javascript数据结构及实现二叉树算法
今天学了慕课网coding迪斯尼 老师的Javascript实现二叉树算法课程,感觉很有意思,既加深了对js的了解,也理解了二叉树算法原理,实在受益匪浅,特将学习过程整理成一篇学习笔记,以免将来想要的时候能找回来看。课程主要内容:
- 二叉树的构造
- 二叉树的排序
- 二叉树的查询
- 二叉树的删除
二叉树的构造
创建一个二叉树的对象,里面包含节点函数、根元素、创建节点之间关系的函数和提供访问的方法。
function BinaryTree(){
var Node=function(key){ //节点函数
this.key=key;
this.left=null;
this.right=null;
}
var root=null; //根元素
this.insert=function(key){ //对外提供访问函数内部的接口
var newNode=new Node(key);
if(root==null){
root=newNode
}else{
insertNode(root,newNode);
}
}
var insertNode=function(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)
}
}
}
}
在计算机科学中,二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用作二叉查找树和二叉堆或是二叉排序树。 360百科
二叉树的排序
中序遍历
在二叉树函数中提供一个对外访问的方法,和一个注入回调函数的递归函数。
var inOrderTraverseNode=function(node,callback){
if(node!=null){
inOrderTraverseNode(node.left,callback)
callback(node.key)
inOrderTraverseNode(node.right,callback)
}
}
this.inOrderTraverse=function(callback){
inOrderTraverseNode(root,callback);
}
将数组遍历放入二叉树进行构造,调用二叉树的inOrderTraverse(中序遍历)方法
var nodes=[8,3,10,1,6,14,4,7,13];
var binaryTree=new BinaryTree();
nodes.forEach(function(key){
binaryTree.insert(key);
})
var callback=function(key){
console.log(key)
}
binaryTree.inOrderTraverse(callback)
实现效果如下:
前序遍历
有的同学会问,既然有了中序遍历为何还需要前序排序?既然存在就一定会有他的道理。前序遍历可以很有效率的复制一个二叉树对象,比直接再使用二叉树对象构造的速度要快差不多10倍。
var proOrderTraverseNode=function(node,callback){
if(node!=null){
callback(node.key)
proOrderTraverseNode(node.left,callback)
proOrderTraverseNode(node.right,callback)
}
}
//前序遍历 复制 效率高得多
this.proOrderTraverse=function(callback){
proOrderTraverseNode(root,callback);
}
使用proOrderTraverse(前序遍历)方法:
var nodes=[8,3,10,1,6,14,4,7,13];
var binaryTree=new BinaryTree();
nodes.forEach(function(key){
binaryTree.insert(key);
})
var callback=function(key){
console.log(key)
}
binaryTree.proOrderTraverse(callback)
运行后的效果
后序遍历
同样后序遍历也有自己的作用,后序遍历选查找子集的特性可以运用在文件系统遍历当中。
var postOrderTraverseNode=function(node,callback){
if(node!=null){
postOrderTraverseNode(node.left,callback)
postOrderTraverseNode(node.right,callback)
callback(node.key)
}
}
//后续遍历 文件系统遍历
this.postOrderTraverse=function(callback){
postOrderTraverseNode(root,callback);
}
使用postOrderTraverse(后序遍历)方法:
var nodes=[8,3,10,1,6,14,4,7,13];
var binaryTree=new BinaryTree();
nodes.forEach(function(key){
binaryTree.insert(key);
})
var callback=function(key){
console.log(key)
}
binaryTree.postOrderTraverse(callback)
运行后的效果
二叉树的查找
查找最大值
var maxNode=function(node){
if(node){
while(node&&node.right!=null){
node=node.left
}
return node.key;
}
}
this.max=function(){
return maxNode(root)
}
查找最小值
var minNode=function(node){
if(node){
while(node&&node.left!=null){
node=node.left
}
return node.key;
}
}
this.min=function(){
return minNode(root)
}
查找指定值
var searchNode=function(node,key){
if(node==null){
return false
}
if(node.key>key){ //小于当前node往左找
searchNode(node.left,key)
}else if(node.key<key){ //大于当前node往右找
searchNode(node.right,key)
}else{ // 找到
return true;
}
}
this.search=function(key){
return searchNode(root,key)
}
二叉树的删除
二叉树删除分三种情况,删除左叶子节点,和删除右叶子节点以及拥有左右两个节点的主节点删除。拥有左右两个节点的主节点删除要考虑到数据的可排序行需要将删掉的节点重新赋值。
var findMinNode=function(node){ //如果存在左右两个节点的话查找右节点的最小节点
if(node){
while(node&&node.left!=null){
node=node.left
}
return node;
}
return null
}
var removeNode=function(node,key){
if(node==null){
return null;
}
if(node.key>key){// 递归查找左叶子节点,直接等于返回的null值
node.left=removeNode(node.left,key)
return node;
}else if(node.key<key){// 递归查找右叶子节点,直接等于返回的null值
node.right=removeNode(mode.right,key)
return node;
}else{// 如果查找到相等的情况下
if(node.left==null&&node.right==null){// 当只有一个节点,而且被选中
node=null;
return node;
}
if(node.left==null){ //左节点为空
node=node.right;
return node;
}else if(node.right==null){//右节点为空
node=node.left;
return node;
}
var aux=findMinNode(node.right);//查找到右节点最小节点赋值
node.key=aux.key;
node.right=removeNode(node.right,aux.key);
return node;
}
}
this.remove=function(key){
return removeNode(root,key)
}
参考:
慕课网Javascript实现二叉树算法