[]ツリーとバイナリツリーデータ構造入門

[]ツリーおよび二分木データ構造


このブログは、木やバイナリツリーの基本的な概念を記録します。

転載この記事:バイナリツリー-あなたはこれらを知っている必要があり


1.ツリーとは何ですか

非線形ツリーデータ構造は、有限のN個のセット(N> = 0)であるそのノード。
n個の== 0の場合、ツリーは空の木です。
nが> 0の場合、
ツリーは、特定のノード、ルートノードを有しています。rootだけ即時の後継者は、何の直接の前身を持っていません。
ルートノード以外のノードは、M(M> = 0)有限の互いに素の集合、T0、T1、T2、...に分割され 、TM-1、 根と呼ばれ、各ツリーを結合しますサブツリーのノードポイント。

2.バイナリツリー

このようなツリーデータ構造のために、最も頻繁に使用されるデータ構造は、バイナリツリーこと。

2.1バイナリツリーは何ですか

ツリーの各ノードは、2つのつの子ノードの最大値は、二分木と呼ばれます。

2.2バイナリツリーのいくつかの機能

2 ^(I-1)番目のノード(I> = 1)に二分木までのi番目の層で、。
B、kは2 ^ k-1個のノード(K> = 0)まで、二分木の高さです。
それは、n個のリーフノードを有する場合にC、バイナリツリーは、非リーフノードの次数は、その後、M 2、N = M + 1を有します。
N +接合を有する高さDの完全二分木、1はlogN個であり
、任意の数のための完全なバイナリN個のノードのツリー階層番号(左から右へ上から下へ、)のノードについては、Eノードiします

バイナリツリーを達成するために2.3ストレージ


// 节点
public class BinaryNode {
    // 存放的信息
    Object data;
    // 左儿子
    BinaryNode left;
    // 右儿子
    BinaryNode right;
}

2.4バイナリツリートラバーサル

トラバーサルは、いわゆるバイナリツリートラバーサルは、各ノードが一度訪問し、一度だけアクセスされたように、すべてのノードが、特定のルールおよび順序に従ってバイナリツリーを移動することである、木の基本動作です。バイナリツリーは非線形構造であるので、従って、ツリーをトラバースすることは、本質的に、各ノードが線形配列として表わされる二分木に変換されます。

ツリーをトラバースするために、別のルートアクセスのために、三つの主要なトラバースアルゴリズムがあります。

  • 予約限定!
  • 後順
  • 予約限定!

ナビゲートするための上記の3つの基本的な方法、ならびにバイナリツリーの深さ優先トラバーサルと幅優先トラバーサルに加えて。

我々は最初の仮説を与える:
L:左のサブツリー
D:ルート
R:右のサブツリーを

2.4.1先行順(DLR)

予約限定:ルート - >左のサブツリー - >右部分木

public static void DLR(BinaryNode node) {
        // 访问根节点
        System.out.print(node.data + " ");
        // 遍历左子树
        if (node.left != null) {
            DLR(node.left);
        }
        // 遍历右子树
        if (node.right != null) {
            DLR(node.right);
        }
    }

2.4.2先行順(LRD)

後順:左のサブツリー - >右部分木 - >ルート


public static void LRD(BinaryNode node) {
        // 遍历左子树
        if (node.left != null) {
            LRD(node.left);
        }
        // 遍历右子树
        if (node.right != null) {
            LRD(node.right);
        }
        // 访问根节点    
        System.out.print(node.data + " ");
    }

トラバーサルINORDER 2.4.3(LDR)

予約限定:左のサブツリー - >ルート - >右部分木

          // 遍历左子树
        if (node.left != null) {
            LDR(node.left);
        }
        // 访问根节点
        System.out.print(node.data + "");

        // 遍历右子树
        if (node.right != null) {
            LDR(node.right);
        }

2.4.4深さ優先トラバーサル

それは手順がそれ以上、これまで行くことができない深いブランチに、可能な各パスの簡単です。DFSの深さ優先探索の略称であり、各ノードは一度だけアクセスすることができます。

深さ優先探索は、スタックは高度な機能を持つ、スタック上のこのデータ構造を使用する必要があります。

上記のように、我々は、深さ優先トラバーサル下にプロセスを分析しなければなりません。

  • ルートノードは、第一のスタック、スタック(A)です。
  • ノードポップアップ、2つの子がBC、定義及びスタックの特性がノードであるので、第一C(右息子)はスタックにプッシュし、次いでB(左息子)スタック、スタック(CB)にプッシュ
  • ポップスタック(CED)、スタックにプッシュノードする上部要素ノードB、D及びEをポップ。
  • 唯一の子ノードH、Hは、従って、直接スタック、スタック(CEH)があるので、上部要素D、ノードDをポップ。
  • トップ要素H、要素H子要素が存在しない、スタック(CE)をポップ。
  • 上部要素Eをポップ、要素Eが存在するサブ要素、スタック(C)ではありません。
  • Cは、サブセクションノードGFは、それぞれスタックポップスタック要素、スタック(GF)。
  • Fスタック、スタック(G)。
  • Gスタック、スタック()。
  • トラバース終了。
    結果の深さ優先探索:ABDHECF G.

上記の分析を通じて、その深さ優先探索の難しさはありませんが、実際にはそう、のは、コード(プロセスの明確な理解、コードを実装するのは簡単ですが)手を実装してみましょうではありません。


private void depthFirst(AVLTreeNode<T> node) {
        if (node == null) {
            return;
        }

        Stack<AVLTreeNode> stack = new Stack<>();
        // 根节点入栈,然后进行后续操作
        stack.push(node);

        while (!stack.isEmpty()) {
            AVLTreeNode root = stack.pop();
            // 弹出栈顶元素,进行访问。
            System.out.println(root.key + " ");
            // 首先将右节点入栈
            if (root.right != null) {
                stack.push(node.right);
            }
            // 然后左节点入栈
            if (root.left != null) {
                stack.push(node.left);
            }
        }

    }

2.4.5幅優先トラバーサル

すなわちBFS広さでFirstSearchの英語の略語。手順は、各階層ノード、完全なアクセス次のレベルへの層、及び各ノードが一度だけアクセスすることができるテストへのアクセスが続きます。上記の例では、結果の幅優先トラバーサルは:A、B、C、D、E、F、G、H(左から右への各アクセスノードを仮定します)。

まずトラバーサルFIFOキュー特性を有する、このようなデータ構造をキューイングする必要があります。

上記のように、我々は、幅優先トラバーサルプロセスを分析します。

キューに最初のノード、キュー(A);
ポップアップノードA、サブノードB Aは、Cは、キューに挿入されたキューの末尾にケースB、Cの最初のキュー、キュー(B、C)です。
ノードBは、D、Eがキューに挿入されたBサブノード、キューの末尾にケースC、Eの最初のキューは、キュー(C、D、E)が、ポップアップ表示されます。
ポップアップノードCを、ノードの子Cながら; F、Gは、キュー(D、E、F、G)、キューにキューの末尾にD、G場合の第1のキューに挿入
E次に、子ノードHがキューに挿入されたポップアップノードD、ノードDであります最初のキューで、Hは、キューの末尾に、キュー(E、F、G、H);
EFGHが排出される(4つのノードの子ノードが存在しません)。
幅優先トラバーサル結果:ABCDEFGH

次のように手が幅優先横断を達成するために、コードは次のとおりです。


public void breadthFirst() {
        breadthFirst(root);
    }

    private void breadthFirst(AVLTreeNode<T> node) {
        if (node == null) {
            return;
        }

        Queue<AVLTreeNode> queue = new ArrayDeque<>();
        // 根节点入栈
        queue.add(node);

        while (!queue.isEmpty()) {
            AVLTreeNode root = queue.poll();
            System.out.print(node.key + " ");

            if (root.left != null) {
                queue.add(node.left);
            }

            if (root.right != null) {
                queue.add(node.right);
            }

        }


    }

2.5 完全二叉树

定義:第一層、その他の層(1〜さh-1)を除く時間は、すべてのノードが連続左側に集中しているノードの最大数、H層に達し、二分木の深さがhであると仮定すると完全なバイナリツリーがあります。

完全なバイナリツリーは、次の特性があります。

  • 右側の欠陥と空孔のノードの最後の層を可能にする、つまり、リーフノードのみが最大レベル2で行うことができます。
  • その右の部分木の深さがJであれば任意のノードについては、サブツリーを左される深さは、J又はJ + 1です。即ち、1又は0の一点のみ。

2.6完全なバイナリツリー

すべての子ノードのない最後のものを除いて、各レイヤー上のすべてのノードは、バイナリツリーの2つのノードを持っています。
国内のチュートリアル定義:バイナリツリーの各階層のノードの数が最大に達している場合、バイナリツリーは完全なバイナリツリーです。すなわち、層の進数がKであり、ノードの合計数は(2 ^ k)がある場合は-1、それは完全なバイナリツリーです。

完全なバイナリツリーは、完全なバイナリツリーの特別な種類です。

おすすめ

転載: www.cnblogs.com/54chensongxia/p/11567515.html