二元堆積
-
enqueue 以及 dequeue 時間複雜度為 O(logN)
-
二元堆積樹為完全二元樹
-
搜尋為 O(N)
-
Parent 會大於或等於 Child
// 用陣列實作
export class Entry {
value: string;
priority: number;
constructor(v: string, p: number) {
this.value = v;
this.priority = p;
}
}
export class PQ {
N: number;
storage: Entry[] = [new Entry('', NaN)]; // 為了方便計算讓其從 1 開始儲存
constructor() {
this.N = 0;
}
less(i: number, j: number) {
return this.storage[i].priority < this.storage[j].priority;
}
swap(i: number, j: number) {
const temp = this.storage[i];
this.storage[i] = this.storage[j];
this.storage[j] = temp;
}
swim(child: number) {
while (child > 1 && this.less(Math.floor(child / 2), child)) {
// 父親節點在 child / 2 的商
this.swap(child, Math.floor(child / 2));
child = Math.floor(child / 2);
}
}
sink(parent: number) {
while (2 * parent <= this.N) {
let child = 2 * parent;
if (child < this.N && this.less(child, child + 1)) {
child += 1;
}
if (!this.less(parent, child)) {
break;
}
this.swap(child, parent);
parent = child;
}
}
enqueue(v: string, p: number) {
this.N += 1;
this.storage.push(new Entry(v, p));
this.swim(this.N);
}
dequeue() {
if (this.N === 0 || this.storage.length === 1) {
throw new Error('Queue is empty');
}
const maxEntry = this.storage[1];
this.storage[1] = this.storage[this.N];
this.storage.pop();
this.N -= 1;
this.sink(1);
return maxEntry;
}
}
Enqueue
-
把新元素放到最後一個
-
從剛剛放入的 Child 開始與其 Parent 比較,遞迴至 Parent 大於 Child
Dequeue
-
取出樹的 Root
-
把最後一個 Child 放到 Root
-
移出最後一個元素
-
從 Root 開始確認二元樹的優先順序是否正確
-
sink 裡如果右 child 比左 child 大時就要用右 child 是因為如果直接使用左 child 與 parent 做 swap 會有可能遇到 new parent 會比右 child 大