js搜索树和优先队列实现
This commit is contained in:
parent
fba29e983f
commit
2eb39645fc
228
javascript/23_tree/binary_tree.js
Normal file
228
javascript/23_tree/binary_tree.js
Normal file
@ -0,0 +1,228 @@
|
||||
class Node {
|
||||
constructor(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 搜索二叉树
|
||||
* 允许重复值添加
|
||||
* 实现有点弯弯绕
|
||||
*/
|
||||
class SearchTree {
|
||||
constructor() {
|
||||
this.root = null;
|
||||
}
|
||||
insert(num) {
|
||||
let node = new Node(num);
|
||||
if (this.root === null) {
|
||||
this.root = node;
|
||||
return
|
||||
}
|
||||
let prent = this.getPrev(num);
|
||||
if (num < prent.value) {
|
||||
prent.left = node;
|
||||
} else {
|
||||
prent.right = node;
|
||||
}
|
||||
|
||||
}
|
||||
remove(num) {
|
||||
let point = this.root;
|
||||
let prent = null;
|
||||
let tree = this;
|
||||
|
||||
let res = null;
|
||||
while (true) {
|
||||
if (point.left) {
|
||||
if (num < point.left.value || num < point.value) {
|
||||
prent = point;
|
||||
point = point.left;
|
||||
continue
|
||||
}
|
||||
}
|
||||
if (point.right) {
|
||||
if (num >= point.right.value || num >= point.value) {
|
||||
if (num === point.value) {
|
||||
delMethod(point, prent);
|
||||
if (prent === null) {
|
||||
point = this.root;
|
||||
} else {
|
||||
prent = prent;
|
||||
point = prent.right;
|
||||
}
|
||||
res = true;
|
||||
continue
|
||||
}
|
||||
prent = point;
|
||||
point = point.right;
|
||||
continue
|
||||
}
|
||||
}
|
||||
if (point.value === num) {
|
||||
res = true;
|
||||
delMethod(point, prent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
function delMethod(delNode, parent) {
|
||||
let p = delNode; // p指向要删除的节点
|
||||
let pp = parent; // pp记录的是p的父节点
|
||||
|
||||
// 要删除的节点有两个子节点
|
||||
if (p.left != null && p.right != null) { // 查找右子树中最小节点
|
||||
let minP = p.right;
|
||||
let minPP = p; // minPP表示minP的父节点
|
||||
while (minP.left != null) {
|
||||
minPP = minP;
|
||||
minP = minP.left;
|
||||
}
|
||||
p.value = minP.value; // 将minP的数据替换到p中
|
||||
p = minP; // 下面就变成了删除minP了
|
||||
pp = minPP;
|
||||
}
|
||||
|
||||
// 删除节点是叶子节点或者仅有一个子节点
|
||||
let child; // p的子节点
|
||||
if (p.left != null) child = p.left;
|
||||
else if (p.right != null) child = p.right;
|
||||
else child = null;
|
||||
|
||||
if (pp == null) {
|
||||
tree.root = child
|
||||
}
|
||||
else if (pp.left == p) {
|
||||
pp.left = child;
|
||||
}
|
||||
else {
|
||||
pp.right = child;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//中序遍历
|
||||
print() {
|
||||
let point = this.root;
|
||||
if (point) {
|
||||
printAll(point.left)
|
||||
console.log(point.value);
|
||||
printAll(point.right)
|
||||
}
|
||||
function printAll(point) {
|
||||
if (point == null) {
|
||||
return
|
||||
}
|
||||
printAll(point.left);
|
||||
console.log(point.value);
|
||||
printAll(point.right)
|
||||
}
|
||||
}
|
||||
find(num) {
|
||||
if (this.root === null) {
|
||||
this.root = node;
|
||||
return
|
||||
}
|
||||
return this.getPrev(num, true);
|
||||
}
|
||||
//添加和查找的公用部分
|
||||
getPrev(num, find = false) {
|
||||
let point = this.root;
|
||||
let res = [];
|
||||
while (true) {
|
||||
if (point.left) {
|
||||
if (num < point.left.value || num < point.value) {
|
||||
point = point.left
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if (point.right) {
|
||||
if (num >= point.right.value || num >= point.value) {
|
||||
//搜索时如果有多个值则缓存
|
||||
if (find && num === point.value) {
|
||||
res.push(point.value);
|
||||
}
|
||||
point = point.right;
|
||||
continue
|
||||
}
|
||||
}
|
||||
//如果是搜索
|
||||
if (find) {
|
||||
if (point.value === num) {
|
||||
res.push(point.value);
|
||||
}
|
||||
|
||||
if (res.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (res.length === 1) {
|
||||
return res[0];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
//如果是添加 返回的是应该添加的那各节点的父节点
|
||||
return point;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function baseTest() {
|
||||
let searchTree = new SearchTree();
|
||||
console.log('step 1:')
|
||||
searchTree.insert(4);
|
||||
searchTree.insert(1);
|
||||
searchTree.insert(2);
|
||||
searchTree.insert(5);
|
||||
|
||||
searchTree.print(); //1 2 4 5
|
||||
console.log('step 2:')
|
||||
console.log('5', searchTree.find(5)) //5
|
||||
console.log('null:', searchTree.find(6)) //null
|
||||
searchTree.insert(5);
|
||||
searchTree.insert(5);
|
||||
console.log('5,5,5:', searchTree.find(5))
|
||||
|
||||
|
||||
}
|
||||
//删除测试
|
||||
function delTest() {
|
||||
let searchTree = new SearchTree();
|
||||
console.log('add: 4 1 2 5 ')
|
||||
searchTree.insert(4);
|
||||
searchTree.insert(1);
|
||||
searchTree.insert(2);
|
||||
searchTree.insert(5);
|
||||
searchTree.print(); //1 2 4 5
|
||||
//console.log('del 3 null:', searchTree.remove(3));
|
||||
console.log('del 1 true:', searchTree.remove(1));
|
||||
// console.log('print 2 4 5:')
|
||||
// searchTree.print();
|
||||
// console.log('del 4 root true:', searchTree.remove(4));
|
||||
// console.log('print 2 5:')
|
||||
// searchTree.print();
|
||||
// console.log('add: 3 7 1 5 5 5 ')
|
||||
// searchTree.insert(3);
|
||||
// searchTree.insert(7);
|
||||
// searchTree.insert(1);
|
||||
// searchTree.insert(5);
|
||||
// searchTree.insert(5);
|
||||
// searchTree.insert(5);
|
||||
// console.log('print: 1 2 3 5 5 5 5 7 ')
|
||||
// searchTree.print();
|
||||
// console.log('del 5 true:', searchTree.remove(5));
|
||||
// console.log('print: 1 2 3 7 ')
|
||||
// searchTree.print();
|
||||
}
|
||||
|
||||
delTest();
|
||||
|
||||
|
||||
|
||||
|
||||
|
119
javascript/28_heapsort/heap.js
Normal file
119
javascript/28_heapsort/heap.js
Normal file
@ -0,0 +1,119 @@
|
||||
/**
|
||||
* 优先队列的 堆实现
|
||||
*/
|
||||
class HeapNode {
|
||||
constructor(num, item) {
|
||||
this.sortNum = num;
|
||||
this.content = item;
|
||||
}
|
||||
}
|
||||
|
||||
class Heap {
|
||||
constructor(arr = []) {
|
||||
this.PRIVATE = {
|
||||
swap(arr, i, j) {
|
||||
let temp = arr[i]
|
||||
arr[i] = arr[j]
|
||||
arr[j] = temp
|
||||
},
|
||||
//从point往下 堆化
|
||||
heapify(point = 1) {
|
||||
let { swap, store } = this;
|
||||
while (true) {
|
||||
let lPoint = point * 2;
|
||||
let rPoint = point * 2 + 1;
|
||||
if (store[lPoint] && store[point].sortNum < store[lPoint].sortNum) {
|
||||
swap(store, point, lPoint);
|
||||
point = lPoint;
|
||||
continue
|
||||
}
|
||||
if (store[rPoint] && store[point].sortNum < store[rPoint].sortNum) {
|
||||
swap(store, point, rPoint);
|
||||
point = rPoint;
|
||||
continue
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
},
|
||||
store: [null].concat(arr)
|
||||
}
|
||||
//建堆
|
||||
//从最后一个非子叶节点遍历
|
||||
for (let i = (this.PRIVATE.store.length / 2 | 0); i > 1; i--) {
|
||||
this.PRIVATE.heapify(i);
|
||||
}
|
||||
|
||||
}
|
||||
insert(node) {
|
||||
let store = this.PRIVATE.store;
|
||||
let HeapUtil = this.PRIVATE;
|
||||
store.push(node);
|
||||
|
||||
let point = store.length - 1;
|
||||
let sub = point / 2 | 0;
|
||||
while (sub > 0 && store[point].sortNum > store[sub].sortNum) { // 自下往上堆化
|
||||
HeapUtil.swap(store, point, sub); // swap()函数作用:交换下标为i和i/2的两个元素
|
||||
point = sub;
|
||||
sub = sub / 2 | 0;
|
||||
}
|
||||
}
|
||||
getMax() {
|
||||
let store = this.PRIVATE.store;
|
||||
let point = store.length - 1;
|
||||
if (point === 0) {
|
||||
return null;
|
||||
}
|
||||
let HeapUtil = this.PRIVATE;
|
||||
//最大与末尾元素交换
|
||||
HeapUtil.swap(store, point, 1);
|
||||
let max = store.pop();
|
||||
HeapUtil.heapify();
|
||||
return max;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function HeapTest() {
|
||||
let maxHeap = new Heap();
|
||||
console.log('偶数个')
|
||||
maxHeap.insert(new HeapNode(2, 'c'))
|
||||
maxHeap.insert(new HeapNode(1, 'c'))
|
||||
maxHeap.insert(new HeapNode(7, 'a'))
|
||||
maxHeap.insert(new HeapNode(4, 'c'))
|
||||
console.log('check:', isHeapArr(maxHeap.PRIVATE.store));
|
||||
console.log('奇数个')
|
||||
maxHeap.insert(new HeapNode(5, 'b'))
|
||||
maxHeap.insert(new HeapNode(6, 'c'))
|
||||
maxHeap.insert(new HeapNode(10, 'a'))
|
||||
console.log('check:', isHeapArr(maxHeap.PRIVATE.store));
|
||||
console.log('获取最大值:', maxHeap.getMax());
|
||||
console.log('check:', isHeapArr(maxHeap.PRIVATE.store));
|
||||
console.log('获取最大值:', maxHeap.getMax());
|
||||
console.log('check:', isHeapArr(maxHeap.PRIVATE.store));
|
||||
|
||||
}
|
||||
function createTest() {
|
||||
console.log('随机创建测试:')
|
||||
let arr = [];
|
||||
let i = 0
|
||||
while (i <= 10) {
|
||||
const num = Math.floor(Math.random() * 100)
|
||||
arr.push(new HeapNode(num, i))
|
||||
i++
|
||||
}
|
||||
let heap = new Heap(arr);
|
||||
console.log('check:', isHeapArr(heap.PRIVATE.store))
|
||||
}
|
||||
|
||||
function isHeapArr(arr) {
|
||||
for (let i = 1; i < arr.length; i++) {
|
||||
let p = arr[i];
|
||||
let l = arr[i * 2];
|
||||
let r = arr[i * 2 + 1];
|
||||
if (l > p || r > p) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
Loading…
Reference in New Issue
Block a user