js搜索树和优先队列实现

This commit is contained in:
Your Name 2019-07-03 16:49:49 +08:00
parent fba29e983f
commit 2eb39645fc
2 changed files with 347 additions and 0 deletions

View 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();

View 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;
}