很久没有认真思考算法了,这两天看了小伙伴的《学习JavaScript数据结构与算法》一书。看到了二叉搜索树一节,感觉又回到了大学时代。下面把书中的代码手敲一下(凭记忆,有改动),分为两个文件BinarySearchTree.js和test.js。用node test.js运行就行了。我要坚持在算法的路上越走越远!!!
// BinarySearchTree.js
// 二叉搜索树
const COMPARE = {
LESS_THAN: -1,
EQUAL: 0,
BIGGER_THAN: 1
};
function Node(val) {
this.val = val;
this.left = null;
this.right = null;
};
function defaultCompareFn(a, b) {
if (a < b) {
return COMPARE.LESS_THAN;
}
if (a > b) {
return COMPARE.BIGGER_THAN;
}
return COMPARE.EQUAL;
};
function BinarySearchTree(compareFn = defaultCompareFn) {
this.compareFn = compareFn;
this.root = null;
};
/**
* 插入
* @param {*} val
*/
BinarySearchTree.prototype.insert = function(val) {
// 如果是空树,直接创建根节点
if (!this.root) {
this.root = new Node(val);
} else { // 否则
this._insert(this.root, val);
}
};
BinarySearchTree.prototype._insert = function(node, val) {
if (this.compareFn(val, node.val) === COMPARE.LESS_THAN) {
if (!node.left) {
node.left = new Node(val);
} else {
this._insert(node.left, val);
}
} else {
if (!node.right) {
node.right = new Node(val);
} else {
this._insert(node.right, val);
}
}
};
BinarySearchTree.prototype.remove = function(val) {
this.root = this._remove(this.root, val);
};
BinarySearchTree.prototype._remove = function(node, val) {
if (!node) {
return null;
}
if (this.compareFn(val, node.val) === COMPARE.LESS_THAN) { // 小于
node.left = this._remove(node.left, val);
return node;
} else if (this.compareFn(val, node.val) === COMPARE.BIGGER_THAN) { // 大于
node.right = this._remove(node.right, val);
return node;
} else {
// 叶子节点
if (!node.left && !node.right) {
return null;
}
if (!node.left) { // 左子树空
return node.right;
}
if (!node.right) { // 右子树空
return node.left;
}
// 两个子树都不空
// 把右子树中最小节点提上来
const minNode = this.min(node.right);
node.val = minNode.val;
node.right = this._remove(node.right, val);
return node;
}
};
BinarySearchTree.prototype.min = function(node) {
let cur = node || this.root;
while(cur && cur.left) {
cur = cur.left;
}
return cur;
};
BinarySearchTree.prototype.max = function(node) {
let cur = node || this.root;
while(cur && cur.right) {
cur = cur.right;
}
return cur;
};
BinarySearchTree.prototype.search = function(val) {
return this._search(this.root, val);
};
BinarySearchTree.prototype._search = function(node, val) {
if (!node) {
return false;
}
if (this.compareFn(val, node.val) === COMPARE.LESS_THAN) {
return this._search(node.left, val);
} else if (this.compareFn(val, node.val) === COMPARE.BIGGER_THAN) {
return this._search(node.right, val);
} else {
return true;
}
};
BinarySearchTree.prototype.inOrderTraverse = function(callback) {
this._inOrderTraverse(this.root, callback);
};
BinarySearchTree.prototype._inOrderTraverse = function(node, callback) {
if (node) {
this._inOrderTraverse(node.left, callback);
callback(node);
this._inOrderTraverse(node.right, callback);
}
};
BinarySearchTree.prototype.preOrderTraverse = function(callback) {
this._preOrderTraverse(this.root, callback);
};
BinarySearchTree.prototype._preOrderTraverse = function(node, callback) {
if (node) {
callback(node);
this._preOrderTraverse(node.left, callback);
this._preOrderTraverse(node.right, callback);
}
};
BinarySearchTree.prototype.postOrderTraverse = function(callback) {
this._postOrderTraverse(this.root, callback);
};
BinarySearchTree.prototype._postOrderTraverse = function(node, callback) {
if (node) {
this._postOrderTraverse(node.left, callback);
this._postOrderTraverse(node.right, callback);
callback(node);
}
};
module.exports = BinarySearchTree;
// test.js
// test.js
const BinarySearchTree = require('./BinarySearchTree.js');
const arr = [4, 99, 44, 3, 55];
const tree = new BinarySearchTree();
// 1. 插入,构建二叉搜索树
arr.forEach(item => {
tree.insert(item);
});
console.log('二叉搜索树:');
console.log(JSON.stringify(tree));
// 2. 中序遍历
console.log('中序遍历');
tree.inOrderTraverse(item => {
// 结果就是从小到大遍历
console.log(item.val);
});
// 3. 先序遍历
console.log('先序遍历');
tree.preOrderTraverse(item => {
// 结果就是从上到下
console.log(item.val);
});
// 4. 中序遍历
console.log('后序遍历');
tree.postOrderTraverse(item => {
// 结果就是从下到上遍历,保证访问中间节点时子节点已经访问过了,用于自底向上汇总
console.log(item.val);
});
// 5. 最大
console.log('最大节点:', tree.max());
// 6. 最小
console.log('最大节点:', tree.min());
// 7 8
console.log('99是否存在:', tree.search(99));
console.log('100是否存在:', tree.search(100));
// 9. 移除44
tree.remove(44);
console.log('移除44后结果:');
console.log(JSON.stringify(tree));
// 10. 移除不存在的22
console.log('移除22后结果:');
console.log(JSON.stringify(tree));