JavaScript で二分探索木を実装する

JavaScript で二分探索木を実装する

JavaScriptでの検索二分木実装は参考までに。具体的な内容は以下のとおりです。

バイナリ検索木 (BST)、バイナリソート木またはバイナリ検索木とも呼ばれる

二分探索木は空になる可能性のある二分木です。空でない場合は、次のプロパティを満たします。

  • 空でない左サブツリーのすべてのキー値は、そのルートノードのキー値よりも小さい
  • 空でない右サブツリーのすべてのキー値は、そのルートノードのキー値よりも大きい
  • つまり、左ノードの値 < ルートノードの値 < 右ノードの値
  • 左と右のサブツリーもバイナリ検索ツリーです。

二分探索木操作

insert(key) : ツリーに新しいキーを挿入する

search(key) : ツリー内のキーを検索し、ノードが存在する場合はtrueを返し、存在しない場合はfalseを返します。

inOrderTraverse : すべてのノードを順番に走査する

preOrderTraverse : 事前順序走査ですべてのノードを走査する

postOrderTraverse : すべてのノードを後順走査で走査する

min : ツリー内の最小の値/キーを返します

max : ツリー内の最大値/キーを返します

remove(key)

事前順序トラバーサル

  • ①ルートノードを訪問する
  • ② 左サブツリーの先行順序走査
  • ③ 右サブツリーの事前順序走査

順序通りの走査

① 左のサブツリーを順に走査する ② ルートノードを訪問する ③ 右のサブツリーを順に走査する

後順序トラバーサル

① 左サブツリーを後順で走査 ② 右サブツリーを後順で走査 ③ ルートノードを訪問

キュー構造を実装するJavaScriptコード

// BinarySearchTree を作成する
関数 BinarySerachTree() {
  // ノードコンストラクタ関数を作成する Node(key) {
    this.key = キー
    this.left = null
    this.right = null
  }

  // ルートプロパティを保存します this.root = null

  // 二分探索木関連の操作メソッド // 木にデータを挿入する BinarySerachTree.prototype.insert = function (key) {
    // 1. キーに応じて対応するノードを作成する
    var newNode = 新しいノード(キー)

    // 2. ルートノードに値があるかどうかを判定する if (this.root === null) {
      this.root = 新しいノード
    } それ以外 {
      this.insertNode(this.root、newNode) は、
    }
  }

  BinarySerachTree.prototype.insertNode = 関数 (ノード、newNode) {
    if (newNode.key < node.key) { // 1. 左のサブツリーにデータを挿入する準備をする if (node.left === null) { // 1.1. ノードの左のサブツリーにコンテンツがない node.left = newNode
      } else { // 1.2. ノードの左のサブツリーにはすでにコンテンツがあります this.insertNode(node.left, newNode)
      }
    } else { // 2. 右サブツリーにデータを挿入する準備をする if (node.right === null) { // 2.1. ノードの右サブツリーにコンテンツがない node.right = newNode
      } else { // 2.2. ノードの右サブツリーにコンテンツがある this.insertNode(node.right, newNode)
      }
    }
  }

  // 最大値と最小値を取得する BinarySerachTree.prototype.min = function () {
    var ノード = this.root
    (node.left !== null) の間 {
      ノード = ノード.左
    }
    ノードキーを返す
  }

  BinarySerachTree.prototype.max = 関数 () {
    var ノード = this.root
    (node.right !== null) の間 {
      ノード = ノード.right
    }
    ノードキーを返す
  }

  //特定の値を検索/*
  BinarySerachTree.prototype.search = 関数 (キー) {
    this.searchNode(this.root, key) を返します。
  }

  BinarySerachTree.prototype.searchNode = 関数 (ノード、キー) {
    // 1. 渡されたノードがnullの場合、再帰を終了します。if (node ​​=== null) {
      偽を返す
    }

    // 2. ノードの値と渡されたキーのサイズを決定します。if (node.key > key) { // 2.1. 渡されたキーの方が小さいので、左に検索を続けます。return this.searchNode(node.left, key)
    } else if (node.key < key) { // 2.2. 渡されたキーの方が大きい場合は、右方向に検索を続けます。 return this.searchNode(node.right, key)
    } else { // 2.3. 同じ、キーが見つかったことを示す
      真を返す
    }
  }
  */
  BinarySerachTree.prototype.search = 関数 (キー) {
    var ノード = this.root
    while (ノード ​​!== null) {
      (ノード.キー>キー)の場合{
        ノード = ノード.左
      } それ以外の場合 (node.key < key) {
        ノード = ノード.right
      } それ以外 {
        真を返す
      }
    }
    偽を返す
  }

  // 削除 nodeBinarySerachTree.prototype.remove = function (key) {
    // 1. 現在のノードを取得する
    var ノード = this.root
    var 親 = null

    // 2. ノードをループする
    while (ノード) {
      (ノードキー>キー)の場合{
        親 = ノード
        ノード = ノード.左
      } それ以外の場合 (node.key < key) {
        親 = ノード
        ノード = ノード.right
      } それ以外 {
        (node.left == null && node.right == null)の場合{

        }
      }
    }
  }

  BinarySerachTree.prototype.removeNode = 関数 (ノード、キー) {
    // 1. 渡されたノードが null の場合、再帰を直接終了します。
    if (node ​​=== null) は null を返す

    // 2. キーと対応するnode.keyのサイズを決定します。if (node.key > key) {
      node.left = this.removeNode(node.left, キー)

    }
  }

  // ノードを削除する BinarySerachTree.prototype.remove = function (key) {
    // 1. 一時保存変数を定義する var current = this.root
    var 親 = this.root
    var isLeftChild = true

    // 2. ノードの検索を開始する while (current.key !== key) {
      親 = 現在
      if (キー < 現在のキー) {
        左の子 = true
        現在の = 現在の左
      } それ以外 {
        isLeftChild = false
        現在の = 現在の右
      }

      // current がすでに null を指していることがわかった場合、削除するデータが見つからないことを意味します if (current === null) return false
    }

    // 3. 削除されたノードはリーフノードです if (current.left === null && current.right === null) {
      (現在の値 == this.root) の場合 {
        this.root == null
      } それ以外の場合 (isLeftChild) {
        親.左 = null
      } それ以外 {
        親.right = null
      }
    }

    // 4. 子ノードを1つ持つノードを削除します。else if (current.right === null) {
      (現在の値 == this.root) の場合 {
        this.root = 現在の左
      } それ以外の場合 (isLeftChild) {
        親.左 = 現在の.左
      } それ以外 {
        親.右 = 現在の.左
      }
    } それ以外の場合 (current.left === null) {
      (現在の値 == this.root) の場合 {
        this.root = 現在の右
      } それ以外の場合 (isLeftChild) {
        親.左 = 現在の.右
      } それ以外 {
        親.右 = 現在の.右
      }
    }

    // 5. 2つのノードを持つノードを削除します。else {
      // 1. 後継ノードを取得する var successor = this.getSuccessor(current)

      // 2. ルートノードかどうかを判定する if (current == this.root) {
        this.root = 後継
      } それ以外の場合は (isLeftChild) {
        親.左 = 後継
      } それ以外 {
        親.右 = 後継者
      }

      // 3. 削除されたノードの左サブツリーを後続ノードに割り当てる
      後継.左 = 現在の.左
    }

    真を返す
  }

  // 後継ノードを見つける methodBinarySerachTree.prototype.getSuccessor = function (delNode) {
    // 1. 変数を使用して一時ノードを保存する var successorParent = delNode
    var 後継者 = delNode
    var current = delNode.right // 右のサブツリーから開始 // 2. ノードを検索 while (current != null) {
      後継者親 = 後継者
      後継者 = 現在
      現在の = 現在の左
    }

    // 3. 図の15を削除する場合は、次のコードも必要です。if (successor != delNode.right) {
      後継親.左 = 後継右
      successor.right = delNode.right
    }
  }

  // トラバーサルメソッド // ハンドラはコールバック関数 // 事前順序トラバーサル BinarySerachTree.prototype.preOrderTraversal = function (handler) {
    this.preOrderTranversalNode(this.root、ハンドラー)
  }

  BinarySerachTree.prototype.preOrderTranversalNode = 関数 (ノード、ハンドラー) {
    if (ノード !== null) {
      ハンドラ(node.key)
      this.preOrderTranversalNode(node.left、ハンドラー)
      this.preOrderTranversalNode(node.right、ハンドラー)
    }
  }

  // 順序付きトラバーサルBinarySerachTree.prototype.inOrderTraversal = function (handler) {
    this.inOrderTraversalNode(this.root、ハンドラー)
  }

  BinarySerachTree.prototype.inOrderTraversalNode = 関数 (ノード、ハンドラー) {
    if (ノード !== null) {
      this.inOrderTraversalNode(node.left、ハンドラー)
      ハンドラ(node.key)
      this.inOrderTraversalNode(node.right、ハンドラー)
    }
  }

  // 後続のトラバーサルBinarySerachTree.prototype.postOrderTraversal = function (handler) {
    this.postOrderTraversalNode(this.root、ハンドラー)
  }

  BinarySerachTree.prototype.postOrderTraversalNode = 関数 (ノード、ハンドラー) {
    if (ノード !== null) {
      this.postOrderTraversalNode(node.left、ハンドラー)
      this.postOrderTraversalNode(node.right、ハンドラー)
      ハンドラ(node.key)
    }
  }
  
  /*
  // トラバーサル結果をテストします (inOrderTraversal は他のトラバーサル メソッドに置き換えることができます)
    結果文字列 = ""
    bst.inOrderTraversal(関数 (キー) {
      結果文字列 += キー + " "
    })
    アラート(結果文字列) // 3 5 6 7 8 9 10 11 12 13 14 15 18 20 25 
   */
}

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • JavaScript データ構造における二分探索木の実装方法
  • Javascriptは、小さな配列から大きな配列へのバイナリ検索ツリーの変換を実装します。
  • JavaScript アルゴリズムの二分探索木の例コード
  • JavaScript を使用して二分探索木を実装する方法
  • JavaScript 初心者のための二分探索木アルゴリズムのチュートリアル

<<:  nginx のバージョン番号と WEB サーバー情報を隠すための解決策

>>:  MySQL でデータベースを作成した後、ユーザー 'root'@'%' によるデータベース 'xxx' へのアクセスが拒否される問題を解決する

推薦する

Element-ui NavMenuサブメニューを使用して再帰的に生成する場合のエラーの詳細な説明

ナビゲーションバーのサブメニューを再帰的に生成すると、メニューは正常に生成できるが、マウスをホバーす...

Linux システム AutoFs 自動マウント サービスのインストールと構成

目次序文1. サービスプログラムをインストールする2. メイン設定ファイルを書く3. サブ構成ファイ...

Linux (Ubuntu 18.04) に vim エディタをインストールする方法

デスクトップ システムをダウンロードするには、Ubuntu の公式 Web サイト (https:/...

Dockerコンテナの紹介

Dockerの概要Docker はオープンソースのソフトウェア展開ソリューションです。 Docker...

MySQL のユニークインデックスと通常のインデックスのどちらを選択すればよいでしょうか?

ユーザー テーブルを設計するときに、各人の ID 番号が一意であり、検索する必要があるシナリオを想像...

HTML テーブル マークアップ チュートリアル (1): テーブルの作成

<br />これは 123WORDPRESS.COM が提供する一連のチュートリアルです...

CSS で要素を中央揃えにする N 通りの方法

目次序文インライン要素の中央揃えテキストを垂直に中央揃え要素を水平方向に中央揃えにするブロックレベル...

CenOS6.7 mysql 8.0.22 のインストールと設定方法のグラフィックチュートリアル

CenOS6.7 は MySQL8.0.22 (推奨コレクション) をインストールします1. MyS...

ウェブサイトのアクセス速度を向上させるための徹底的な最適化に関するヒント

<br />ウェブサイトのアクセス速度はウェブサイトのトラフィックに直接影響を及ぼし、ウ...

Dockerはjenkins+mavenコード構築および展開プラットフォームを構築します

目次Docker の基本概念Docker インストール プロセス (Centos6.9)カーネルのア...

MySQL インデックスがソートに与える影響の分析例

この記事では、例を使用して、MySQL インデックスがソートに与える影響を説明します。ご参考までに、...

JavaScript イベント ループのケース スタディ

js のイベント ループJavaScript はシングルスレッドなので、同じイベントで実行できるメソ...

MySQL 5.7.18 のインストール中に MySQL サービスの起動に失敗する問題の解決策

MySQL は非常に強力なリレーショナル データベースです。しかし、初心者の中には、インストールや設...

効率を向上できる Linux コマンドエイリアス 10 個のまとめ

序文Linux 環境で作業するエンジニアは、これらの面倒な命令とパラメータのコマンドラインにきっと驚...

JavaScript 以外の静的リソースのバンドルの詳細

目次1. パッケージングツールでのカスタムインポート2. ブラウザとバンドラの共通インポート構文3....