C言語でプライオリティーキュー構造体
C言語で関数ポインタを使ってカプセル化に挑戦してみた
でやってみたカプセル化にならって、優先順位付きキューを実装してみました。
int型を扱うシンプルな作りをしていて、構造体を作るときに渡す列挙体の値で優先順位を昇順か降順か選択できます。また、ヒープに使う領域が不足したらメモリ領域を自動で伸張する作りになっています。1万でも10万でも要素を入れちゃえる。
また、ヒープを操作するときに、ノード操作のためにルートノードの番号は1なので、仕様する配列は0番目を使わないか、インデクス操作をごにょごにょするか、普通はどちらかをすると思うんですが、今回はC言語の配列の添え字が1から始まるように工夫してみました。
int a[10]; int p = a-1;
これで配列の添え字が1スタートになりました。
そんな感じです.てきとう.
#include<stdio.h> #include<stdlib.h> // // utility // void swap(int* p, int* q) { int swp = *q; *q = *p; *p = swp; } // // data structure // enum pqueue_order { PQUEUE_ORDER_DESC = -1, PQUEUE_ORDER_ASC = 1 }; typedef struct pqueue { int* heap; int reserved; // reserved memory size int size; // heap size int (*push)(struct pqueue*, int); int (*pop)(struct pqueue*); int (*empty)(struct pqueue*); enum pqueue_order ord; } pqueue_t; // // methods // int pqueue_push(pqueue_t* self, int n) { int node; int *heap; // ordering n *= self->ord; // expand heap size if stervation occured if (self->size >= self->reserved) { self->reserved = self->reserved * 2; self->heap = realloc(self->heap, self->reserved * sizeof(int)); } heap = self->heap - 1; // index start from 1 heap[++self->size] = n; // up-heap for (node = self->size; heap[node] < heap[node / 2] && node != 1; node/=2) swap(heap + node, heap + node/2); return 0; } int pqueue_pop(pqueue_t* self) { int ret; int left, rght; int node, downto; int *heap = self->heap - 1; // index start from 1 if (self->size == 0) return -1; // de-ordering ret = heap[1] * self->ord; // down-heap heap[1] = heap[(self->size)--]; for (node = 1, downto = -1; node != downto; swap(heap + node, heap + downto), node = downto) { int left = node*2 ; int rght = node*2 + 1; downto = node; // downto = min(parent, left child, right child) if (left <= self->size && heap[left] < heap[downto]) downto = left; if (rght <= self->size && heap[rght] < heap[downto]) downto = rght; } return ret; } int pqueue_empty(pqueue_t* self) { return self->size == 0; } // // constructor // pqueue_t* create_pqueue(enum pqueue_order ord) { pqueue_t *p = malloc(sizeof(pqueue_t)); p->size = 0; p->reserved = 2; p->heap = malloc(p->reserved * sizeof(int)); p->ord = ord; p->push = pqueue_push; p->pop = pqueue_pop; p->empty = pqueue_empty; return p; } // // destructor // void dispose_pqueue(pqueue_t* q) { free(q->heap); free(q); } int test() { pqueue_t *q; q = create_pqueue(PQUEUE_ORDER_DESC); q->push(q, 5); q->push(q, 1); q->push(q, 8); q->push(q, 9); q->push(q, -1); while (!q->empty(q)) printf("%d%c", q->pop(q), 10); dispose_pqueue(q); return 0; } int main() { test(); return 0; }
実行結果
$ ./a.out 9 8 5 1 -1