序文コンピュータ サイエンスでは、ツリーは広く使用されている抽象データ型 (ADT) であり、非線形データ構造の一種です。ツリー、特にバイナリツリーはコンピューター分野で広く使用されています。 ツリー関連の概念:
1. バイナリツリー概念: 各ノードに最大 2 つのサブツリーが含まれるツリーは、バイナリ ツリーと呼ばれます。 1.1. 二分木の走査バイナリ ツリーのトラバーサルには、深さトラバーサルと幅トラバーサルの 2 種類があります。深さトラバーサルには、事前順序、インオーダー、事後順序の 3 つのトラバーサル方法があります。 幅方向のトラバーサルは、レイヤーごとに順番にトラバーサルするレベル方向のトラバーサルです。 4 つのトラバーサルの主なアイデアは次のとおりです。
たとえば、a+b*(cd)-e/f という式はバイナリ ツリーで表されます。 それらを個別にトラバースします。
1.2. jsを使用してバイナリツリーを表現するバイナリ ツリーを表すには、js オブジェクトを使用します。オブジェクトには、left、value、right の 3 つのプロパティがあり、それぞれ左サブツリー、値、右サブツリーを表します。上記の例 a+b*(cd)-e/f は、js を使用して次のように表すことができます。 var ツリー = { 価値: '-'、 左: { 値: '+', 左: { 値: 'a' }, 右: 価値: '*'、 左: { 値: 'b' }, 右: 価値: '-'、 左: { 値: 'c' }, 右: 値: 'd' } } } }, 右: 価値: '/'、 左: { 値: 'e' }, 右: 値: 'd' } } } 1.3 事前順序探索アルゴリズム前書き: 方法は 2 つあります。最初の方法は非常に簡単で、再帰を直接使用する方法です。 関数 preOrder(treeNode) { if(ツリーノード) { console.log(treeNode.value); // 出力は、このノードにアクセスすることを意味します preOrder(treeNode.left); ツリーノードを右にプリオーダーします。 } } アルゴリズムは非常にシンプルです。まずルート ノードをトラバースし、次に左のサブツリーを再帰的にトラバースします。左のサブツリーをトラバースした後、右のサブツリーを再帰的にトラバースします。 2番目の非再帰的走査 関数 preOrder(treeNode) { if(ツリーノード) { var stack = [treeNode]; // バイナリツリーをスタックにプッシュします while (stack.length !== 0) { treeNode = stack.pop(); // スタックの先頭を取得します。 document.getElementById('text').appendChild(document.createTextNode(treeNode.value)); // ノードにアクセスします。 if(treeNode.right) stack.push(treeNode.right); // 右のサブツリーをスタックにプッシュします。 if(treeNode.left) stack.push(treeNode.left); // 左のサブツリーをスタックにプッシュします。 } } } 2 つ目は、スタックの考え方を使うことです。ご存知のとおり、スタックは先入れ後出しのデータ構造です。最初にルート ノードをスタックにプッシュし、次にスタックの先頭を取り、ルート ノードにアクセスして、右と左のサブツリーをそれぞれスタックにプッシュします。最初に左側からアクセスする必要があるため、右側を最初にスタックにプッシュする必要があります。そのため、最初に右側のサブツリーをスタックにプッシュし、次にスタックが空になるまでスタックを取り出すループを実行します。 1.4. 順序探索アルゴリズム順序再帰アルゴリズム: 関数InOrder(treeNode) { if(ツリーノード) { ツリーノードの左端に順序を付けます。 document.getElementById('text').appendChild(document.createTextNode(treeNode.value)); ツリーノードの右端に順序を付けます。 } } 事前順序再帰アルゴリズムと同じ考え方だが、訪問したノードの位置が異なる 2番目のタイプ: 関数InOrder(ノード) { if(ノード) { var stack = []; // 空のスタックを作成する // スタックが空でないかノードが空でない場合は、while (stack.length !== 0 || node) { をループします。 if (node) { //ノードが空でない場合 stack.push(node); //ノードをスタックにプッシュします node = node.left; //左のサブツリーを現在のノードとして使用します } else { //左のサブツリーが空です。つまり、左のサブツリーはありません node = stack.pop(); //ノードを取り出します document.getElementById('text').appendChild(document.createTextNode(node.value)); node = node.right; // 右ノードを現在のノードとして使用します} } } } 非再帰的順序アルゴリズムの考え方は、現在のノードをスタックにプッシュし、次に左のサブツリーをトラバースし、左のサブツリーが存在する場合は、左のサブツリーが空になるまでスタックにプッシュし続け、前のノードにアクセスし、右のサブツリーをスタックにプッシュすることです。 1.5. 後順序探索アルゴリズム1つ目: 再帰的トラバーサルアルゴリズム 関数 postOrder(ノード) { if (node) { // バイナリツリーが空かどうかを判断します postOrder(node.left); // 左のサブツリーを再帰的にトラバースします postOrder(node.right); // 右のサブツリーを再帰的にトラバースします document.getElementById('text').appendChild(document.createTextNode(node.value)); } } 2番目: 非再帰的トラバーサルアルゴリズム 関数 postOrder(ノード) { if (node) { //バイナリツリーが空かどうかを判断var stack = [node]; //バイナリツリーをスタックにプッシュvar tmp = null; //キャッシュ変数を定義while (stack.length !== 0) { //スタックが空でない場合はループしますtmp = stack[stack.length - 1]; //スタックの最上位の値をtmpに保存if (tmp.left && node !== tmp.left && node !== tmp.right) { //左のサブツリーがある場合、node !== tmp.left && node !== tmp.right は、左と右のサブツリーを繰り返しスタックにプッシュすることを回避するためですstack.push(tmp.left); //左のサブツリーノードをスタックにプッシュします} else if (tmp.right && node !== tmp.right) { //ノードに右のサブツリーがある場合stack.push(tmp.right); //右のサブツリーをスタックにプッシュします} else { document.getElementById('text').appendChild(document.createTextNode(stack.pop().value)); ノード = tmp; } } } } ここでは、最後にポップおよびプッシュされたノードを記録するために tmp 変数が使用されます。アイデアとしては、まずルート ノードと左のツリーをスタックにプッシュし、次に左のツリーを取り出し、右のツリーをプッシュして取り出し、最後にルート ノードを取り出すというものです。 以下は、このアルゴリズムを使用して前のバイナリツリーをトラバースするプロセスです。
1.6. レイヤーごとのトラバーサルアルゴリズム関数breadthTraversal(ノード) { if (node) { //バイナリツリーが空かどうかを判断var que = [node]; //バイナリツリーをキューに入れますwhile (que.length !== 0) { //キューが空かどうかを判断node = que.shift(); //キューからノードを取得しますdocument.getElementById('text').appendChild(document.createTextNode(node.value)); //取得したノードの値を配列に保存しますif (node.left) que.push(node.left); //左のサブツリーが存在する場合は、左のサブツリーをキューに入れますif (node.right) que.push(node.right); //右のサブツリーが存在する場合は、右のサブツリーをキューに入れます} } } 配列を使用してキューをシミュレートし、最初にルート ノードをキューに配置します。キューが空でない場合は、ループを実行します。キューからノードを取り出し、ノードに左サブツリーがある場合は、ノードの左サブツリーをキューに格納します。ノードに右サブツリーがある場合は、ノードの右サブツリーをキューに格納します。 2. アルゴリズムに関する質問1.1. 二分木の最大深さバイナリツリーが与えられた場合、その最大深さを見つけます。 バイナリ ツリーの深さは、ルート ノードから最も遠いリーフ ノードまでの最長パス上のノードの数です。 たとえば、次のバイナリ ツリーは深さ 3 を返します。
再帰アルゴリズム:再帰アルゴリズムの考え方は非常にシンプルです。まず、左のサブツリーの最も深い層を取得し、次に右のサブツリーの最も深い層を取得し、それらの最大値がツリーの深さになります。 var maxDepth = function(ルート) { ルートの場合 0を返します。 } 定数 leftDeep = maxDepth(root.left) + 1; 定数 rightDeep = maxDepth(root.right) + 1; Math.max(leftDeep, rightDeep) を返します。 }; /* 最大深度(ルート) = 最大深度(ルート.左) + 1 = 2 最大深度(ルート.左) = 最大深度(ルート.左.左) + 1 = 1 最大深度(ルートの左端) = 0; 最大深度(ルート) = 最大深度(ルート.右) + 1 = 3 最大深度(ルート.右) = 最大深度(ルート.右.右) + 1 = 2 最大深度(ルート.右.右) = 最大深度(ルート.右.右.右) + 1 = 1 最大深度(ルート右右右) = 0 */ 1.2. 二分木のすべてのパスバイナリ ツリーが与えられた場合、ルート ノードからリーフ ノードまでのすべてのパスを返します。 例えば:
再帰メソッドの使用: var binaryTreePaths = function(ルート) { if (!root) は [] を返します。 定数res = []; 関数 dfs(curNode, curPath) { if(!curNode.left && !curNode.right) { res.push(curPath); } 左のノードの場合 dfs(curNode.left, `${curPath}->${curNode.left.value}`) } 右のノードの場合 dfs(curNode.right、`${curPath}->${curNode.right.value}`) } } dfs(ルート、`${root.value}`); res を返します。 }; 要約するJS を使用してバイナリ ツリー トラバーサル アルゴリズムを実装する方法に関するこの記事はこれで終わりです。JS バイナリ ツリー トラバーサル アルゴリズムに関する関連コンテンツをさらにご覧になりたい場合は、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
>>: MySQL マスタースレーブレプリケーションと読み取り書き込み分離の詳細な説明
vue コンポーネントのスタイル タグ内には、背景画像を使用する次の CSS コードがあります。 背...
Ubuntuでsshを開くのに1時間以上かかりました。主な原因は、最初に読んだチュートリアルの手順...
最近、vue について読みました。これまで基本的に見落としていた単一ファイル コンポーネントを見つけ...
<br />1998年に最初の個人ページが誕生してから2008年の今日まで、デザイン業界...
MySQL バッチ挿入の問題プロジェクトを開発しているときに、古いシステムの基本データを事前にインポ...
この記事は議論の出発点となることを目的としています。詳細なドキュメントと easycom の仕様につ...
Linux や Unix の cut コマンドは、ファイルの各行から一部を切り取って標準出力に出力す...
ウェブサイト機能を開発する場合、セッション キャッシュを時間内にクリアできません。一連の探索が始まり...
仮想化とコンテナ化は、クラウドベースのプロジェクトでは避けられない 2 つの問題です。仮想化は純粋な...
Dockerコンテナを使用する場合は、nsenterツールを使用する方が便利です。システムにない場合...
MySQL をインストールした後、初めてmysql -uroot -pを実行したときに、root パ...
方法1: SET PASSWORDコマンドを使用する MySQL -u ルート mysql> ...
目次1件のレビュー2 水平分割の5つの戦略2.1 ハッシュ2.2 範囲2.3. キー2.4. リスト...
一般的に、URL に基づいてファイルをダウンロードする場合、次の 2 つの解決策があります。 1. ...
序文Linux システムはシステム サービス crond によって制御されます。 Linux システ...