二叉树

本文内容学习自JavaScript实现二叉树


二叉树

  • 二叉树是每个节点最多有两个子树的树结构。通常子树被称左子树右子树

  • 二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。

  • 二叉树的第i层至多有2^{i-1} 个结点(顶层为第一层)

二叉树遍历

  • 前序遍历就是先访问树的根节点,再访问树的左子节点,再访问右子节点。

  • 中序遍历就是先访问树的左子节点,再访问树的根节点,再访问右子节点。

  • 后序遍历就是先访问树的左子节点,再访问树的右子节点,再访问根节点。



创建二叉树

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>二叉树</title>
  </head>
  <body>
    <script>
      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 (newNode.key < node.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);
            }
          }
        }
      }
    </script>
  </body>
</html>

中序遍历

      // 中序遍历
        this.inOrderTraverse = function (callback) {
          inOrderTraverseNode(root, callback);
        }
        var inOrderTraverseNode = function (node, callback) {
          if (node !== null) {
            inOrderTraverseNode(node.left, callback);
            callback(node.key);
            inOrderTraverseNode(node.right, callback);
          }
        }
      var callback = function (key) {
        console.log(key);
      }

前序遍历

// 前序遍历
        this.preOrderTraverse = function (callback) {
          preOrderTraverseNode(root, callback);
        }
        var preOrderTraverseNode = function (node, callback) {
          if (node !== null) {
            callback(node.key);
            preOrderTraverseNode(node.left, callback);
            preOrderTraverseNode(node.right, callback);
          }
        }
      var callback = function (key) {
        console.log(key);
      }

后序遍历

        this.postOrderTraverse = function (callback) {
          postOrderTraverseNode(root, callback);
        }
        var postOrderTraverseNode = function (node, callback) {
          if (node !== null) {
            postOrderTraverseNode(node.left, callback);
            postOrderTraverseNode(node.right, callback);
            callback(node.key);
          }
        }
      var callback = function (key) {
        console.log(key);
      }

最小值

        this.min = function () {
          return minNode(root);
        }
        var minNode = function (node) {
          if (node) {
            while (node && node.left !== null) {
              node = node.left;
            }
            return node.key;
          }
          return null;
        }

最大值

        this.max = function () {
          return maxNode(root);
        }
        var maxNode = function (node) {
          if (node) {
            while (node && node.right !== null) {
              node = node.right;
            }
            return node.key;
          }
          return null;
        }

查找某个值

        this.search = function (key) {
          return searchNode(root, key);
        }
        var searchNode = function (node, key) {
          if (node == null) {
            return false;
          }
          if (key < node.key) {
            return searchNode(node.left, key);
          } else if (key > node.key) {
            return searchNode(node.right, key);
          } else {
            return true;
          }
        }

删除末节点

        this.remove = function (key) {
          root = removeNode(root, key);
        }
        var removeNode = function (node, key) {
          if (node === null) {
            return null;
          }
          if (key < node.key) {
            node.left = removeNode(node.left, key);
            return node;
          } else if (key > node.key) {
            node.right = removeNode(node.right, key);
            return node;
          } else {
            if (node.left === null && node.right === null) {
              node = null;
              return node;
            }
          }
        }

删除节点 包括末节点中间节点

        this.remove = function (key) {
          root = removeNode(root, key);
        }
        var removeNode = function (node, key) {
          if (node === null) {
            return null;
          }
          if (key < node.key) { // 小于此节点的key,node赋值为 node.left 继续遍历
            node.left = removeNode(node.left, key);
            return node;
          } else if (key > node.key) { // 大于此节点的key,node赋值为 node.right 继续遍历
            node.right = removeNode(node.right, key);
            return node;
          } else { // 等于此节点的key , 1 末节点 , 2 中间节点

            // 末节点直接把此key赋值为null
            if (node.left === null && node.right === null) {
              node = null;
              return node;
            }
            // 中间节点
            // 1,有right 或 left时,把此节点的left或right赋值为node = node.left 或 node = node.right
            if (node.left === null) {
              node = node.right;
              return node;
            } else if (node.right === null) {
              node = node.left;
              return node;
            }
            // 2,同时有right和left , 找到此节点右侧的最小值赋值  node = node.right的最小值
            var aux = findMinNode(node.right);
            node.key = aux.key;
            node.right = removeNode(node.right, aux.key);
            return node;
          }
        }
        //找到最小节点
        var findMinNode = function (node) {
          if (node) {
            while (node && node.left !== null) {
              node = node.left;
            }
            return node;
          }
          return null;
        }

完整代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>二叉树</title>
  </head>
  <body>
    <script>
      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 (newNode.key < node.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.inOrderTraverse = function (callback) {
          inOrderTraverseNode(root, callback);
        }
        var inOrderTraverseNode = function (node, callback) {
          if (node !== null) {
            inOrderTraverseNode(node.left, callback);
            callback(node.key);
            inOrderTraverseNode(node.right, callback);
          }
        }

        // 前序遍历
        this.preOrderTraverse = function (callback) {
          preOrderTraverseNode(root, callback);
        }
        var preOrderTraverseNode = function (node, callback) {
          if (node !== null) {
            callback(node.key);
            preOrderTraverseNode(node.left, callback);
            preOrderTraverseNode(node.right, callback);
          }
        }

        // 后序遍历
        this.postOrderTraverse = function (callback) {
          postOrderTraverseNode(root, callback);
        }
        var postOrderTraverseNode = function (node, callback) {
          if (node !== null) {
            postOrderTraverseNode(node.left, callback);
            postOrderTraverseNode(node.right, callback);
            callback(node.key);
          }
        }

        // 最小值
        this.min = function () {
          return minNode(root);
        }
        var minNode = function (node) {
          if (node) {
            while (node && node.left !== null) {
              node = node.left;
            }
            return node.key;
          }
          return null;
        }

        // 最大值
        this.max = function () {
          return maxNode(root);
        }
        var maxNode = function (node) {
          if (node) {
            while (node && node.right !== null) {
              node = node.right;
            }
            return node.key;
          }
          return null;
        }

        // 查找某个值
        this.search = function (key) {
          return searchNode(root, key);
        }
        var searchNode = function (node, key) {
          if (node == null) {
            return false;
          }
          if (key < node.key) {
            return searchNode(node.left, key);
          } else if (key > node.key) {
            return searchNode(node.right, key);
          } else {
            return true;
          }
        }

        // 删除末节点
        // this.remove = function (key) {
        //   root = removeNode(root, key);
        // }
        // var removeNode = function (node, key) {
        //   if (node === null) {
        //     return null;
        //   }
        //   if (key < node.key) {
        //     node.left = removeNode(node.left, key);
        //     return node;
        //   } else if (key > node.key) {
        //     node.right = removeNode(node.right, key);
        //     return node;
        //   } else {
        //     if (node.left === null && node.right === null) {
        //       node = null;
        //       return node;
        //     }
        //   }
        // }

        // 删除节点
        this.remove = function (key) {
          root = removeNode(root, key);
        }
        var removeNode = function (node, key) {
          if (node === null) {
            return null;
          }
          if (key < node.key) { // 小于此节点的key,node赋值为 node.left 继续遍历
            node.left = removeNode(node.left, key);
            return node;
          } else if (key > node.key) { // 大于此节点的key,node赋值为 node.right 继续遍历
            node.right = removeNode(node.right, key);
            return node;
          } else { // 等于此节点的key , 1 末节点 , 2 中间节点

            // 末节点直接把此key赋值为null
            if (node.left === null && node.right === null) {
              node = null;
              return node;
            }
            // 中间节点
            // 1,有right 或 left时,把此节点的left或right赋值为node = node.left 或 node = node.right
            if (node.left === null) {
              node = node.right;
              return node;
            } else if (node.right === null) {
              node = node.left;
              return node;
            }
            // 2,同时有right和left , 找到此节点右侧的最小值赋值  node = node.right的最小值
            var aux = findMinNode(node.right);
            node.key = aux.key;
            node.right = removeNode(node.right, aux.key);
            return node;
          }
        }
        //找到最小节点
        var findMinNode = function (node) {
          if (node) {
            while (node && node.left !== null) {
              node = node.left;
            }
            return node;
          }
          return null;
        }

      }
      var callback = function (key) {
        console.log(key);
      }

      var nodes = [8, 3, 10, 1, 6, 14, 4, 7, 13];
      var binaryTree = new BinaryTree();
      nodes.forEach(function (key) {
        binaryTree.insert(key);
      })
      console.log('------中序遍历---------')
      binaryTree.inOrderTraverse(callback);
      console.log('------前序遍历---------')
      binaryTree.preOrderTraverse(callback);
      console.log('------后序遍历---------')
      binaryTree.postOrderTraverse(callback);
      console.log('------最小值---------')
      console.log(binaryTree.min());
      console.log('------最大值---------')
      console.log(binaryTree.max());
      console.log('------某个值---------')
      console.log(binaryTree.search(3));
      console.log(binaryTree.search(2));
      // console.log('------删除末节点‘1’值---------')
      // binaryTree.remove(1);
      // binaryTree.postOrderTraverse(callback);
      console.log('------删除节点3---------')
      binaryTree.remove(3);
      binaryTree.postOrderTraverse(callback);
    </script>
  </body>
</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容