UNPKG

3.93 kBPlain TextView Raw
1import { ICompare } from "../interface/ICompare";
2import {BasicBinaryTreeNode} from "../tree/basic-binary-tree/BasicBinaryTreeNode";
3
4// tslint:disable-next-line:no-internal-module
5function compareFn<T>(a: T, b: T) {
6 return a <= b;
7}
8
9/**
10 * 左偏树节点
11 */
12export class LeftistTreeNode<T = number> extends BasicBinaryTreeNode<T> {
13 constructor(value: T, private rank: number) {
14 super(value);
15 }
16
17 public set Rank(rank: number){
18 this.rank = rank;
19 }
20
21 public get Rank(){
22 return this.rank;
23 }
24}
25
26/**
27 * 左偏树
28 */
29export class LeftistTree<T>{
30 private root: LeftistTreeNode<T>;
31 private count = 0;
32
33 constructor(private compare: ICompare<T> = compareFn, value?: T) {
34 if (typeof value !== "undefined") {
35 this.root = new LeftistTreeNode(value , 0);
36 this.count = 1;
37 }
38 }
39
40 public get Root(){
41 return this.root;
42 }
43
44 public get Count(){
45 return this.count;
46 }
47
48 public isEmpty() {
49 return !this.root;
50 }
51
52 /**
53 * 修复合并后的节点
54 * @param node
55 */
56 private fixNode(node: LeftistTreeNode<T>) {
57 const left = node.Left as LeftistTreeNode<T>;
58 const right = node.Right as LeftistTreeNode<T>;
59 // 比较左右子树的距离,如果左子树距离小于右子树距离,交换左右子树
60 if (left && right && left.Rank < right.Rank) {
61 const temp = node.Right;
62 node.setRight(node.Left);
63 node.setLeft(temp);
64 }else if (node.Right && !node.Left) {
65 // 如果左子树为空,将右子树置为左子树
66 node.setLeft(node.Right);
67 node.setRight(null);
68 }
69
70 // 修复根节点距离
71 if (node.Right) {
72 node.Rank = (node.Right as LeftistTreeNode<T>).Rank + 1;
73 }else {
74 node.Rank = 0;
75 }
76 }
77
78 /**
79 * 递归合并两个堆
80 * @param root1
81 * @param root2
82 */
83 private _merge(root1: LeftistTreeNode<T>, root2: LeftistTreeNode<T>) {
84 if (!root1) {
85 return root2;
86 }
87 if (!root2) {
88 return root1;
89 }
90 // 比较节点值大小,选择根
91 if (!this.compare(root1.Value , root2.Value)) {
92 const temp = root2;
93 root2 = root1;
94 root1 = temp;
95 }
96 // 递归合并根节点的左子树和另外一个树,然后将其设为根节点的左子树
97 root1.setRight(this._merge(root1.Right as LeftistTreeNode<T>, root2));
98 this.fixNode(root1);
99 return root1;
100 }
101
102 /**
103 * 合并两颗树
104 * @param tree2
105 */
106 public merge(tree2: LeftistTree<T>) {
107 // 如果一棵树为空,以另一个树为根
108 if (!tree2 || tree2.isEmpty()) {
109 return this;
110 }
111 if (!this.root) {
112 this.root = tree2.Root;
113 this.count = tree2.Count;
114 return this;
115 }
116
117 const root1 = this.Root;
118 const root2 = tree2.Root;
119 this.root = this._merge(root1 , root2);
120 this.count += tree2.Count;
121 return this;
122 }
123
124 /**
125 * 获取最值
126 */
127 public findExtremum() {
128 if (!this.root) {
129 return null;
130 }
131 return this.root.Value;
132 }
133
134 /**
135 * 插入节点
136 * @param value
137 */
138 public insert(value: T) {
139 const node = new LeftistTree(this.compare , value);
140 this.merge(node);
141 return node;
142 }
143
144 /**
145 * 取出最值
146 */
147 public deleteExtremum(): T {
148 if (!this.root) {
149 return null;
150 }
151 const value = this.root.Value;
152 // 删除根节点,然后合并左右子树
153 this.root = this._merge(this.root.Left as LeftistTreeNode<T> , this.root.Right as LeftistTreeNode<T>);
154 this.count --;
155 return value;
156 }
157}