javascript数据结构7-二叉搜索树(BST)

二叉树 :

这里写图片描述

闲话少说,直接上代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BST</title>
</head>
<body>
<script>
  //结点
    function Node(data,left,right){
        this.data=data;
        this.left=left;
        this.right=right;
        this.floor=floor;  //层数
        this.show=show;
    }
    function floor(){
      return this.floor;
    }
    function show(){
        return this.data;
    }

    function BST(){
        this.root=null;
        this.insert=insert; //插入数据
        this.inOrder=inOrder; //中序排列,详细见后面解释
        this.preOrder=preOrder; //先序排序
        this.postOrder=postOrder; //后续排序
        this.getMax=getMax; //得到最大值
        this.getMin=getMin; //得到最小值
        this.find=find; //查找
        this.remove=remove; //删除节点
    }

    function insert(data){
       var n=new Node(data,null,null);
        if(this.root==null){
            this.root=n;
            this.root.floor=1;
        }else{
            var current=this.root;
            var parent;
                var c=1;    
            while(true){
                parent=current;  
                if(data<current.data){
                        current=current.left;
                        c++;  //计算层数的计数器加1
                    if(current==null){
                        parent.left=n;
                        parent.left.floor=c;
                        break;
                    }
                }else{
                    current=current.right;
                        c++;   //加1
                    if(current==null){
                        parent.right=n;
                        //rHeight++;
                        // console.log("**"+rHeight+"**");
                        parent.right.floor=c;
                        break;
                    }
                }
            }
        }
    }
  //中序遍历
  function inOrder(node){
      if(!(node==null)){
          inOrder(node.left);
          document.write(node.show()+" ");
          document.write("层数"+node.floor+"<br/>");
          inOrder(node.right);
      }
       //console.count("inOrder被执行的次数");
  }
  //先序遍历
   function preOrder(node){
      if(!(node==null)){
          document.write(node.show()+" ");
          preOrder(node.left);
          preOrder(node.right);
      }
  }

  //后序遍历
   function postOrder(node){
      if(!(node==null)){
          postOrder(node.left);        
          postOrder(node.right);
            document.write(node.show()+" ");
      }
  }

  //查找最大值
  function getMax(){
        var current=this.root;
        while(!(current.right==null)){
            current=current.right;
        }
        return current.data;
  }
  //查找最小值
   function getMin(){
        var current=this.root;
        while(!(current.left==null)){
            current=current.left;
        }
        return current.data;
  }
  //带参数---查找最小值
  function getSmallest(node){
        while(!(node.left==null)){
            node=node.left;
        }
     return node;
  }
  //查找
  function find(data){
        var current=this.root;
        while(current!=null){
            if(current.data==data){
              document.write("<br/>找到【"+data+"】节点<br/>");
              return current;
            }else if(data<current.data){
               current=current.left;
            }else{
               current=current.right;
            }

        }
     document.write("<br/>没有找到【"+data+"】 节点<br/>");
//      return current;
  }

  //删除节点-详细解释见后后面
     function remove(data) {
            root = removeNode(this.root, data);
            //其实root=没有用处,只是保留了函数执行的地址
    }
    function removeNode(node, data) {
          if (node == null) {
                return null;
            }
        if (data == node.data) {
            // 没有子节点的节点
            if (node.left == null && node.right == null) {
                    return null;
            }
            // 没有左子节点的节点
            if (node.left == null) {
                    return node.right;
            }
            // 没有右子节点的节点
            if (node.right == null) {
                    return node.left;
            }
            // 有两个子节点的节点
            var tempNode = getSmallest(node.right);
            node.data = tempNode.data;
            node.right = removeNode(node.right, tempNode.data);
                    return node;
            }
            else if (data < node.data) {
                node.left = removeNode(node.left, data);

                return node;
            }
            else {
                node.right = removeNode(node.right, data);
              // console.log(node);
                return node;
            }
}

  //测试
      var nums=new BST();
      nums.insert(56);
      nums.insert(22);  
      nums.insert(81);
      nums.insert(10);
      nums.insert(30);
      nums.insert(77);
      nums.insert(92);
      nums.insert(100);
      document.write("*****************中序遍历***************</br>");
      inOrder(nums.root);
      document.write("</br>***************先序遍历***************</br>");
      preOrder(nums.root);
      document.write("</br>***************后序遍历***************</br>");
      postOrder(nums.root);
      //nums.show();
      //console.log(nums);  
      document.write("</br>***************最大值/最小值************</br>");
      document.write(nums.getMax()+"/"+nums.getMin());
      document.write("</br>***************查找************</br>");
      nums.find(100);
      document.write("</br>***************删除节点81后************</br>");
      nums.remove(81);
      console.log(nums);
      preOrder(nums.root);
</script>
</body>
</html>

结果:
这里写图片描述

遍历

中序遍历:
这里写图片描述
理解双层递归

function inOrder(node) {
    if (!(node == null)) {
        inOrder(node.left);                             //@1
        document.document(node.show() + " ");           //@2
        inOrder(node.right);                            //@3
    }
}


inOrder(nums.root);    //开始执行

从根节点开始:
这里写图片描述

这里写图片描述
这里写图片描述

删除节点:

function remove(data) {
        root = removeNode(this.root, data);  
    }

简单接受待删除的数据,具体执行是removeNode函数;

function removeNode(node, data) {
    }

待删除的节点是:
1.叶子结点,只需要将从父节点只想它的链接指向null;

if (node.left == null && node.right == null) {
        return null;   
    }
if (node.left == null && node.right == null) {
                return null;   //递归,找到节点置为空即可
            }
               //其他情况
            }
            else if (data < node.data) {
                node.left = removeNode(node.left, data);  //#1            
                return node; //#2
            }
            else {
                node.right = removeNode(node.right, data);//#3
                return node; //#4
            }

通过if else逻辑找到node节点


//#1  node.left=null(后面的函数递归后返回的值)
//#3  node.right=null(后面的函数递归后返回的值)

2.只包含一个子节点,原本指向它的节点指向它的子节点。
3.左右子树都有的时候。两种做法:找到左子树的最大值或者右子树的最小值。这里我们用第二种。

  • 查找右子树的最小值,创建一个临时的节点tempNode。
  • 将临时节点的值赋值给待删除节点
  • 删除临时节点

注意:


//#2 //#4必须有,如果没有,则删除节点下面的所有子树都将被删除。
真个过程举个形象的说明,遍历的时候把节点之间的链条解开进行查询,return node;递归查询到最后一级后,由下向上对链条进行缝合。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值