JSでのバイナリツリートラバーサルの詳細な説明
二分木はルートノード、左サブツリー、右サブツリーで構成されます。左サブツリーとフレンドサブツリーはそれぞれ二分木です。
この記事では主に JS でバイナリ ツリー トラバーサルを実装します。
バイナリ ツリーの例
var tree = { value: 1, left: { value: 2, left: { value: 4 } }, right: { value: 3, left: { value: 5, left: { value: 7 }, right: { value: 8 } }, right: { value: 6 } } }
幅優先トラバーサル
幅優先トラバーサルは、バイナリ ツリーの最初のレベル (ルート ノード) から開始し、同じレベル内で上から下にレベルごとにトラバースし、ノードは左から右の順に 1 つずつアクセスされます。
実装:
配列を使用してキューをシミュレートします。まずルートノードをキューに入れます。キューが空でない場合は、ループを実行します。キューからノードを取り出し、ノードの左側のサブツリーが空でない場合は、ノードの右側のサブツリーが空の場合、ノードの左側のサブツリーをキューに入れます。空でない場合は、ノードの右のサブツリーをキューに入れます。
(説明がちょっとわかりにくいのでコードを見てください。)
var levelOrderTraversal = function(node) { if(!node) { throw new Error('Empty Tree') } var que = [] que.push(node) while(que.length !== 0) { node = que.shift() console.log(node.value) if(node.left) que.push(node.left) if(node.right) que.push(node.right) } }
再帰走査
のような気がしますこれらの文字を使用する 再帰的走査を表現するには 3 つの適切な方法があります:
D: ルート ノードにアクセスする、L: ルート ノードの左側のサブツリーを走査する、R: ルート ノードの右側のサブツリーを走査する。
プリオーダートラバーサル: DLR
インオーダートラバーサル: LDR
ポストオーダートラバーサル: LRD
文字の意味に従うと、順序は ^ ^
これら 3 種類のトラバーサルはすべて、常に
より深いところにアクセスするため、再帰的トラバーサル、または深さ優先トラバーサル (深さ優先検索、DFS) です。
事前順序走査の再帰アルゴリズム:
var preOrder = function (node) { if (node) { console.log(node.value); preOrder(node.left); preOrder(node.right); } }
順走査の再帰アルゴリズム:
var inOrder = function (node) { if (node) { inOrder(node.left); console.log(node.value); inOrder(node.right); } }
事後探索の再帰アルゴリズム:
var postOrder = function (node) { if (node) { postOrder(node.left); postOrder(node.right); console.log(node.value); } }
非再帰的な深さ優先探索
実のところ、これらの概念が誰のものなのかはわかりません。一部の本では、バイナリ ツリー トラバーサルに関する上記 3 つの再帰トラバーサルについてのみ説明しています。一部のものは幅優先トラバーサルと深さ優先トラバーサルの 2 つのタイプに分類され、再帰的トラバーサルは深さ優先トラバーサルに分類されます。また、非再帰トラバーサルには幅優先トラバーサルが含まれます。そして次の縦走路。個人的には、メソッドと使用方法をマスターしている限り、分割方法は問題ではありません:)
これに対応して、この非再帰的な深さでは、幅優先トラバーサルで使用したのはキューです。 -first トラバーサルでは、 stack を使用します。 JS でシミュレートするには引き続き配列を使用します。
ここでは予約注文についてのみ説明します。
このアルゴリズムについて説明しようとしましたが、コードに従うだけで理解できるでしょう。
var preOrderUnRecur = function(node) { if(!node) { throw new Error('Empty Tree') } var stack = [] stack.push(node) while(stack.length !== 0) { node = stack.pop() console.log(node.value) if(node.right) stack.push(node.right) if(node.left) stack.push(node.left) } }
この記事を読んだ後、非再帰ポストオーダーアルゴリズムを見つけたので、ここで非再帰トラバーサルメソッドを完了します。
非再帰順
最初に数値の左側のノードをスタックにプッシュし、次にそれを取り出して、次に右側のノードをプッシュします。
var inOrderUnRecur = function(node) { if(!node) { throw new Error('Empty Tree') } var stack = [] while(stack.length !== 0 || node) { if(node) { stack.push(node) node = node.left } else { node = stack.pop() console.log(node.value) node = node.right } } }
非再帰ポストオーダー (スタックを使用)
ここでは、最後のプッシュを記録するために一時変数が使用されます/ポップノード。このアイデアは、最初にルート ノードと左側のツリーをスタックにプッシュし、次に左側のツリーを取り出し、次に右側のツリーにプッシュしてそれらを取り出し、最後に次のノードを取り出すことです。
var posOrderUnRecur = function(node) { if(!node) { throw new Error('Empty Tree') } var stack = [] stack.push(node) var tmp = null while(stack.length !== 0) { tmp = stack[stack.length - 1] if(tmp.left && node !== tmp.left && node !== tmp.right) { stack.push(tmp.left) } else if(tmp.right && node !== tmp.right) { stack.push(tmp.right) } else { console.log(stack.pop().value) node = tmp } } }
非再帰ポストオーダー (2 つのスタックを使用)
このアルゴリズムの考え方は次のように似ています。上の例では、s1 は一時変数に少し似ています。
var posOrderUnRecur = function(node) { if(node) { var s1 = [] var s2 = [] s1.push(node) while(s1.length !== 0) { node = s1.pop() s2.push(node) if(node.left) { s1.push(node.left) } if(node.right) { s1.push(node.right) } } while(s2.length !== 0) { console.log(s2.pop().value); } } }
モリストラバーサル
このメソッドは、再帰やスタックを使用せずに 3 つの深さトラバーサルを実装し、空間計算量は O(1 ) (この概念については特に明確ではありません)
(これら 3 つのアルゴリズムは脇に置いて、時間があるときに勉強します)
モリス順序:
var morrisPre = function(head) { if(!head) { return } var cur1 = head, cur2 = null while(cur1) { cur2 = cur1.left if(cur2) { while(cur2.right && cur2.right != cur1) { cur2 = cur2.right } if(!cur2.right) { cur2.right = cur1 console.log(cur1.value) cur1 = cur1.left continue } else { cur2.right = null } } else { console.log(cur1.value) } cur1 = cur1.right } }
モリス ミッドオーダー:
var morrisIn = function(head) { if(!head) { return } var cur1 = head, cur2 = null while(cur1) { cur2 = cur1.left if(cur2) { while(cur2.right && cur2.right !== cur1) { cur2 = cur2.right } if(!cur2.right) { cur2.right = cur1 cur1 = cur1.left continue } else { cur2.right = null } } console.log(cur1.value) cur1 = cur1.right } }
モリス ポストオーダー:
var morrisPost = function(head) { if(!head) { return } var cur1 = head, cur2 = null while(cur1) { cur2 = cur1.left if(cur2) { while(cur2.right && cur2.right !== cur1) { cur2 = cur2.right } if(!cur2.right) { cur2.right = cur1 cur1 = cur1.left continue } else { cur2.right = null printEdge(cur1.left) } } cur1 = cur1.right } printEdge(head) } var printEdge = function(head) {
以上ですこの記事の内容全体が皆さんの学習に役立つことを願っています。その他の関連チュートリアルについては、JavaScript ビデオ チュートリアル をご覧ください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます
