【データ構造】バイナリツリーの概念とヒープの実装(on)

目次

1. ツリーの概念と構造

2. 二分木の概念

 2.3 バイナリツリーの記憶構造

3. バイナリツリーの逐次構造とヒープの実装

3.1 ヒープの概念

3.2 ヒープの実装

3.3 ヒープの関連インターフェイスを実現する

3.5 下方調整方法

3.6 ヒープの初期化

 3.7 ヒープの破壊

3.8 ヒープの最上位要素を取得する

3.9 ヒープ内の要素数を取得する

3.10 ヒープの挿入

3.11 ヒープの削除 

 3.12 ヒープソート


1. ツリーの概念と構造

1.1 ツリーの概念
ツリーは非線形データ構造であり、n (n>=0) 個の有限ノードで構成される階層関係のセットです。根が上を向き、葉が下を向いている、逆さまの木に見えることからツリーと呼ばれています。
ルート ノードと呼ばれる特別なノードがあります。ルート ノードには先行ノードがありません
。ルート ノードを除き、他のノードは M (M>0) 個の互いに素な集合 T1、T2、...、Tm に分割されます。ここで、各集合はTi (1<= i<= m) は、ツリーと同様の構造のサブツリーです。各サブツリーのルート ノードには 1 つのみの先行ノードがあり、0 個以上の後続ノードを持つことができます。したがって、ツリーは再帰的に定義されます。ツリー構造では、ツリー構造に注意する必要があります。ノード間の交差はありませ
。サブツリー、それ以外の場合はツリー構造ではありません

 上図のように、サブツリー間に交差がある場合、その構造は現時点ではツリーとは言えず、グラフと呼ぶ必要があります。

ノードの次数: ノードに含まれる部分木の数をノードの次数といいます; 上図に示すように: A は 6 葉のノード
または終端ノードです: 次数が 0 のノードは葉と呼ばれますノード; 上の図に示すように: B、C、H、I... などのノードは葉ノード、
非終端ノード、または分岐ノードです: 次数が 0 でないノード; 上の図に示すように: などのノードD、E、F、G... はブランチ ノード、
親ノード、または親ノードであるため、A ノードに子ノードが含まれる場合、このノードはその子ノードの親ノードと呼ばれます。上の図に示すように、A はB の親ノード 子ノード
または子ノード: ノードに含まれるサブツリーのルート ノードをノードの子ノードと呼びます; 上図に示すように: B は A の子ノード
です。上の図に示すように、同じ親ノードは兄弟ノードと呼ばれます: B と C は兄弟ノードです (兄弟である必要があることに注意してください)
上の図に示すように、ノードの次数はツリーの次数と呼ばれます。 : ツリーの次数は 6 (ツリーの次数は、親ノードが次数として持つ子ノードの数としても理解できます)
ノードの階層: ルートから定義され、ルートは最初の層であり、ルートの子ノードは 2 番目のレイヤーなどです (上の図には 4 つのレイヤーがあります)
ツリーの高さまたは深さ: ツリー内のノードの最大レベル; 上の図のように: ツリーの高さは4 (4 層)
いとこノード: 親が同じ層にあるノードはいとこです; 上図に示すように: H と I は兄弟
ノードの互いの祖先です: ルートからノードまでの枝にあるすべてのノード;上の図に示すように: A はすべてのノードの
祖先です: ノードをルートとするサブツリー内のノードは、ノードの子孫と呼ばれます。上の図に示すように、すべてのノードはフォレストの子孫です
。m (m>0) の互いに素なツリーの集合はフォレストと呼ばれます。


ツリー構造は線形テーブルに比べて複雑で、保存や表現が面倒です。値の範囲が保存されるため、ノードとノード間の関係も保存されます。実際には、ツリーを表現する方法はたくさんあります。表現子表現の親表現、および子の兄弟表現としてここでは、最も一般的に使用される子兄弟表記を簡単に理解します。

 子兄弟表記法は、以下の図に示すように、左子右兄弟表記法とも呼ばれます。子ポインタはその子ノードを指し、兄弟ポインタはその兄弟を指します。

 ツリーの実際の応用例は、コンピュータ内のファイル ディレクトリがツリー構造で実現されるようなものです。

2. 二分木の概念

2.1 概念
バイナリ ツリーは有限のノードのセットであり、そのセットは次のとおりです。
1. または空です
。 2. ルート ノードと、左サブツリーおよび右サブツリーと呼ばれる 2 つのバイナリ ツリーで構成されます。


上の図からわかります。
1. 二分木には次数が 2 より大きいノードはありません。
2. 二分木の部分木は左右に分割されており、順序を逆にすることはできないため、二分木は次のようになります。ツリーは順序付きツリーです
。 注: バイナリ ツリーは、次のような状況の組み合わせで構成されます。

 

 実際には、下の図に示すように、バイナリ ツリーも見たことがあります (ツリーは完全なバイナリ ツリーです)。

2.2 特別なバイナリ ツリー:
1. 完全なバイナリ ツリー: バイナリ ツリーは、各層のノードの数が最大値に達すると、このバイナリ ツリーは完全なバイナリ ツリーになります。つまり、バイナリ ツリーの層の数が K で、ノードの総数が 2^k-1 であれば、それは完全なバイナリ ツリーになります。
2. 完全なバイナリ ツリー: 完全なバイナリ ツリーは非常に効率的なデータ構造であり、完全なバイナリ ツリーは完全なバイナリ ツリーから派生します。深さが K でノードが n のバイナリ ツリーの場合、各ノードが、深さのある完全なバイナリ ツリー内の 1 から n までの番号が付けられたノードと 1 対 1 対応する場合に限り、完全なバイナリ ツリーと呼ばれます。 Kさんの 完全なバイナリ ツリーは特別な種類の完全なバイナリ ツリーであることに注意してください。
2.4 二分木の性質1. ルートノードの層数を i と指定した場合、
空ではない二分木のi 番目の層には最大2^(i-1)個のノードが存在します
。ルート ノードの層数を h として指定すると、深さ h の二分木の最大ノード数は2^h-1
になります葉ノードの数を X0、次数 2 の分岐ノードの数を X2 とすると、X0=X2+1
4. ルートノードの層数を h と指定すると、完全な二分木の深さは n になります。ノード: h= log(n+1)  (log は 2、n+1 の対数に基づきます)
5. n 個のノードを持つ完全なバイナリ ツリーの場合、すべてのノードが配列の上から順に 0 から番号付けされているとします。下から左から右へ、シーケンス番号 i のノードについては次のようになります。

1. i>0 の場合、i 位置のノードの親番号: (i-1)/2; i=0、i はルート ノード番号、親ノードなし 2. 2i+1< n の場合、
左子の番号: 2i+ 1、2i+1>=n それ以外の場合、左側の子 3 はありません。2i
+2<n の場合、右側の子のシリアル番号: 2i+2、2i+2>=n、それ以外の場合は右側はありません。上記
(1.2.3) は、配列内の親ノードを知り、左側の子ノードの添え字 2*parnet+1 を見つけ、右側の子ノードの添え字は 2*parent+2 であると理解できます
いずれかの子ノードの子添字がわかっている場合は、親ノードの添字を (子 -1)/2 として見つけます。

次の図は、完全なバイナリ ツリーと完全なバイナリ ツリーの概略図です。

 2.3 バイナリツリーの記憶構造


バイナリ ツリーは通常、シーケンシャル構造チェーン構造の 2 つの構造を使用して格納できます。
1.シーケンシャル ストレージ
シーケンシャル構造ストレージでは、ストレージに配列が使用されます。一般に、配列は完全なバイナリ ツリーに対するスペースの無駄ではないため、完全なバイナリ ツリーを表す場合にのみ適しています実際には、配列にはヒープのみが格納されます。バイナリ ツリー逐次ストレージは、物理的には配列であり、論理的にはバイナリ ツリーです。下の図のような不完全な二分木だ、かなりのスペースを無駄にしてしまいます。

 2.リンクストレージ
二分木のリンクストレージ構造とは、二分木をリンクリストで表現する、つまり要素の論理的な関係をリンクで表現することを意味します。通常の方法では、リンク リストの各ノードは、データ フィールドと左右のポインタ フィールドの 3 つのフィールドで構成され、左右のポインタは、左の子と左の子がポイントするリンクのストレージ アドレスを与えるために使用されます。ノードの右の子が見つかります。チェーン構造はバイナリチェーンとトリプルチェーンに分けられ、バイナリツリーの実装は一般的にバイナリチェーン、赤黒ツリーなどのトリプルチェーンのデータ構造が使われます。

3. バイナリツリーの逐次構造とヒープの実装

3.1 ヒープの概念


通常のバイナリ ツリーは、無駄な領域が多くなる可能性があるため、配列での保存には適していません。完全なバイナリ ツリーは、順次構造の保存に適しています。実際には、通常、シーケンシャル構造の配列にヒープ (バイナリ ツリー) を格納します。ここでのヒープとオペレーティング システムの仮想プロセス アドレス空間内のヒープは 2 つの異なるものであることに注意してください。1 つはデータです。
ヒープの概念と構造 メモリの領域をセグメント化する ヒープの概念と構造

ヒープは、コンピューター サイエンスにおける特別なクラスのデータ構造の一般用語です。ヒープは通常、ツリーと考えることができるオブジェクトの配列です。ヒープは常に次の特性を満たします。

ヒープ内のノードの値は、常にその親ノードの値よりも大きくも小さくもなりません。

ヒープは常に完全なバイナリ ツリーです。

最大のルート ノードを持つヒープは最大ヒープまたはビッグ ルート ヒープと呼ばれ、最小のルート ノードを持つヒープは最小ヒープまたはスモール ルート ヒープと呼ばれます。一般的なヒープには、バイナリ ヒープ、フィボナッチ ヒープなどが含まれます。

ヒープは非線形データ構造であり、1 次元配列と同等です。

 上の図は大きな山を示しています。これは、親ノードが子ノードよりも大きいという事実によって特徴付けられます (昇順でソートするため)。

 上の図は小さなヒープの写真ですが、小さなヒープの特徴は、親ノードが子ノードよりも小さいことです(降順ソートの場合)

3.2 ヒープの実装

ヒープダウン調整アルゴリズム
ここで、論理的に完全なバイナリ ツリーとみなされる配列が与えられます。ルートノードから始まる下方調整アルゴリズムを通じて、それを小さなヒープに調整できます。下方調整アルゴリズムには前提条件があります。つまり、左右のサブツリーが調整対象のヒープである必要があります。

 上の図のような構造を下方調整方法で調整すると、次の図が得られます。

 しかし、順序が正しくなく、左右のサブツリーが小さなヒープではない配列が与えられた場合、どのようにヒープを構築すればよいでしょうか? 現時点では、ヒープをボトムアップで構築することを検討できます。上記のヒープを構築すると、このときのヒープ構築の時間計算量は O(n) になります。

3.3 ヒープの関連インターフェイスを実現する

3.5 下方調整方法

 

 

3.6 ヒープの初期化

 3.7 ヒープの破壊

3.8 ヒープの最上位要素を取得する

3.9 ヒープ内の要素数を取得する

3.10 ヒープの挿入

 まず配列の末尾に 10 を挿入し、ヒープが満たされるまで上方調整アルゴリズムを実行します。以下に示すように

 コード

 

3.11 ヒープの削除 

ヒープの削除では、ヒープの先頭のデータを削除し、ヒープの先頭のデータを最後のデータに置き換え、次に配列内の最後のデータを削除して、下方調整アルゴリズムを実行します。

 

 3.12 ヒープソート

大きなヒープを構築すると昇順にソートできるのですが、なぜこんなことができるのでしょうか? このときヒープの先頭の要素が最大の要素なので、ヒープの先頭の要素を入れ替えるだけで済みます。下方調整方法では、次に大きい数値を選択し、それを再度変更するなどを繰り返し、最終的に配列内の数値が昇順になります。

 

おすすめ

転載: blog.csdn.net/m0_72532428/article/details/129938408