Skip to content

Commit dc206af

Browse files
Merge pull request #350 from Tarhyru/master
js搜索树和优先队列的堆实现
2 parents 8b2548e + 2eb3964 commit dc206af

File tree

2 files changed

+347
-0
lines changed

2 files changed

+347
-0
lines changed

javascript/23_tree/binary_tree.js

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
class Node {
2+
constructor(value) {
3+
this.value = value;
4+
this.left = null;
5+
this.right = null;
6+
}
7+
}
8+
/**
9+
* 搜索二叉树
10+
* 允许重复值添加
11+
* 实现有点弯弯绕
12+
*/
13+
class SearchTree {
14+
constructor() {
15+
this.root = null;
16+
}
17+
insert(num) {
18+
let node = new Node(num);
19+
if (this.root === null) {
20+
this.root = node;
21+
return
22+
}
23+
let prent = this.getPrev(num);
24+
if (num < prent.value) {
25+
prent.left = node;
26+
} else {
27+
prent.right = node;
28+
}
29+
30+
}
31+
remove(num) {
32+
let point = this.root;
33+
let prent = null;
34+
let tree = this;
35+
36+
let res = null;
37+
while (true) {
38+
if (point.left) {
39+
if (num < point.left.value || num < point.value) {
40+
prent = point;
41+
point = point.left;
42+
continue
43+
}
44+
}
45+
if (point.right) {
46+
if (num >= point.right.value || num >= point.value) {
47+
if (num === point.value) {
48+
delMethod(point, prent);
49+
if (prent === null) {
50+
point = this.root;
51+
} else {
52+
prent = prent;
53+
point = prent.right;
54+
}
55+
res = true;
56+
continue
57+
}
58+
prent = point;
59+
point = point.right;
60+
continue
61+
}
62+
}
63+
if (point.value === num) {
64+
res = true;
65+
delMethod(point, prent);
66+
}
67+
break;
68+
}
69+
return res;
70+
function delMethod(delNode, parent) {
71+
let p = delNode; // p指向要删除的节点
72+
let pp = parent; // pp记录的是p的父节点
73+
74+
// 要删除的节点有两个子节点
75+
if (p.left != null && p.right != null) { // 查找右子树中最小节点
76+
let minP = p.right;
77+
let minPP = p; // minPP表示minP的父节点
78+
while (minP.left != null) {
79+
minPP = minP;
80+
minP = minP.left;
81+
}
82+
p.value = minP.value; // 将minP的数据替换到p中
83+
p = minP; // 下面就变成了删除minP了
84+
pp = minPP;
85+
}
86+
87+
// 删除节点是叶子节点或者仅有一个子节点
88+
let child; // p的子节点
89+
if (p.left != null) child = p.left;
90+
else if (p.right != null) child = p.right;
91+
else child = null;
92+
93+
if (pp == null) {
94+
tree.root = child
95+
}
96+
else if (pp.left == p) {
97+
pp.left = child;
98+
}
99+
else {
100+
pp.right = child;
101+
}
102+
}
103+
104+
}
105+
//中序遍历
106+
print() {
107+
let point = this.root;
108+
if (point) {
109+
printAll(point.left)
110+
console.log(point.value);
111+
printAll(point.right)
112+
}
113+
function printAll(point) {
114+
if (point == null) {
115+
return
116+
}
117+
printAll(point.left);
118+
console.log(point.value);
119+
printAll(point.right)
120+
}
121+
}
122+
find(num) {
123+
if (this.root === null) {
124+
this.root = node;
125+
return
126+
}
127+
return this.getPrev(num, true);
128+
}
129+
//添加和查找的公用部分
130+
getPrev(num, find = false) {
131+
let point = this.root;
132+
let res = [];
133+
while (true) {
134+
if (point.left) {
135+
if (num < point.left.value || num < point.value) {
136+
point = point.left
137+
continue
138+
}
139+
}
140+
141+
if (point.right) {
142+
if (num >= point.right.value || num >= point.value) {
143+
//搜索时如果有多个值则缓存
144+
if (find && num === point.value) {
145+
res.push(point.value);
146+
}
147+
point = point.right;
148+
continue
149+
}
150+
}
151+
//如果是搜索
152+
if (find) {
153+
if (point.value === num) {
154+
res.push(point.value);
155+
}
156+
157+
if (res.length === 0) {
158+
return null
159+
}
160+
161+
if (res.length === 1) {
162+
return res[0];
163+
}
164+
165+
return res;
166+
}
167+
//如果是添加 返回的是应该添加的那各节点的父节点
168+
return point;
169+
}
170+
}
171+
}
172+
173+
174+
175+
function baseTest() {
176+
let searchTree = new SearchTree();
177+
console.log('step 1:')
178+
searchTree.insert(4);
179+
searchTree.insert(1);
180+
searchTree.insert(2);
181+
searchTree.insert(5);
182+
183+
searchTree.print(); //1 2 4 5
184+
console.log('step 2:')
185+
console.log('5', searchTree.find(5)) //5
186+
console.log('null:', searchTree.find(6)) //null
187+
searchTree.insert(5);
188+
searchTree.insert(5);
189+
console.log('5,5,5:', searchTree.find(5))
190+
191+
192+
}
193+
//删除测试
194+
function delTest() {
195+
let searchTree = new SearchTree();
196+
console.log('add: 4 1 2 5 ')
197+
searchTree.insert(4);
198+
searchTree.insert(1);
199+
searchTree.insert(2);
200+
searchTree.insert(5);
201+
searchTree.print(); //1 2 4 5
202+
//console.log('del 3 null:', searchTree.remove(3));
203+
console.log('del 1 true:', searchTree.remove(1));
204+
// console.log('print 2 4 5:')
205+
// searchTree.print();
206+
// console.log('del 4 root true:', searchTree.remove(4));
207+
// console.log('print 2 5:')
208+
// searchTree.print();
209+
// console.log('add: 3 7 1 5 5 5 ')
210+
// searchTree.insert(3);
211+
// searchTree.insert(7);
212+
// searchTree.insert(1);
213+
// searchTree.insert(5);
214+
// searchTree.insert(5);
215+
// searchTree.insert(5);
216+
// console.log('print: 1 2 3 5 5 5 5 7 ')
217+
// searchTree.print();
218+
// console.log('del 5 true:', searchTree.remove(5));
219+
// console.log('print: 1 2 3 7 ')
220+
// searchTree.print();
221+
}
222+
223+
delTest();
224+
225+
226+
227+
228+

javascript/28_heapsort/heap.js

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/**
2+
* 优先队列的 堆实现
3+
*/
4+
class HeapNode {
5+
constructor(num, item) {
6+
this.sortNum = num;
7+
this.content = item;
8+
}
9+
}
10+
11+
class Heap {
12+
constructor(arr = []) {
13+
this.PRIVATE = {
14+
swap(arr, i, j) {
15+
let temp = arr[i]
16+
arr[i] = arr[j]
17+
arr[j] = temp
18+
},
19+
//从point往下 堆化
20+
heapify(point = 1) {
21+
let { swap, store } = this;
22+
while (true) {
23+
let lPoint = point * 2;
24+
let rPoint = point * 2 + 1;
25+
if (store[lPoint] && store[point].sortNum < store[lPoint].sortNum) {
26+
swap(store, point, lPoint);
27+
point = lPoint;
28+
continue
29+
}
30+
if (store[rPoint] && store[point].sortNum < store[rPoint].sortNum) {
31+
swap(store, point, rPoint);
32+
point = rPoint;
33+
continue
34+
}
35+
break;
36+
}
37+
38+
},
39+
store: [null].concat(arr)
40+
}
41+
//建堆
42+
//从最后一个非子叶节点遍历
43+
for (let i = (this.PRIVATE.store.length / 2 | 0); i > 1; i--) {
44+
this.PRIVATE.heapify(i);
45+
}
46+
47+
}
48+
insert(node) {
49+
let store = this.PRIVATE.store;
50+
let HeapUtil = this.PRIVATE;
51+
store.push(node);
52+
53+
let point = store.length - 1;
54+
let sub = point / 2 | 0;
55+
while (sub > 0 && store[point].sortNum > store[sub].sortNum) { // 自下往上堆化
56+
HeapUtil.swap(store, point, sub); // swap()函数作用:交换下标为i和i/2的两个元素
57+
point = sub;
58+
sub = sub / 2 | 0;
59+
}
60+
}
61+
getMax() {
62+
let store = this.PRIVATE.store;
63+
let point = store.length - 1;
64+
if (point === 0) {
65+
return null;
66+
}
67+
let HeapUtil = this.PRIVATE;
68+
//最大与末尾元素交换
69+
HeapUtil.swap(store, point, 1);
70+
let max = store.pop();
71+
HeapUtil.heapify();
72+
return max;
73+
}
74+
75+
}
76+
77+
function HeapTest() {
78+
let maxHeap = new Heap();
79+
console.log('偶数个')
80+
maxHeap.insert(new HeapNode(2, 'c'))
81+
maxHeap.insert(new HeapNode(1, 'c'))
82+
maxHeap.insert(new HeapNode(7, 'a'))
83+
maxHeap.insert(new HeapNode(4, 'c'))
84+
console.log('check:', isHeapArr(maxHeap.PRIVATE.store));
85+
console.log('奇数个')
86+
maxHeap.insert(new HeapNode(5, 'b'))
87+
maxHeap.insert(new HeapNode(6, 'c'))
88+
maxHeap.insert(new HeapNode(10, 'a'))
89+
console.log('check:', isHeapArr(maxHeap.PRIVATE.store));
90+
console.log('获取最大值:', maxHeap.getMax());
91+
console.log('check:', isHeapArr(maxHeap.PRIVATE.store));
92+
console.log('获取最大值:', maxHeap.getMax());
93+
console.log('check:', isHeapArr(maxHeap.PRIVATE.store));
94+
95+
}
96+
function createTest() {
97+
console.log('随机创建测试:')
98+
let arr = [];
99+
let i = 0
100+
while (i <= 10) {
101+
const num = Math.floor(Math.random() * 100)
102+
arr.push(new HeapNode(num, i))
103+
i++
104+
}
105+
let heap = new Heap(arr);
106+
console.log('check:', isHeapArr(heap.PRIVATE.store))
107+
}
108+
109+
function isHeapArr(arr) {
110+
for (let i = 1; i < arr.length; i++) {
111+
let p = arr[i];
112+
let l = arr[i * 2];
113+
let r = arr[i * 2 + 1];
114+
if (l > p || r > p) {
115+
return false;
116+
}
117+
}
118+
return true;
119+
}

0 commit comments

Comments
 (0)