UNPKG

6.33 kBPlain TextView Raw
1import { ICompare } from "../interface/ICompare";
2import { LinkNode } from "../linklist/LinkNode";
3
4export interface HeapNode<T>{
5 value: T;
6 degree: number;
7 child ?: LinkNode<HeapNode<T>>;
8 parent ?: LinkNode<HeapNode<T>>;
9}
10
11function compareFn<T>(a: T, b: T){
12 return a <= b;
13}
14
15/**
16 * 二项堆
17 */
18export class BinomialHeap<T = number>{
19 private head: LinkNode<HeapNode<T>>;
20 private count = 0;
21 constructor(private compare: ICompare<T> = compareFn){
22 }
23
24 get Count(){
25 return this.count;
26 }
27
28 get Head(){
29 return this.head;
30 }
31
32 private setHead(value: T){
33 this.head = new LinkNode<HeapNode<T>>({
34 value,
35 degree: 0,
36 });
37 this.count = 1;
38 }
39
40 public clear(){
41 this.head = null;
42 this.count = 0;
43 }
44
45 public isEmpty(){
46 return !this.head;
47 }
48
49 /**
50 * 插入节点
51 * @param value
52 */
53 public insert(value: T){
54 /**
55 * 创建新节点为一个新堆,然后合并该堆到当前堆
56 */
57 const heap = new BinomialHeap<T>();
58 heap.setHead(value);
59 const newNode = heap.Head;
60 this.union(heap);
61 return newNode;
62 }
63
64 /**
65 * 取最值
66 */
67 public deleteExtremum(){
68 if (!this.head){
69 return null;
70 }
71 const deleteNode = this._findExtremum();
72 if (!deleteNode.minPrev){
73 this.head = deleteNode.minNode.Next;
74 }else{
75 deleteNode.minPrev.setNext(deleteNode.minNode.Next);
76 }
77 let child = deleteNode.minNode.Value.child;
78 const newHead = child;
79 // NOTE:为什么反转
80 // 删除节点的子节点的父级引用,然后重新合并
81 while (child){
82 child.Value.parent = null;
83 child = child.Next;
84 }
85 const heap = new BinomialHeap<T>(this.compare);
86 heap.head = newHead;
87 // count为0;
88 this.union(heap);
89 this.count --;
90 return deleteNode.minNode.Value.value;
91 }
92
93 /**
94 * 查找最值
95 */
96 private _findExtremum(){
97 let next = this.head.Next;
98 let minNode = this.head;
99 let prev: LinkNode<HeapNode<T>> = this.head;
100 let minPrev: LinkNode<HeapNode<T>> = null;
101 let min = minNode.Value.value;
102 // 查找第一行 最小值
103 while (next){
104 if (!this.compare(min, next.Value.value)){
105 minPrev = prev;
106 minNode = next;
107 min = minNode.Value.value;
108 }
109 prev = next;
110 next = next.Next;
111 }
112 return {minNode, minPrev};
113 }
114
115 /**
116 * 查找最值
117 * @returns T|null
118 */
119 public findExtremum(){
120 if (!this.head){
121 return null;
122 }
123 return this._findExtremum().minNode.Value.value;
124 }
125
126 /**
127 * 合并指定堆到当前堆
128 * @param heap
129 */
130 public union(heap: BinomialHeap<T>){
131 /**
132 * 1、将两个堆串联成新链表
133 * 2、从头到尾合并两个堆(合并度数相同的)
134 */
135 if (!heap){
136 return this;
137 }
138 this.count += heap.Count;
139 let newHead = this.mergeHeaps(heap);
140 if (!newHead) {
141 return this;
142 }
143 this.head = null;
144 heap.head = null;
145
146 let prev: LinkNode<HeapNode<T>>;
147 let curr = newHead;
148 let next = newHead.Next;
149 /**
150 * 判断两个度数是否相同,相同合并
151 */
152 while (next){
153 // 节点度数不同,或者三个度数相同
154 if (next.Value.degree !== curr.Value.degree ||
155 (next.Next && next.Next.Value.degree === curr.Value.degree)){
156 prev = curr;
157 curr = next;
158 }else{
159 if (this.compare( curr.Value.value , next.Value.value)){
160 //
161 curr.setNext(next.Next);
162 this.link(curr, next);
163 // curr游标不走,判断curr和next.next
164 }else{
165 // 并且第二个key小于第一个key
166 if (!prev){
167 // 第一个和第二个相同度
168 newHead = next;
169 }else{
170 // 不是第一个和第二个元素
171 prev.setNext(next);
172 }
173 this.link(next, curr);
174 curr = next;
175 // curr游标走动,判断next和next.next;
176 }
177 }
178 // 不能取next ,next已经合并
179 next = curr.Next;
180 }
181 this.head = newHead;
182 return this;
183 }
184
185 /**
186 * 合并两个节点
187 * @param tomerge
188 * @param frommerge
189 */
190 private link(tomerge: LinkNode<HeapNode<T>>, frommerge: LinkNode<HeapNode<T>>){
191 frommerge.setNext(tomerge.Value.child);
192 frommerge.Value.parent = tomerge;
193 tomerge.Value.child = frommerge;
194 tomerge.Value.degree ++;
195 }
196
197 /**
198 * 根据度数排列合并两个堆
199 * @param heap
200 */
201 private mergeHeaps(heap: BinomialHeap<T>){
202 let thisHead = this.head;
203 let thatHead = heap.Head;
204 if (!thisHead) {
205 return heap.head;
206 }
207 if (!thatHead) {
208 return this.head;
209 }
210 let newHead: LinkNode<HeapNode<T>>;
211 // 比较两个堆头节点度数,以度数小的节点为头节点
212 if (thisHead.Value.degree <= thatHead.Value.degree){
213 newHead = this.head;
214 thisHead = thisHead.Next;
215 }else{
216 newHead = heap.head;
217 thatHead = thatHead.Next;
218 }
219 let temp = newHead;
220 // 循环两个堆,按读书排列
221 while (thisHead && thatHead) {
222 if (thisHead.Value.degree <= thatHead.Value.degree) {
223 temp.setNext(thisHead);
224 thisHead = thisHead.Next;
225 }else{
226 temp.setNext(thatHead);
227 thatHead = thatHead.Next;
228 }
229 temp = temp.Next;
230 }
231 temp.setNext(thisHead ? thisHead : thatHead);
232 return newHead;
233 }
234}