1. 二叉搜索树(Binary Search Tree)
<待补充>
class Node {
constructor(key) {
this.key = key;
this.left = null;
this.right = null;
}
}
const compareFn = (a, b) => {
if(a < b) {
return -1
} else if(a > b) {
return 1;
} else {
return 0;
}
}
compareFn.LESS_THAN = -1;
compareFn.MORE_THAN = 1;
compareFn.EQ = 0;
export class BinarySearchTree {
constructor(compare = compareFn) {
this.compare = compare;
this.root = null;
}
/**
* @description:
* @param {*} key
* @return {*}
*/
insert(key) {
const node = new Node(key);
if(!this.root) {
this.root = node;
return true;
} else {
return this.insetNode(node, this.root)
}
}
/**
* @description:
* @param {*} node
* @param {*} parent
* @return {*}
*/
insetNode(node, parent) {
const compareRes = this.compare(node.key, parent.key);
if(compareRes === compareFn.LESS_THAN) {
if(!parent.left) {
parent.left = node;
return true;
} else {
return this.insetNode(node, parent.left);
}
} else if(compareRes === compareFn.MORE_THAN) {
if(!parent.right) {
parent.right = node;
return true;
} else {
return this.insetNode(node, parent.right);
}
} else {
return false;
}
}
/**
* @description:
* @param {*} key
* @return {*}
*/
remove(key) {
if(!this.root) {
return null;
}
const node = this.root;
if(this.compare(key, node.key) === compareFn.EQ) {
this.root = null;
return node;
}
const res = this.removeNode(key, node);
return res.deletedNode;
}
removeNode(key, current) {
const compareRes = this.compare(key, current.key);
if(compareRes === compareFn.LESS_THAN) {
if(!current.left) {
return null;
} else {
const res = this.removeNode(key, current.left);
if(res.needLinked) {
current.left = res.linkedNode;
}
return {deletedNode: res.deletedNode };
}
} else if(compareRes === compareFn.MORE_THAN) {
if(!current.right) {
return null;
} else {
const res = this.removeNode(key, current.right);
if(res.needLinked) {
current.right = res.linkedNode;
}
return {deletedNode: res.deletedNode };
}
} else {
const left = current.left;
const right = current.right;
if(!left && !right) {
return {deletedNode: current, linkedNode: null, needLinked: true};
} else if(left && !right) {
return {deletedNode: current, linkedNode: left, needLinked: true};
} else if(!left && right) {
return {deletedNode: current, linkedNode: right, needLinked: true};
} else {
const tempNode = {...current};
const minNode = this.findMinNode(right);
current.key = minNode.key;
const res = this.removeNode(minNode.key, right);
if(res.needLinked) {
current.right = res.linkedNode;
}
return { deletedNode: tempNode };
}
}
}
deepth() {
if(!this.root) {
return null;
}
return this.searchDeepth(this.root);
}
searchDeepth(current) {
if(!current.left && !current.right) {
return 0;
}
if(current.left && !current.right) {
return this.searchDeepth(current.left) + 1;
} else if(!current.left && current.right) {
return this.searchDeepth(current.right) + 1;
} else if(current.left && current.right) {
return Math.max(this.searchDeepth(current.left), this.searchDeepth(current.right)) + 1;
}
}
find(key) {
return this.findNode(key, this.root)
}
findNode(key, current) {
if(!current) {
return null;
}
const compareRes = this.compare(key, current.key);
if(compareRes === compareFn.LESS_THAN) {
return this.findNode(key, current.left);
} else if(compareRes === compareFn.MORE_THAN) {
return this.findNode(key, current.right);
} else {
return current;
}
}
findMinNode(current) {
if(!current){
return null;
}
while(current.left) {
current = current.left;
}
return current;
}
max() {
if(!this.root) {
return undefined;
}
let current = this.root;
while(current.right) {
current = current.right;
}
return current.key;
}
min() {
if(!this.root) {
return undefined;
}
let current = this.root;
while(current.left) {
current = current.left;
}
return current.key;
}
inorder() {
const keys = [];
this.inorderTraverse(this.root, keys);
console.log(keys.toString());
}
inorderTraverse(current, keys) {
if(!current) {
return false;
}
this.inorderTraverse(current.left, keys);
keys.push(current.key);
this.inorderTraverse(current.right, keys);
}
preorder() {
const keys = [];
this.preorderTraverse(this.root, keys);
console.log(keys.toString());
}
preorderTraverse(current, keys) {
if(!current) {
return false;
}
keys.push(current.key);
this.preorderTraverse(current.left, keys);
this.preorderTraverse(current.right, keys);
}
postorder() {
const keys = [];
this.postorderTraverse(this.root, keys);
console.log(keys.toString());
}
postorderTraverse(current, keys) {
if(!current) {
return false;
}
this.postorderTraverse(current.left, keys);
this.postorderTraverse(current.right, keys);
keys.push(current.key);
}
}
const bst = new BinarySearchTree();
bst.insert(200);
bst.insert(100);
bst.insert(300);
bst.insert(50);
bst.insert(150);
bst.insert(250);
bst.insert(350);
bst.insert(25);
bst.insert(75);
bst.insert(125);
bst.insert(175);
bst.insert(225);
bst.insert(275);
bst.insert(325);
bst.insert(375);
bst.postorder();
bst.preorder();
bst.inorder();
bst.deepth();
bst.remove(250);
bst.inorder();
bst.deepth();
bst.max();
bst.min();
2. 二叉堆(Heap)
最大堆和最小堆
const compareFn = (a, b) => {
if(a < b) {
return -1
} else if(a > b) {
return 1;
} else {
return 0;
}
}
compareFn.LESS_THAN = -1;
compareFn.MORE_THAN = 1;
compareFn.EQ = 0;
export class Heap {
constructor(compare = compareFn) {
this.items = [];
this.compare = compare;
}
insert(item) {
if(item) {
this.items.push(item);
this.shiftUp(this.items.length - 1)
}
}
extract() {
if(this.isEmpty()) {
return undefined;
}
const size = this.size();
if(size === 1) {
return this.items.shift();
}
const item = this.items[0];
this.items[0] = this.items.pop();
this.shiftDown(0);
return item;
}
isEmpty() {
return this.items.length === 0;
}
size() {
return this.items.length;
}
min() {
return this.items[0];
}
max() {
return this.items[0];
}
swap(array, indexA, indexB) {
const temp = array[indexA];
array[indexA] = array[indexB];
array[indexB] = temp;
}
getParentIndex(index) {
return Math.floor((index - 1) / 2);
}
getLeftIndex(index) {
return 2 * index + 1;
}
getRightIndex(index) {
return 2 * index + 2;
}
toString() {
return this.items.toString();
}
}
class MaxHeap extends Heap {
constructor(compareFn) {
super(compareFn);
}
shiftUp(index) {
let parent = this.getParentIndex(index);
while(index > 0 && this.compare(this.items[index], this.items[parent]) === compareFn.MORE_THAN) {
this.swap(this.items, index, parent);
index = parent;
parent = this.getParentIndex(index);
}
}
shiftDown(index) {
let element = index;
const left = this.getLeftIndex(element);
const right = this.getRightIndex(element);
const size = this.size();
if(left < size && right < size) {
const leftCompareRes = this.compare(this.items[element], this.items[left]);
const rightCompareRes = this.compare(this.items[element], this.items[right]);
if(leftCompareRes === compareFn.LESS_THAN && rightCompareRes === compareFn.LESS_THAN) {
if(this.compare(this.items[left], this.items[right]) === compareFn.MORE_THAN) {
element = left;
} else {
element = right;
}
} else if(leftCompareRes === compareFn.LESS_THAN) {
element = left;
} else if(rightCompareRes === compareFn.LESS_THAN) {
element = right;
}
} else if(left < size) {
if(this.compare(this.items[element], this.items[left]) === compareFn.LESS_THAN) {
element = left;
}
} else if(right < size) {
if(this.compare(this.items[element], this.items[right]) === compareFn.LESS_THAN) {
element = right;
}
}
if(index !== element) {
this.swap(this.items, index, element);
this.shiftDown(element);
}
}
}
class MinHeap extends Heap {
constructor() {
super();
}
shiftUp(index) {
const parent = this.getParentIndex(index);
if(index > 0 && this.compare(this.items[index], this.items[parent]) === compareFn.LESS_THAN) {
this.swap(this.items, index, parent);
index = parent;
this.shiftUp(index);
}
}
shiftDown(index) {
let element = index;
const left = this.getLeftIndex(element);
const right = this.getRightIndex(element);
const size = this.size();
if(left < size && right < size) {
const leftCompareRes = this.compare(this.items[element], this.items[left]);
const rightCompareRes = this.compare(this.items[element], this.items[right]);
if(leftCompareRes === compareFn.MORE_THAN && rightCompareRes === compareFn.MORE_THAN) {
if(this.compare(this.items[left], this.items[right]) === compareFn.LESS_THAN) {
element = left;
} else {
element = right;
}
} else if(leftCompareRes === compareFn.MORE_THAN) {
element = left;
} else if(rightCompareRes === compareFn.MORE_THAN) {
element = right;
}
} else if(left < size) {
if(this.compare(this.items[element], this.items[left]) === compareFn.MORE_THAN) {
element = left;
}
} else if(right < size) {
if(this.compare(this.items[element], this.items[right]) === compareFn.MORE_THAN) {
element = right;
}
}
if(index !== element) {
this.swap(this.items, index, element);
this.shiftDown(element);
}
}
}
const maxHp = new MaxHeap();
maxHp.insert(55);
maxHp.insert(45);
maxHp.insert(35);
maxHp.insert(25);
maxHp.insert(15);
maxHp.insert(10);
maxHp.insert(20);
maxHp.insert(30);
maxHp.insert(40);
maxHp.insert(50);
maxHp.insert(60);
maxHp.insert(70);
maxHp.insert(80);
const minHp = new MinHeap();
minHp.insert(55);
minHp.insert(45);
minHp.insert(35);
minHp.insert(25);
minHp.insert(15);
minHp.insert(10);
minHp.insert(20);
minHp.insert(30);
minHp.insert(40);
minHp.insert(50);
minHp.insert(60);
minHp.insert(70);
minHp.insert(80);
下一篇:【数据结构】自己动手使用JavaScript实现单向链表、双向链表(第四篇)-CSDN博客
注:以上,如有不合理之处,还请帮忙指出,大家一起交流学习~