優先順位付き待ち行列(Priority queue)(2007/07/23(月) 22:58:42)

優先順位付き待ち行列(Priority queue)とは、普通の待ち行列(キュー)と少し違い、デキュー(取り出す)ときに優先順位の高い(低い)ものから取り出す待ち行列

順次にデータが出てくる場合においてデータをソートしたい場合において、並び替えを行う時にも有効な手段だと思う(汗

実現方法

2分ヒープのデータ構造を用いており、データの追加/削除がO(log n)で行えるのが特徴。添付しているソースでは一次元配列で実現している。

配列番号0が根として
ある配列番号iにおける左側の子はi * 2
右側の子はi * 2 + 1で表す。
ある配列番号iにおける親はi / 2で表す。

また、ヒープは親要素が常に2つの子要素より大きい(またはその逆)の条件を満たさなければならない。(注:2分探索木ではない)

エンキュー(追加)

データの追加は配列の末尾に行い、実現方法で示した方法で追加した値が、親の値より大きい間値と交換する。

デキュー(取り出し)

取り出すデータは配列の先頭(根)。その後根の値を削除するには、配列の末尾の値を根に代入し、ヒープの条件を満たすように、子の値より小さい間値を交換する。

ソース

#include <iostream>
#include <iomanip>
using namespace std;

template <typename  T, int D>
class PriorityQueue{
public:
  PriorityQueue(){
    data = new T[1 << D];
    index = 0;
  }

  ~PriorityQueue(){
    delete data;
  }

  int size(){
    return index;
  }

  void enqueue(T d){
    int i = index, j;
    T tmp;

    data[index++] = d;
    while(i > 0){
      j = i / 2;
      if(data[i] > data[j]){
        tmp = data[i];
        data[i] = data[j];
        data[j] = tmp;
        i = j;
      }
      else break;
    }
  }

  T dequeue(){
    T re = data[0];
    int i = 0, j;
    T tmp;

    data[0] = data[--index];
    while(index > i * 2){
      j = i * 2;
      if(data[j] < data[j + 1])j++;
      if(data[i] < data[j]){
        tmp = data[i];
        data[i] = data[j];
        data[j] = tmp;
        i = j;
      }
      else break;
    }
    return re;
  }

  void show(){
    for(int i = 1, j = 0; j < index; i *= 2){
      for(int k = 0; j < index && k < i; j++, k++){
        cout << setw(3) << data[j] << " ";
      }
      cout << endl;
    }
  }

private:
  T *data;
  int index;
};