【JSデータ構造とアルゴリズム】二分探索木の一般的な方法

目次

1.二分木の構造カプセル化を導入します

2、挿入挿入(キー)

第三に、二分木のトラバーサル法

1.一次走査

2.順序どおりのトラバーサル

3.注文後のトラバーサル

第四に、二分探索木は最良の値を見つけます

キーを見つけるための5つの二分探索木

6、二分探索木削除ノード

7つの完全なコード


1.二分木の構造カプセル化を導入します

function BinarySearchTree(){

      // 新结点创建的构造函数
      function Node(key){
        this.key = key;
        this.lchild = null;
        this.rchild = null;
      }

      // 保存根的属性
      this.root = null;

      // 创建关于二叉搜索树的相关操作方法

}

2、挿入挿入(キー)

アイデア:

挿入メソッドを作成する

    1.新しいノードを作成します

    2.空のツリーかどうかを判断します
         。2.1空のツリーの場合は、ルートの属性が新しいノードを指すようにします
         。2.2空でないツリーでない場合は、挿入する適切な場所を見つけます。

次に、内部使用のメソッドを作成します。insertNode()
。1、新しい
       ノードの値が小さな
               挿入空の右サブツリーノードの比較のノード値よりも大きい場合は、新しいノードとノードサイズの値1.1を比較します。続行する必要はありません。右側の比較を空にする
       1.2ノードの値よりも新しいノードの値が大きい場合、ノードの
                左側のサブツリーを比較して、左側の比較を空にし続けない

次のツリーで、20ノードを挿入する場合は、次の手順を実行します。

コード:

      // 插入元素,给用户使用
      BinarySearchTree.prototype.insert = function(key){
        // 1、创建新结点
        var newNode = new Node(key);

        // 2、判断是否为空树
        // 2.1如果是空树,则让根的属性指向新结点
        if (this.root == null){
          this.root = newNode;
        }else{// 2.2如果不是非空树,则寻找合适的位置插入
          this.insertNode(this.root, newNode);
        }
      }

      // 用于内部使用
      BinarySearchTree.prototype.insertNode = function(node, newNode){

        // 1、比较结点与新结点的值大小
        // 1.1如果结点的值比新结点的值小
        if (node.key < newNode.key) {
          // 比较结点的右子树为空时插入,不为空时继续往下比较
          if (node.rchild == null) {
            node.rchild = newNode;
          }else{
            this.insetNode(node.rchild, newNode);
          }
        }else{ // 1.2 如果结点的值比新结点的值大
          // 比较结点的左子树为空时插入,不为空时继续往下比较
          if (node.lchild == null) {
            node.lchild = newNode;
          }else{
            this.insertNode(node.lchild, newNode);
          }
        }
      }

コードテスト

    // 测试
    // 1、创建BinarySearchTree
    var bst = new BinarySearchTree();

    // 2、插入数据
    bst.insert(18);
    bst.insert(4);
    bst.insert(2);
    bst.insert(7);
    bst.insert(30);
    bst.insert(24);
    bst.insert(20);

    // 3、输出结构
    console.log(bst);

          -》

第三に、二分木のトラバーサル法

二分探索木の探索は、二分木の探索です。各ノードを探索する場合は、特定の順序で探索する必要があります。

二分木には3つの一般的な方法があります。

  • プレオーダートラバーサル
  • 順序どおりの走査
  • 注文後のトラバーサル

もう1つの珍しいトラバーサルは、ツリーの各レベルに応じて、上から下に左から右にトラバースする階層トラバーサルです。

1.一次走査

操作の定義:

二分木が空の場合、操作はありません。それ以外の場合。

(1)ルートノードにアクセスします。

(2)最初に左側のサブツリーをトラバースします。

(3)最初に右側のサブツリーをトラバースします。

                             

コード:

      // 先序遍历
      BinarySearchTree.prototype.preOrderTraversal = function(fun){
        // 让preOrderTraversalNode去实现递归操作
        this.preOrderTraversalNode(this.root, fun)
      }

      // 内部使用
      BinarySearchTree.prototype.preOrderTraversalNode = function(node, fun){

        if (node) {
          // 1、打印当前结点
          fun(node.key);

          // 2、遍历所有的左子树;
          this.preOrderTraversalNode(node.lchild, fun);

          // 3、遍历所有的右子树。
          this.preOrderTraversalNode(node.rchild, fun);
        }
      }

テストコード

// 测试
    // 1、创建BinarySearchTree
    var bst = new BinarySearchTree();

    // 2、插入数据
    bst.insert(18);
    bst.insert(4);
    bst.insert(2);
    bst.insert(7);
    bst.insert(30);
    bst.insert(24);
    bst.insert(20);

    // 3、先序遍历
    var result = '';
    bst.preOrderTraversal(function (key){
      result += key + ' ';
    })
    console.log(result); //18 4 2 7 30 24 20 

2.順序どおりのトラバーサル

操作の定義:

二分木が空の場合、操作はありません。それ以外の場合。

(1)左側のサブツリーをトラバースするため。

(2)ルートノードにアクセスします。

(3)右側のサブツリーをトラバースするため。

                             

コード:

      // 中序遍历
      BinarySearchTree.prototype.midOrderTraversal = function(fun){
        // 让midOrderTraversalNode去实现递归操作
        this.midOrderTraversal(this.root, fun)
      }

      // 内部使用
      BinarySearchTree.prototype.midOrderTraversalNode = function(node, fun){

        if (node) {

          // 1、遍历所有的左子树;
          this.midOrderTraversalNode(node.lchild, fun);

          // 2、打印当前结点
          fun(node.key);

          // 3、遍历所有的右子树。
          this.midOrderTraversalNode(node.rchild, fun);
        }
      }

テストコード

// 测试
    // 1、创建BinarySearchTree
    var bst = new BinarySearchTree();

    // 2、插入数据
    bst.insert(18);
    bst.insert(4);
    bst.insert(2);
    bst.insert(7);
    bst.insert(30);
    bst.insert(24);
    bst.insert(20);

    // 3、中序遍历
    var result = '';
    bst.midOrderTraversal(function (key){
      result += key + ' ';
    })
    console.log(result); //2 4 7 18 20 24 30 

3.注文後のトラバーサル

操作の定義:

二分木が空の場合、操作はありません。それ以外の場合。

(1)左のサブツリーをポストオーダーでトラバースします。

(2)ポストオーダーで右側のサブツリーをトラバースします。

(3)ルートノードにアクセスします。

                             

コード:

      // 后序遍历
      BinarySearchTree.prototype.postOrderTraversal = function(fun){
        // 让postOrderTraversalNode去实现递归操作
        this.postOrderTraversalNode(this.root, fun)
      }

      // 内部使用
      BinarySearchTree.prototype.postOrderTraversalNode = function(node, fun){

        if (node) {

          // 1、遍历所有的左子树;
          this.postOrderTraversalNode(node.lchild, fun);

          // 2、遍历所有的右子树。
          this.postOrderTraversalNode(node.rchild, fun);

          // 3、打印当前结点
          fun(node.key);
        }
      }

テストコード

// 测试
    // 1、创建BinarySearchTree
    var bst = new BinarySearchTree();

    // 2、插入数据
    bst.insert(18);
    bst.insert(4);
    bst.insert(2);
    bst.insert(7);
    bst.insert(30);
    bst.insert(24);
    bst.insert(20);

    // 3、先序遍历
    var result1 = '';
    bst.preOrderTraversal(function (key){
      result1 += key + ' ';
    })
    console.log(result1); //18 4 2 7 30 24 20 

    // 4、中序遍历
    var result2 = '';
    bst.midOrderTraversal(function (key){
      result2 += key + ' ';
    })
    console.log(result2); //2 4 7 18 20 24 30 


    // 5、后序遍历
    var result3 = '';
    bst.postOrderTraversal(function (key){
      result3 += key + ' ';
    })
    console.log(result3); //2 7 4 20 24 30 18 

第四に、二分探索木は最良の値を見つけます

ツリーが空の場合、最大値はありません。

ツリーが空でない場合

  • ルートノードから開始する必要があり、最後のものが最も大きな値であることを正しく見つけます。
  • 最後が最も小さいを見つけるために、のルートから開始する必要があります。

コード:

      // 最大值
      BinarySearchTree.prototype.max = function(){
        var node = this.root;

        var key = null;
        while(node){
          key = node.key;
          node = node.rchild;
        }
        return key;
      }

      // 最小值
      BinarySearchTree.prototype.min = function(){
        var node = this.root;

        var key = null;
        while(node){
          key = node.key;
          node = node.lchild;
        }
        return key;
      }

キーを見つけるための5つの二分探索木

キーの検索は、アイテムを挿入するときの検索と非常によく似ています。ここでは、ループを使用してコードを記述します。

      // 查找某个key
      BinarySearchTree.prototype.searchKey = function(key){
        var node = this.root;

        while(node != null){
          if (node.key < key) {
            node = node.rchild;
          }else if (node.key > key) { 
            node = node.lchild;
          }else{
            return true;
          }
        }
        return false;
      }

 

6、二分探索木削除ノード

二分探索木のノード削除操作は、状況が多いので、少しずつ分析していくので、非常に複雑だということを先ほど申し上げましたが、操作はわかりにくくなく、最も重要なことです。それをよく考えることです。二分木の構造については、削除されたノードによって接続されたサブノードの数を3つのケースに分けます。

ケース1:削除されたノードには子ノードがありません(つまり、リーフノードです)。

ケース2:削除されたノードに子ノードがあります。

状況3:削除されたノードには2つの子ノードがあります。

特定の手順:

1.削除するノードを見つけます。

  • 1.1変数を定義し、情報を保存します。

currentはルートノードを保存します。

レコードは、ノードの親ノードを削除します。

isLeftChildは、削除されたノードが親ノードの左の子ノードであるかどうかを判別します。

var current = this.root; // 保存根结点
var parent = null;   // 记录删除结点的父节点
var isLeftChild = true;   //判断删除的结点是否是该父结点的左子结点

 

  • 1.2削除するノードを見つけ、最後のノードが見つかった場合は終了します。
// 1.2 查找要删除的结点
while(current.key != key){
  parent = current;
  if (key < current.key) {
    isLeftChild = true;
    current = current.lchild;
  }else{
    isLeftChild = false;
    current = current.rchild;
  }

  // 已经找到最后一个结点还没有找到就退出
  if (current == null) return false;
}

 

2.ノードを見つけて、対応する状況に応じてノードを削除します。

  • 2.1ケース1:削除されたノードはリーフノードです(つまり、子ノードはありません)。

①ツリーにルートノードが1つしかない場合は、それを削除するだけです。

②ツリーに複数のノードがあり、リーフノードを削除した場合、削除するノードの親ノードに応じてポインタフィールドを空にすることができます。

// 2.1删除的结点是叶子结点(即没有子结点)
if (current.lchild == null && current.rchild == null) {
  if (current == this.root) {
    this.root = null;
  } else if (isLeftChild) {
    parent.lchild = null;
  } else {
    parent.rchild = null;
  }
}

 

  • 2.2ケース2:削除されたノードには子ノードがあります。

①削除されたノードがルートノードです。this.rootを削除するノードの子ノードにポイントします。

②削除されたノードがルートノードではありません。4つの特定の状況があります。

else if (current.rchild == null) {
  if (current == this.root) {
    this.root = current.lchild;
  } else if (isLeftChild) {
    parent.lchild = current.lchild;
  } else {
    parent.rchild = current.lchild;
  }
} else if (current.lchild == null) {
  if (current == this.root) {
    this.root = current.rchild;
  } else if (isLeftChild) {
    parent.lchild = current.rchild;
  } else {
    parent.rchild = current.rchild;
  }
}

 

  • 2.3ケース3:削除されたノードには2つの子ノードがあります。

削除するノードに2つの子ノードがある場合、子ノードにまだノードが残っている可能性があるため、削除したノードを置き換えるノードを見つける必要があります。

削除されたノードより少し大きいもの、または削除されたノードより少し小さいもの、つまり削除されたノードに最も近い置換ノードを見つけることができます。

次に、次のことを行う必要があります。

削除されたノードより少し小さい値は、削除されたノードの左側のサブツリーの最大値(先行)である必要があります

削除されたノードよりわずかに大きい値は、削除されたノードの右側のサブツリーの最小値(後続)である必要があります

ここでは、その後のノードの検索と置換の方法を使用します

①削除されたノードがルートノードであり、this.rootを置換するノードにポイントし、置換されたノードの親ノードを右側のノードに接続します。

②削除されたノードがルートノードではありません。

// 2.3删除的结点两个子结点
else {
  // 1、寻找后继
  var replaceNode = this.getReplaceNode(current);

  // 2、判断是否是根结点
  if (current == this.root) {
    this.root = replaceNode;
  } else if (isLeftChild) {
    parent.lchild = replaceNode;
  } else {
    parent.rchild = replaceNode;
  }

  // 3、将替代的结点的左子树  = 删除结点的左子树
  replaceNode.lchild = current.lchild;
}
// 找后继的方法
BinarySearchTree.prototype.getReplaceNode = function (delNode) {

  // 1、定义变量,来保存找到的后继
  var replaceNode = delNode; // 替代的结点
  var previous = delNode.rchild;  //删除结点的右结点
  var replaceParent = delNode;

  // 2、循环查找
  while(previous != null){
    replaceParent = replaceNode;
    replaceNode = previous;
    previous = previous.lchild;
  }

  // 3、判断找到的替换结点(后继)是否就是delNode的rchild结点,如果是则填补结点
  if (replaceNode != delNode.rchild) {
    // 后继结点必定是小于两个子结点的结点,将后继结点的父结点的左结点指向替代结点的右结点,连接操作。
    replaceParent.lchild = replaceNode.rchild;
    // 替换
    replaceNode.rchild = delNode.rchild;
  }
  return replaceNode;
}

 

コードテスト:

    // 测试
    // 1、创建BinarySearchTree
    var bst = new BinarySearchTree();

    // 2、插入数据
    bst.insert(18);
    bst.insert(4);
    bst.insert(2);
    bst.insert(7);
    bst.insert(30);
    bst.insert(24);
    bst.insert(20);

    // 3、先序遍历
    var result1 = '';
    bst.preOrderTraversal(function (key){
      result1 += key + ' ';
    })
    console.log('先序遍历:' + result1); //18 4 2 7 30 24 20 

 

18を削除

    // 6、删除操作
    // 删除根结点18
    bst.remove(18);

    // 先序遍历
    var result4 = '';
    bst.preOrderTraversal(function (key){
      result4 += key + ' ';
    })
    console.log('先序遍历为18 4 2 7 30 24 20 ,删除结点18后得到先序遍历结果:' + result4); 
    //先序遍历为18 4 2 7 30 24 20 ,删除结点18后得到先序遍历结果:20 4 2 7 30 24 

    // 插入数据
    bst.insert(26);
    bst.insert(21);
    bst.insert(25);
    bst.insert(27);

    //  先序遍历
    var result5 = '';
    bst.preOrderTraversal(function (key){
      result5 += key + ' ';
    })
    console.log('在先序为20 4 2 7 30 24 的二叉树搜索树中插入26、21、25、27,得到先序遍历结果:' + result5); 
    //在先序为20 4 2 7 30 24 的二叉树搜索树中插入26、27、28、29,得到先序遍历结果:20 4 2 7 30 24 21 26 25 27 

24を削除

    // 删除结点24
    bst.remove(24);

    // 先序遍历
    var result6 = '';
    bst.preOrderTraversal(function (key){
      result6 += key + ' ';
    })
    console.log('先序遍历为20 4 2 7 30 24 21 26 25 27 ,删除结点24后得到先序遍历结果:' + result6); 
    //先序遍历为20 4 2 7 30 24 21 26 25 27 ,删除结点24后得到先序遍历结果:20 4 2 7 30 25 21 26 27 

フルプリント

7つの完全なコード

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>二叉搜索树的相关方法</title>
</head>
<body>
  <script type="text/javascript">
    function BinarySearchTree(){

      // 新结点创建的构造函数
      function Node(key){
        this.key = key;
        this.lchild = null;
        this.rchild = null;
      }

      // 保存根的属性
      this.root = null;

      // 创建关于二叉搜索树的相关操作方法

      // 插入元素,给用户使用
      BinarySearchTree.prototype.insert = function(key){
        // 1、创建新结点
        var newNode = new Node(key);

        // 2、判断是否为空树
        // 2.1如果是空树,则让根的属性指向新结点
        if (this.root == null){
          this.root = newNode;
        }else{// 2.2如果不是非空树,则寻找合适的位置插入
          this.insertNode(this.root, newNode);
        }
      }

      // 用于内部使用
      BinarySearchTree.prototype.insertNode = function(node, newNode){

        // 1、比较结点与新结点的值大小
        // 1.1如果结点的值比新结点的值小
        if (node.key < newNode.key) {
          // 比较结点的右子树为空时插入,不为空时继续往下比较
          if (node.rchild == null) {
            node.rchild = newNode;
          }else{
            this.insertNode(node.rchild, newNode);
          }
        }else{ // 1.2 如果结点的值比新结点的值大
          // 比较结点的左子树为空时插入,不为空时继续往下比较
          if (node.lchild == null) {
            node.lchild = newNode;
          }else{
            this.insertNode(node.lchild, newNode);
          }
        }
      }

      // 先序遍历
      BinarySearchTree.prototype.preOrderTraversal = function(fun){
        // 让preOrderTraversalNode去实现递归操作
        this.preOrderTraversalNode(this.root, fun)
      }

      // 内部使用
      BinarySearchTree.prototype.preOrderTraversalNode = function(node, fun){

        if (node) {
          // 1、打印当前结点
          fun(node.key);

          // 2、遍历所有的左子树;
          this.preOrderTraversalNode(node.lchild, fun);

          // 3、遍历所有的右子树。
          this.preOrderTraversalNode(node.rchild, fun);
        }
      }

      // 中序遍历
      BinarySearchTree.prototype.midOrderTraversal = function(fun){
        // 让midOrderTraversalNode去实现递归操作
        this.midOrderTraversalNode(this.root, fun)
      }

      // 内部使用
      BinarySearchTree.prototype.midOrderTraversalNode = function(node, fun){

        if (node) {

          // 1、遍历所有的左子树;
          this.midOrderTraversalNode(node.lchild, fun);

          // 2、打印当前结点
          fun(node.key);

          // 3、遍历所有的右子树。
          this.midOrderTraversalNode(node.rchild, fun);
        }
      }

      // 后序遍历
      BinarySearchTree.prototype.postOrderTraversal = function(fun){
        // 让postOrderTraversalNode去实现递归操作
        this.postOrderTraversalNode(this.root, fun)
      }

      // 内部使用
      BinarySearchTree.prototype.postOrderTraversalNode = function(node, fun){

        if (node) {

          // 1、遍历所有的左子树;
          this.postOrderTraversalNode(node.lchild, fun);

          // 2、遍历所有的右子树。
          this.postOrderTraversalNode(node.rchild, fun);

          // 3、打印当前结点
          fun(node.key);
        }
      }

      // 最大值
      BinarySearchTree.prototype.max = function(){
        var node = this.root;

        var key = null;
        while(node){
          key = node.key;
          node = node.rchild;
        }
        return key;
      }

      // 最小值
      BinarySearchTree.prototype.min = function(){
        var node = this.root;

        var key = null;
        while(node){
          key = node.key;
          node = node.lchild;
        }
        return key;
      }

      // 查找某个key
      BinarySearchTree.prototype.searchKey = function(key){
        var node = this.root;

        while(node != null){
          if (node.key < key) {
            node = node.rchild;
          }else if (node.key > key) { 
            node = node.lchild;
          }else{
            return true;
          }
        }
        return false;
      }

      // 删除某个结点
      BinarySearchTree.prototype.remove = function(key){
        // 1、寻找要删除的结点
        // 1.1 定义变量,保存信息
        var current = this.root; // 保存根结点
        var parent = null;   // 记录删除结点的父节点
        var isLeftChild = true;   //判断删除的结点是否是该父结点的左子结点

        // 1.2 查找要删除的结点
        while(current.key != key){
          parent = current;
          if (key < current.key) {
            isLeftChild = true;
            current = current.lchild;
          }else{
            isLeftChild = false;
            current = current.rchild;
          }

          // 已经找到最后一个结点还没有找到就退出
          if (current == null) return false;
        }

        // 2、根据对应的情况删除结点
        // 2.1删除的结点是叶子结点(即没有子结点)
        if (current.lchild == null && current.rchild == null) {
          if (current == this.root) {
            this.root = null;
          } else if (isLeftChild) {
            parent.lchild = null;
          } else {
            parent.rchild = null;
          }
        }

        // 2.2删除的结点有一个子结点
        else if (current.rchild == null) {
          if (current == this.root) {
            this.root = current.lchild;
          } else if (isLeftChild) {
            parent.lchild = current.lchild;
          } else {
            parent.rchild = current.lchild;
          }
        } else if (current.lchild == null) {
          if (current == this.root) {
            this.root = current.rchild;
          } else if (isLeftChild) {
            parent.lchild = current.rchild;
          } else {
            parent.rchild = current.rchild;
          }
        }

        // 2.3删除的结点两个子结点
        else {
          // 1、寻找后继
          var replaceNode = this.getReplaceNode(current);

          // 2、判断是否是根结点
          if (current == this.root) {
            this.root = replaceNode;
          } else if (isLeftChild) {
            parent.lchild = replaceNode;
          } else {
            parent.rchild = replaceNode;
          }

          // 3、将替代的结点的左子树  = 删除结点的左子树
          replaceNode.lchild = current.lchild;
        }
      }

      // 找后继的方法
      BinarySearchTree.prototype.getReplaceNode = function (delNode) {

        // 1、定义变量,来保存找到的后继
        var replaceNode = delNode; // 替代的结点
        var previous = delNode.rchild;  //删除结点的右结点
        var replaceParent = delNode;

        // 2、循环查找
        while(previous != null){
          replaceParent = replaceNode;
          replaceNode = previous;
          previous = previous.lchild;
        }

        // 3、判断找到的替换结点(后继)是否就是delNode的rchild结点,如果是则填补结点
        if (replaceNode != delNode.rchild) {
          // 后继结点必定是小于两个子结点的结点,将后继结点的父结点的左结点指向替代结点的右结点,连接操作。
          replaceParent.lchild = replaceNode.rchild;
          // 替换
          replaceNode.rchild = delNode.rchild;
        }
        return replaceNode;
      }
    }

    // 测试
    // 1、创建BinarySearchTree
    var bst = new BinarySearchTree();

    // 2、插入数据
    bst.insert(18);
    bst.insert(4);
    bst.insert(2);
    bst.insert(7);
    bst.insert(30);
    bst.insert(24);
    bst.insert(20);

    // 3、先序遍历
    var result1 = '';
    bst.preOrderTraversal(function (key){
      result1 += key + ' ';
    })
    console.log('先序遍历:' + result1); //18 4 2 7 30 24 20 

    // 4、中序遍历
    var result2 = '';
    bst.midOrderTraversal(function (key){
      result2 += key + ' ';
    })
    console.log('中序遍历:' + result2); //2 4 7 18 20 24 30 


    // 5、后序遍历
    var result3 = '';
    bst.postOrderTraversal(function (key){
      result3 += key + ' ';
    })
    console.log('后序遍历:' + result3); //2 7 4 20 24 30 18 


    console.log('最大值是' + bst.max());
    console.log('最小值是' + bst.min());
    console.log('是否存在24?' + bst.searchKey(24)); //true
    console.log('是否存在30?' + bst.searchKey(30)); //true
    console.log('是否存在5?' + bst.searchKey(5)); //false
    console.log('是否存在8?' + bst.searchKey(8)); //false
    console.log('是否存在500?' + bst.searchKey(500)); //false


    // 6、删除操作
    // 删除根结点18
    bst.remove(18);

    // 先序遍历
    var result4 = '';
    bst.preOrderTraversal(function (key){
      result4 += key + ' ';
    })
    console.log('先序遍历为18 4 2 7 30 24 20 ,删除结点18后得到先序遍历结果:' + result4); 
    //先序遍历为18 4 2 7 30 24 20 ,删除结点18后得到先序遍历结果:20 4 2 7 30 24 

    // 插入数据
    bst.insert(26);
    bst.insert(21);
    bst.insert(25);
    bst.insert(27);

    // 先序遍历
    var result5 = '';
    bst.preOrderTraversal(function (key){
      result5 += key + ' ';
    })
    console.log('在先序为20 4 2 7 30 24 的二叉树搜索树中插入26、21、25、27,得到先序遍历结果:' + result5); 
    //在先序为20 4 2 7 30 24 的二叉树搜索树中插入26、27、28、29,得到先序遍历结果:20 4 2 7 30 24 21 26 25 27 

    // 删除结点24
    bst.remove(24);

    // 先序遍历
    var result6 = '';
    bst.preOrderTraversal(function (key){
      result6 += key + ' ';
    })
    console.log('先序遍历为20 4 2 7 30 24 21 26 25 27 ,删除结点24后得到先序遍历结果:' + result6); 
    //先序遍历为20 4 2 7 30 24 21 26 25 27 ,删除结点24后得到先序遍历结果:20 4 2 7 30 25 21 26 27 
  </script>

</body>
</html>

 

おすすめ

転載: blog.csdn.net/weixin_42339197/article/details/99845315