二叉搜索树数据结构及基本方法
function BinarySearchTree(){
var root = null;
var Node = function(key){
this.key = key;
this.left = this.right = null;
}
//插入节点
function insertNode(node, newNode){
if(node.key > newNode.key){
if(node.left == null){
node.left = newNode;
}else{
insertNode(node.left, newNode);
}
}else{
if(node.right == null){
node.right = newNode;
}else{
insertNode(node.right, newNode);
}
}
}
this.insert = function(key){
let newNode = new Node(key);
if(root === null){
root = newNode;
}else{
insertNode(root, newNode);
}
}
//打印二叉树
this.review = function(){
console.log(root);
}
//查询最小值
function minNode(node){
if(node){
while(node && node.left !== null){
node = node.left;
}
return node.key;
}
return null;
}
this.min = function(){
return minNode(root);
}
//查询最大值
function maxNode(node){
if(node){
while(node && node.right){
node = node.right;
}
return node.key;
}
return null;
}
this.max = function(){
return maxNode(root);
}
//查询树中是否有特定值
function searchNode(node, key){
if(node == null){
return false;
}else if(node.key < key){
searchNode(node.left, key);
}else if(node.key > key){
searchNode(node.right, key);
}else{
return true;
}
}
this.search = function(key){
return searchNode(root, key);
}
//移除节点
function findMinNode(node){
while(node && node.left !== null){
node = node.left;
}
return node;
}
function removeNode(node, key){
if(node === null){
return null;
}else if(node.key < key){
node.right = removeNode(node.right, key);
return node;
}else if(node.key > key){
node.left = removeNode(node.left, key);
return node;
}else{
if(node.left == null && node.right == null){
node = null;
return node;
}else if(node.left == null){
node = node.right;
return node;
}else if(node.right == null){
node = node.left;
return node;
}else{
let changeNode = findMinNode(node.right);//找出右子树最小节点
node.key = changeNode.key;
node.right = removeNode(node.right, changeNode.key);
return node;
}
}
}
this.remove = function(key){
removeNode(root, key);
}
复制代码
中序、前序、后序遍历
//中序遍历
function inOrderTraverseNode(node, callback){
if(node != null){
inOrderTraverseNode(node.left,callback);
callback(node);
inOrderTraverseNode(node.right,callback);
}
}
this.inOrderTraverse = function(callback){
inOrderTraverseNode(root, callback);
}
//前序遍历
//递归版
function preOrderTraverseNode(node, callback){
if(node != null){
callback(node);
preOrderTraverseNode(node.left,callback);
preOrderTraverseNode(node.right,callback);
}
}
//非递归版
function preOrderTraverseNode(node, callback){
let stack = [];
if(node === null){
return null;
}
stack.push(node);
while(stack.length > 0){
let currentNode = stack.pop();
callback(currentNode);
if(currentNode.right!==null){
stack.push(currentNode.right);
}
if(currentNode.left){
stack.push(currentNode.left);
}
}
}
this.preOrderTraverse = function(callback){
preOrderTraverseNode(root, callback);
}
//后序遍历
function postOrderTraverseNode(node, callback){
if(node != null){
postOrderTraverseNode(node.left,callback);
postOrderTraverseNode(node.right,callback);
callback(node);
}
}
this.postOrderTraverse = function(callback){
postOrderTraverseNode(root, callback);
}
复制代码
广度搜索遍历(非递归)
//用队列来实现
function breadthFirstSearch(node, callback){
if(node === null){
return;
}
let queue = [];
queue.push(node);
while(queue.length > 0){
let currentNode = queue.shift();
callback(currentNode);
if(currentNode.left){
queue.push(currentNode.left);
}
if(currentNode.right){
queue.push(currentNode.right);
}
}
}
this.breathFirst = function(callback){
breadthFirstSearch(root, callback);
}
复制代码
翻转(镜像)二叉树
//递归版(破坏原二叉树)
function invertTreeNode(node){
if(node === null){
return ;
}
invertTreeNode(node.left);
invertTreeNode(node.right);
//交换左右节点
let temp = node.left;
node.left = node.right;
node.right = temp;
}
//非递归(破坏原二叉树)
//其实过程类似于层序遍历,所以可使用队列来解决
function invertTreeNode(node){
let queue = [];
if(node === null){
reurn ;
}
queue.push(node);
while(queue.length > 0){
let currentNode = queue.shift();
let temp = currentNode.left;
currentNode.left = currentNode.right;
currentNode.right = temp;
if(currentNode.left !== null){
queue.push(currentNode.left);
}
if(currentNode.right !== null){
queue.push(currentNode.right);
}
}
}
//递归版(不破坏原二叉树)
function invertTreeNode(node){
if(node === null){
return null;
}
let newTree = new Node(node.key);
newTree.left = invertTreeNode(node.right);
newTree.right = invertTreeNode(node.left);
return newTree;
}
//非递归版(不坏原二叉树)
function invertTreeNode(node){
let queue = [], newqueue = [];
let newTree = new Node(node.key);
queue.push(node);
newqueue.push(newTree);
while(queue.length > 0){
let onode = queue.shift();
let currentNode = newqueue.shift();
if(onode.left !== null){
currentNode.left = new Node(onode.right.key);
queue.push(onode.right);
newqueue.push(currentNode.left);
}
if(onode.left !== null){
currentNode.right = new Node(onode.left.key);
queue.push(onode.left);
newqueue.push(currentNode.right);
}
}
return newTree;
}
this.invertTree = function(){
invertTreeNode(root);
}
复制代码
求节点个数
function countNode(node){
if(node === null){
return 0;
}
return countNode(node.left) + countNode(node.right) + 1;
}
this.num = function(){
return countNode(root);
}
复制代码
求二叉树深度
//递归
function countDepth(node){
if(node === null){
return 0;
}
return Math.max(countDepth(node.left), countDepth(node.right)) + 1;
}
//非递归
function countDepth(node){
if(node === null){
return 0;
}
let queue = [];
let depth = 1;
let currentLevelCount = 1;//当前层的节点数(关键)
let nextLevelCount = 0;//下一层的节点数(关键)
queue.push(node);
while(queue.length > 0){
let currentNode = queue.shift();
currentLevelCount--;
if(currentNode.left !== null){
queue.push(currentNode.left);
nextLevelCount++;
}
if(currentNode.right !== null){
queue.push(currentNode.right);
nextLevelCount++;
}
if(currentLevelCount === 0 && nextLevelCount > 0){
depth++;
currentLevelCount = nextLevelCount;
nextLevelCount = 0;
}
}
return depth;
}
this.depth = function(){
return countDepth(root);
}
复制代码
求第k层的所有节点
//求第k层的所有节点(递归)
function kLevelNode(node, level, callback){
if(node === null){
return ;
}
if(level == 1){
callback(node);
return ;
}
kLevelNode(node.left, level-1, callback);
kLevelNode(node.right, level-1, callback);
}
this.kLevel = function(level, callback){
kLevelNode(root, level, callback);
}
复制代码
求叶子节点
//求叶子节点(递归)
function leafNode(node, callback){
if(node === null){
return ;
}
if(node.left === null && node.right === null){
callback(node);
return ;
}
leafNode(node.left, callback);
leafNode(node.right, callback);
}
this.leaf = function(callback){
leafNode(root, callback);
}
复制代码
判断是否为二分查找树
//判断是否为二分查找树(递归)
//如果是二分查找树,那么该树的中序遍历是由小到大的
function isValidBST(node, pre) {
if(!node)return true;
if(!isValidBST(node.left, pre))
return false;
if(pre && node.key < pre.key)
return false;
return isValidBST(node.right, node);
}
this.isBST = function(){
return isValidBST(root, null);
}
}
复制代码
总结
- 有广度遍历特征的算法的非递归实现一般用队列
- 有深度遍历特征的算法的非递归实现一般用栈
做得不好的地方还请各位指出,谢谢!