二叉树的创建与方法

二叉树是一种重要的数据存储结构,它体现了一对多的数据存储方式,一颗二叉树有一个根节点(root),与众多分结点组成,每个双亲最多有两个子树分为左子树右子树,结点的分支数称为这个结点的度,整个二叉树的度为最大的度.度为0的结点称为叶结点.
代码放在GitHub:二叉查找树

满二叉树与完全二叉树

在这里插入图片描述

  • 满二叉树每个层级的结点都达到最大
  • 完全二叉树必须从左到右依次排序,造成只能右边存在缺失(如果左边缺失势必造成不是正确的排序)

二叉树的创建

  • 每个结点最多只有两个分支left(左子树)、right(右子树)

使用JavaScript实现二叉树的创建


 /**
  * @name: 二叉树创建封装
  * @params: null
  * @return: undefined
  */
 function BinarySearchTree() {
    //  根节点
     this.root=null;
    // 结点包括左子树和右子树结点和当前的键
     this.node=function (key) {
         this.key=key;
         this.left=null;
         this.right=null;
     };
 }

可以看到非常的简单,每个结点由相应的key、left(左子树)、right(右子树)构成,还有一个root(根节点)

添加插入结点的方法

  • 小于双亲的结点在双亲的左边,大于双亲的在双亲的右边
  • 根节点的左边为全部小于结点的树,右边全部为大于跟结点
  • 如果没有root(根节点)则插入结点为根节点
/**
  * @name: 二叉树插入方法
  * @params: 插入的键
  * @return: undefined
  */
 BinarySearchTree.prototype.insert=function (key) {
    // 创建新结点
    let newNode=new this.node(key); 
    if(this.root===null){
         this.root=newNode;
     }else{

         this.insertRecurse(this.root,newNode);
     }
 }
/**
 * @name:二叉树递归插入方法 
 * @params: parent(双亲)  node(插入的结点)
 * @return: undefined
 */
BinarySearchTree.prototype.insertRecurse=function (parent,node) {
    // 小于为左子树部分,大于为右子树部分
    if(node.key<parent.key){
        parent.left?this.insertRecurse(parent.left,node):parent.left=node;
    }
    else{
        parent.right?this.insertRecurse(parent.right,node):parent.right=node;
    }
}

遍历操作

二叉树数据结构常用的遍历方法主要有4种:

  • 前序遍历
  • 中序遍历
  • 后序遍历
  • 层序遍历

各种遍历操作可以用根节点的位置进行区分,遍历顺序都是优先遍历左在遍历右,所以前序遍历顺序为双亲(D)->左子树(L)->右子树( R),中序遍历顺序为左子树(L)->双亲(D)->右子树( R),后序遍历顺序为左子树(L)->右子树( R)->双亲(D),层序遍历就是从左到右、从上到下进行遍历,一般没做说明.
在这里插入图片描述
例:如上图满二叉树,前序遍历顺序为 A BDE CFG,上图非完全二叉树遍历顺序为A BD CEF

JavaScript实现前序遍历
假设利用上边的二叉树插入方法,生成一颗二叉树如下:
插入数值

var bst=new BinarySearchTree()
bst.insert(11);
bst.insert(5);
bst.insert(8);
bst.insert(10);
bst.insert(15);
bst.insert(16);
bst.insert(12);
bst.insert(14);
bst.insert(17);

在这里插入图片描述
则想要实现的前序遍历顺序应该 11 5 8 10 15 12 14 16 17
实现前序遍历算法:

 /**
      * @name:前序遍历算法 
      * @params: 接收遍历结果的回调 
      * @return: undefined
      */
     BinarySearchTree.prototype.prevOrderIterate=function(callback) {
         this.prevOrderIterateRecurse(this.root,callback);
     };
    //  前序遍历递归
     BinarySearchTree.prototype.prevOrderIterateRecurse=function (node,callback) {
         if(node!==null){
            //  返回遍历值
            callback(node.key);
          
            //  继续遍历左子树,再遍历右子树(利用栈结构特点)
             this.prevOrderIterateRecurse(node.left,callback);
             this.prevOrderIterateRecurse(node.right,callback);
         }
       }
/*调用*/
var res=''
bst.prevOrderIterate(function(e) {
    res+=' '+e;
})
console.log(res);

JavaScript实现中序遍历、后序遍历
思想同前序遍历,只需改变递归操作中的顺序即可

/**
* @name:中序遍历 
* @params: 接收参数的回调 callback: [Function]
* @return: undefined
*/
BinarySearchTree.prototype.midOrderInterate=function (callback) {
   this.midOrderInterateRecurse(this.root,callback);
};
// 中序遍历递归
BinarySearchTree.prototype.midOrderInterateRecurse=function (node,callback) {
   if(node!==null){
       this.midOrderInterateRecurse(node.left,callback);
       callback(node.key);
       this.midOrderInterateRecurse(node.right,callback);
   }
};
/**
* @name:后序遍历 
* @params: 后序遍历的回调 callback [Function]
* @return: undefined
*/
BinarySearchTree.prototype.aftOrderInterate=function (callback) {
   this.aftOrderInterateRecurse(this.root,callback);
};
// 后序遍历递归
BinarySearchTree.prototype.aftOrderInterateRecurse=function (node,callback) {
   if(node!==null){
       this.midOrderInterateRecurse(node.left,callback);
       this.midOrderInterateRecurse(node.right,callback);
       callback(node.key);
   }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章