UNPKG

4.43 kBJavaScriptView Raw
1import { LinkNode } from "../linklist/LinkNode";
2function compareFn(a, b) {
3 return a <= b;
4}
5export class BinomialHeap {
6 constructor(compare = compareFn) {
7 this.compare = compare;
8 this.count = 0;
9 }
10 get Count() {
11 return this.count;
12 }
13 get Head() {
14 return this.head;
15 }
16 setHead(value) {
17 this.head = new LinkNode({
18 value,
19 degree: 0,
20 });
21 this.count = 1;
22 }
23 clear() {
24 this.head = null;
25 this.count = 0;
26 }
27 isEmpty() {
28 return !this.head;
29 }
30 insert(value) {
31 const heap = new BinomialHeap();
32 heap.setHead(value);
33 const newNode = heap.Head;
34 this.union(heap);
35 return newNode;
36 }
37 deleteExtremum() {
38 if (!this.head) {
39 return null;
40 }
41 const deleteNode = this._findExtremum();
42 if (!deleteNode.minPrev) {
43 this.head = deleteNode.minNode.Next;
44 }
45 else {
46 deleteNode.minPrev.setNext(deleteNode.minNode.Next);
47 }
48 let child = deleteNode.minNode.Value.child;
49 const newHead = child;
50 while (child) {
51 child.Value.parent = null;
52 child = child.Next;
53 }
54 const heap = new BinomialHeap(this.compare);
55 heap.head = newHead;
56 this.union(heap);
57 this.count--;
58 return deleteNode.minNode.Value.value;
59 }
60 _findExtremum() {
61 let next = this.head.Next;
62 let minNode = this.head;
63 let prev = this.head;
64 let minPrev = null;
65 let min = minNode.Value.value;
66 while (next) {
67 if (!this.compare(min, next.Value.value)) {
68 minPrev = prev;
69 minNode = next;
70 min = minNode.Value.value;
71 }
72 prev = next;
73 next = next.Next;
74 }
75 return { minNode, minPrev };
76 }
77 findExtremum() {
78 if (!this.head) {
79 return null;
80 }
81 return this._findExtremum().minNode.Value.value;
82 }
83 union(heap) {
84 if (!heap) {
85 return this;
86 }
87 this.count += heap.Count;
88 let newHead = this.mergeHeaps(heap);
89 if (!newHead) {
90 return this;
91 }
92 this.head = null;
93 heap.head = null;
94 let prev;
95 let curr = newHead;
96 let next = newHead.Next;
97 while (next) {
98 if (next.Value.degree !== curr.Value.degree ||
99 (next.Next && next.Next.Value.degree === curr.Value.degree)) {
100 prev = curr;
101 curr = next;
102 }
103 else {
104 if (this.compare(curr.Value.value, next.Value.value)) {
105 curr.setNext(next.Next);
106 this.link(curr, next);
107 }
108 else {
109 if (!prev) {
110 newHead = next;
111 }
112 else {
113 prev.setNext(next);
114 }
115 this.link(next, curr);
116 curr = next;
117 }
118 }
119 next = curr.Next;
120 }
121 this.head = newHead;
122 return this;
123 }
124 link(tomerge, frommerge) {
125 frommerge.setNext(tomerge.Value.child);
126 frommerge.Value.parent = tomerge;
127 tomerge.Value.child = frommerge;
128 tomerge.Value.degree++;
129 }
130 mergeHeaps(heap) {
131 let thisHead = this.head;
132 let thatHead = heap.Head;
133 if (!thisHead) {
134 return heap.head;
135 }
136 if (!thatHead) {
137 return this.head;
138 }
139 let newHead;
140 if (thisHead.Value.degree <= thatHead.Value.degree) {
141 newHead = this.head;
142 thisHead = thisHead.Next;
143 }
144 else {
145 newHead = heap.head;
146 thatHead = thatHead.Next;
147 }
148 let temp = newHead;
149 while (thisHead && thatHead) {
150 if (thisHead.Value.degree <= thatHead.Value.degree) {
151 temp.setNext(thisHead);
152 thisHead = thisHead.Next;
153 }
154 else {
155 temp.setNext(thatHead);
156 thatHead = thatHead.Next;
157 }
158 temp = temp.Next;
159 }
160 temp.setNext(thisHead ? thisHead : thatHead);
161 return newHead;
162 }
163}