diff --git a/javascript/23_tree/binary_tree.js b/javascript/23_tree/binary_tree.js new file mode 100644 index 0000000..f6e201f --- /dev/null +++ b/javascript/23_tree/binary_tree.js @@ -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(); + + + + + diff --git a/javascript/28_heapsort/heap.js b/javascript/28_heapsort/heap.js new file mode 100644 index 0000000..ce42077 --- /dev/null +++ b/javascript/28_heapsort/heap.js @@ -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; +}