構造とアルゴリズム: バイナリツリーとマルチツリー

構造とアルゴリズム: バイナリツリーとマルチツリー

1. ツリー構造

1. 配列とリンクリスト

配列構造

配列ストレージは、要素に添字でアクセスするため、クエリ速度が速くなります。配列要素が順序付けられている場合は、バイナリ検索を使用して検索速度を上げることができます。新しい要素を追加すると複数の添字が移動する可能性がある場合は、効率が低くなります。

リンクリスト構造

リンク リストは要素を格納し、要素の追加や削除には効率的ですが、要素をトラバースするには毎回先頭ノードから開始する必要があり、非常に非効率的です。

ツリー構造により、データの保存と読み取りの効率が比較的向上します。

2. ツリー構造の概念

  • ルート ノード: ツリーのルート、つまり親ノードのないノード (上図のノード A など)。
  • 兄弟ノード: 同じ親ノードを持つ子ノード。図の点 B と C に示すように、
  • リーフ ノード: 子ノードを持たないノード。図に示すように、DEFG ノード。
  • 木の高さ: 最大層数。図に示すように、3 層あります。
  • パス: ルート ノードから指定されたノードへのルートを検索します。

ツリー構造はネストされた構造です。ツリー構造の外側の層と内側の層は同様の構造を持つため、この構造は多くの場合再帰的に表現できます。従来のデータ構造におけるさまざまなツリー図は、典型的なツリー構造です。ツリーは、ルート、左サブツリー、右サブツリーとして単純に表すことができます。 左のサブツリーと右のサブツリーにはそれぞれ独自のサブツリーがあります。

2. 二分木モデル

木には多くの種類があります。二分木は重要な種類の木構造です。各ノードが最大 2 つの子ノードを持つことができる形式は、二分木と呼ばれます。二分木の子ノードは、左ノードと右ノードに分かれています。多くの実用的な問題から抽象化されたデータ構造は、多くの場合、二分木の形式になっています。

完全な二分木

バイナリ ツリーのすべてのリーフ ノードは、最後のレイヤーまたは最後から 2 番目のレイヤーにあり、最後のレイヤーのリーフ ノードは左側で連続しており、最後から 2 番目のレイヤーのリーフ ノードは右側で連続しています。これを完全バイナリ ツリーと呼びます。

完全な二分木

バイナリ ツリーのすべてのリーフ ノードが最後のレイヤーにあり、ノードの総数が 2^n -1 (n はレイヤーの数) の場合、そのツリーは完全バイナリ ツリーと呼ばれます。

バランスのとれた二分木

バランスのとれた二分木とは、任意のノードのサブツリーの高さの差の絶対値が 1 以下であり、左右のサブツリーが両方ともバランスのとれた二分木であることを意味します。一般的なバランスのとれた木には、B ツリー (多方向バランス探索木)、AVL ツリー (二分バランス探索木) などがあります。

二分探索木

二分探索木 (BinarySearchTree) は二分木であるだけでなく、特定の順序も満たします。つまり、ノードの左の子はそれ自体よりも小さく、ノードの右の子はそれ自体よりも大きくなります。

3. バイナリツリーエンコーディング

1. 基本コード

ノードコード

  1. クラス TreeNode {
  2. プライベート文字列 num ;
  3. プライベート TreeNode leftNode;
  4. プライベート TreeNode rightNode ;
  5. パブリックTreeNode(文字列 num) {
  6. this.num = num;
  7. } @オーバーライド
  8. パブリック文字列toString() {
  9. 戻る  "TreeNode{num=" + num + '}' ;
  10. }}

ツリー構造コード

  1. クラス BinaryTree01 {
  2. プライベート TreeNode ルート;
  3. }

2. トラバーサルと検索

事前順序トラバーサル検索

まず現在のノードのデータを処理し、次に左のサブツリーと右のサブツリーを順番に再帰的にトラバースします。

  1. パブリックvoid prevTraverse() {
  2. // 親ノードを出力する
  3. System.out.println (これ) ;
  4. // 左のサブツリーを前順に再帰的に走査する
  5. if (this.leftNode != null ) {
  6. this.leftNode.prevTraverse();
  7. } // 右のサブツリーを前順序で再帰的に走査する
  8. if (this.rightNode != null ) {
  9. this.rightNode.prevTraverse();
  10. }} public TreeNode prevSearch(String num) { //現在のノードを比較する
  11. if (this.num.equals(num)) {
  12. これを返します
  13. } // 左のサブツリーを再帰的に走査して検索する
  14. ツリーノード findNode = null ;
  15. if (this.leftNode != null ) {
  16. findNode = this.leftNode.prevSearch(num);
  17. } // 左サブツリーのトラバーサルヒット
  18. findNode がnull場合
  19. findNodeを返します
  20. } // 右のサブツリーを再帰的に走査して検索する
  21. if (this.rightNode != null ) {
  22. findNode = this.rightNode.prevSearch(num);
  23. } findNodeを返します
  24. }

順序探索検索

まず左のサブツリーを再帰的に走査し、次に親ノードを処理し、次に右のサブツリーを再帰的に走査します。

  1. パブリックボイドmidTraverse() {
  2. // 左のサブツリーを再帰的に走査する
  3. if (this.leftNode != null ) {
  4. this.leftNode.midTraverse();
  5. } // 親ノードを出力する
  6. System.out.println (これ) ;
  7. // 右のサブツリーを再帰的に走査する
  8. if (this.rightNode != null ) {
  9. this.rightNode.midTraverse();
  10. }} public TreeNode midSearch(String num) { // 左のサブツリーを再帰的に走査して検索する
  11. ツリーノード findNode = null ;
  12. if (this.leftNode != null ) {
  13. findNode = this.leftNode.midSearch(num);
  14. } の場合 (findNode != null ) {
  15. findNodeを返します
  16. } // 現在のノードを比較する
  17. if (this.num.equals(num)) {
  18. これを返します
  19. } // 右のサブツリーを再帰的に走査して検索する
  20. if (this.rightNode != null ) {
  21. findNode = this.rightNode.midSearch(num);
  22. } findNodeを返します
  23. }

後順序トラバーサル検索

まず左のサブツリーを再帰的にトラバースし、次に右のサブツリーを再帰的にトラバースし、最後に親ノードを処理します。

  1. パブリックボイドlastTraverse() {
  2. // 左のサブツリーを後順に再帰的に走査する
  3. if (this.leftNode != null ) {
  4. this.leftNode.lastTraverse();
  5. } // 右のサブツリーを後順で再帰的に走査する
  6. if (this.rightNode != null ) {
  7. this.rightNode.lastTraverse();
  8. } // 親ノードを出力する
  9. System.out.println (これ) ;
  10. } public TreeNode lastSearch(String num) { // 左のサブツリーを再帰的に走査して検索する
  11. ツリーノード findNode = null ;
  12. if (this.leftNode != null ) {
  13. findNode = this.leftNode.lastSearch(num);
  14. } の場合 (findNode != null ) {
  15. findNodeを返します
  16. } // 右のサブツリーを再帰的に走査して検索する
  17. if (this.rightNode != null ) {
  18. findNode = this.rightNode.lastSearch(num);
  19. } の場合 (findNode != null ) {
  20. findNodeを返します
  21. } // 現在のノードを比較する
  22. if (this.num.equals(num)) {
  23. これを返します
  24. }戻る ヌル;
  25. }

3. ノードを削除する

現在削除中のノードがリーフ ノードである場合は、ノードを直接削除できます。削除中のノードが非リーフ ノードである場合は、ノード ツリーが削除されます。

  1. パブリックvoid deleteNode(文字列 num) {
  2. // 左のノードが削除されているかどうかを判定する
  3. this.leftNode != null && this.leftNode.num.equals(num) の場合 {
  4. this.leftNode = null ;
  5. 戻る;
  6. } // 正しいノードが削除されているかどうかを判定する
  7. this.rightNode != null && this.rightNode.num.equals(num) の場合 {
  8. this.rightNode = null ;
  9. 戻る;
  10. } // 左のサブツリーを走査し、再帰的に削除する
  11. if (this.leftNode != null ) {
  12. this.leftNode.deleteNode(num);
  13. } // 右のサブツリーを走査し、再帰的に削除する
  14. if (this.rightNode != null ) {
  15. 右ノードからノード番号を削除します。
  16. }}

4. 多分岐ツリー

多分岐ツリーとは、親ノードが複数の子ノードを持つことができるが、子ノードは依然として親ノードの法則に従うことを意味します。通常、バイナリツリーの実用性は非常に高く、多分岐ツリーを使用してデータ関係の説明を簡素化できます。

たとえば、Linux ファイルシステム、組織構造の関係、ロールメニュー権限管理システムなどは、通常、マルチブランチツリーに基づいて記述されます。

<<:  人工知能XiaoIceが繊維企業向けにオンデマンドカスタマイズを実現するAIデザインプラットフォームを開設

>>:  従来の連合学習が異種混在の課題に直面したときは、これらのパーソナライズされた連合学習アルゴリズムを試してみてください。

ブログ    
ブログ    

推薦する

よく使われる8つのソートアルゴリズム - Javaコード実装

1. バブルソート改良版: 2. 選択ソート3. 挿入ソート4. シェルソート5. クイックソート6...

C# で開発されたソートアルゴリズムの詳細な説明

C# 言語は、まだ比較的一般的なものです。ここでは、バブル ソート、選択ソート、挿入ソート、シェル ...

新しい AI スキル: 芸術の分類と鑑賞

芸術作品の分類と分析は難しいことで知られており、ごく少数の専門家だけが発言権を持ち、この分野への人工...

7つの主要カテゴリ、40を超える主要概念、機械学習を始める際に習得する必要があるすべての概念がここにあります

勉強すると、学んだことを忘れてしまい、忘れた後にまた学ぶという悪循環に陥ってしまう、そんな気持ちにな...

AI バイアスは、偏見のない視点を必要とする未解決の問題でしょうか?

[[418851]] [51CTO.com クイック翻訳]非常に複雑な技術的アプリケーションで A...

人工知能は私たちの言語を理解するのでしょうか?思っていたよりも強力だ

2016年3月の「人間対機械」は、機械に対する認識を一新した。世界一の囲碁名人イ・セドルが、人工知能...

AI によるマインドリーディング: コンピューターはどのようにして脳波を復元するのか?

[[255490]]画像出典: Visual China 「私の体は潜水鐘のように重いが、私の心は...

非人道的だ!人工知能はソーシャルエンジニアリングの天敵である

人工知能 (AI) はまだ初期段階ですが、AI は急速に企業が自らを守るための重要な手段になりつつあ...

...

わかりやすい! 「高校数学」勾配降下法の数学的原理を理解する

「時期尚早な最適化は諸悪の根源である。」 —ドナルド・アーヴィン・クヌース、コンピュータ科学者、数...

...

人工知能業界の給与データが公開され、私たちは転職を余儀なくされるのか?

人工知能は、現在最もホットな産業であると言っても過言ではありません。最先端のテクノロジー企業から革新...

Spring-Smart-DI は実装クラスを動的に切り替えます。非常に優れています。

実際のシステム開発のシナリオでは、同じ機能を複数のサービスプロバイダーに接続する必要があるというタイ...

ニューラルネットワークの父ヒントン氏は、34年前の画期的な業績を再検証し、脳内のAI手法の「存在」を模索している。

これまで耳にした人工知能の進歩のほぼすべては、30 年前に発表された、多層ニューラル ネットワークを...

人工知能の7つの応用シナリオ

人工知能とは、人間の行動や思考をシミュレートし、トレーニングを通じて特定の問題を解決できる機械によっ...