ASL とバイナリ ソート ツリー

(1) コンセプト

100個のデータを含む線形リストまたは連結リストがあり、100個のデータの中から目的のAを見つけたい場合、これを「1回の検索」といいます。比較しますか? 必要な A を見つけます (検索長と呼ばれます)。

これら 100 個のデータでは、100 個のデータの検索には 100 個の異なる検索長があります。

たとえば、A は 1 番目、検索長は 1、B は 3 番目、検索長は 3、C は 10 番目、検索長は 10...

これら 100 個の異なるデータのさまざまな検索長を合計し、データの総数 100 で割って、平均検索長を取得します。

簡単に理解するには、実際には、データの一部を平均して何回比較する必要があるかが重要です。

成功した検索の平均検索長 (ASL 成功): 検索されたデータが存在する場合、検索に成功した対応するデータの平均検索長を指します。

検索失敗の平均検索長 (ASL 失敗): 検索データが存在しない検索失敗の平均検索長を指します。

ここに画像の説明を挿入
Pi は、i 番目のデータが見つかる確率です。一般に、各データの検索確率は 1/n であると想定されます。一部のトピックでは、具体的に各データに異なる確率が与えられます。ここで、Pi は、次のデータを見つけることを意味する Ci に置き換える必要があります。 i-
th データを比較する必要がある回数、つまり、トピックで指定された検索アルゴリズムを使用して現在のデータを見つけるために比較する回数。

ASL は、検索アルゴリズムの効率を測定するための最も重要な指標です。

(2) 例

1: n 個のデータの配列またはリンク リストがあり、それを順番に検索すると、次のようになります。

ASL の成功:
順次検索方法 (つまり、最初から最後まで 1 つずつ比較する) を使用すると、
最初のデータ長 1 を見つけ、2 番目のデータ長 2 を見つけ、3 番目のデータ長 3 を見つけます。 、4番目のデータ長4を求めます...
等差数列の合計公式に従ってn番目のデータ長nを求めます: n*(1+n)/2
最後に、データがn個あるので、nで割ります:n*(1+ ASL 成功を取得するには、n)/ 2 / n
: (1+n)/2

ASL の失敗:
タイトルに、配列にセンチネル ビットがあると記載されている場合、つまり、後ろから前へ逆の順序で検索し、a[0] でセンチネルを比較する場合、合計 n+1 回の比較が必要です。タイトルにセンチネル ビットがあることが記載されていない場合は、
n 回比較するだけでデータが存在しないと判断されます。

2: 順序付けされていない配列: [29, 13, 37, 7, 10, 16, 19, 32, 33, 41, 43] を指定して、配列のバイナリ ソート ツリーとバイナリ検索用のソート ツリーを生成し、ASL の成功を求めます。そしてASLの失敗

バイナリ ソート ツリー (左側が小さく、右側が大きい) を生成するアイデアは次のとおりです。 順序付けさ
れていない配列をループします
(1) 現在のツリーが空の場合、現在の要素をルート ノードとして使用します
( 2) ツリーが空ではなく、現在の要素が現在のノードより大きい場合 点の要素が小さい場合、左の対応する位置を再帰的に検索します。 (3) ツリーが空ではなく、現在の要素
が現在のノードの要素よりも大きい場合、再帰的に右側の対応する位置を見つけます
(4) 特定のノードまで 左の子または右の子が空の場合、現在の要素はルールに従って対応する位置に配置されます左が小さく、右が大きい
擬似コードは次のとおりです。

int a[MaxLenght];   // 假设的无序数组
	TNode rootNode = null; // 创建一个根结点
	for(int i=0; i<MaxLenght; i++){
    
    
		// 把数组一个个的元素不断插入到二叉排序树中
		Create_Tree(rootNode, a[i]);
	}
	
	void Create_Tree(TNode node, int value){
    
    
		if(node == null) {
    
    
			// 如果是空,则生成一个新的结点,该新结点一定是叶子结点
		 	node = (TNode)malloc(sizeof(TNode));
			// 二叉树中叶子结点左右孩子一定是null
			node.lchild = node.rchild = null;
			node.data = value;
			return 0;
		} else if (value < node.data) {
    
    
			// 待插入数据比当前结点的数据小,往左边找位置
			Create_Tree(node.lchild , value);
		} else if (value > node.data) {
    
    
			// 待插入数据比当前结点的数据大,往右边找位置
			Create_Tree(node.rchild , value);
		} else if (value == node.data) {
    
    
			// 如果有重复值,无需插入
			return 1;
		}
	}

生成されたバイナリ ソート ツリー:
ここに画像の説明を挿入
それに対して半検索を実行します。半検索の前提は、配列のセットが単調な順序で使用できることであるため、最初に中間の順序 (左、中央、右、ちょうど順序を小さいものから大きいものに正確に変換するため) 順序付けされた配列を取得します:
添字: 0、1、2、3、4、5、6、7、8、9、10 データ
: 7、10 、13、16、19、 29、32、33、37、41、43

スパニングツリーのグラフと比較すると、階層数は各データ要素の比較回数となり、検索確率が同じ(それぞれ1/n)とすると、式より合計11データ要素となります。 : ASL 成功 = (1 1
+ 2 2 + 3 4 + 4 4 )/ 11 = 33/11 = 3
スパニング ツリーのグラフと対比すると、検索要素が 7 より小さい場合、検索は失敗する必要があり、ノード 7 に対応する左の子の位置は null です。ノード 7 の左の子の位置に対して、検索要素が存在しないことを確認するには 3 回の比較が必要です (29 との比較、13 との比較、7 と​​の比較、そして同じレイヤーには空の子ノードが 16 個残っています (13 を超え 16 未満のデータが存在しないことを表しますが、3 回比較する必要があります)。確認)、32 個の左子ノード (29 より大きく 32 未満のデータ)、41 個の左子ノード 子ノード (37 より大きく 41 未満のデータ)、したがって、以下の 4
種類7 10 未満、10 より大きい、13 未満、16 より大きい 19 未満、19 より大きい 29 未満...

上記では多くの分析を行ってきましたが、実際には、より簡単な方法は、左右の空のノードがいくつあるかを数えるということです。n 番目の層の空のノードは、n-1 回比較するだけで済みます。

ASL 障害 = (3*4 + 4*8)/12 = 11/3

3: 長さ 3 の配列テーブルに対して順次検索を実行します。最初の要素が見つかる確率が 1/2 である場合、2 番目の要素が見つかる確率は 1/3、3 番目の要素が見つかる確率は 1/ 6; 平均的な検索は成功しました。長さは次のとおりです。

非等確率検索は次の式に基づく必要があることに注意してください: Pi (確率) * Ci (比較回数)、i は 1 ~ 3 : (
1/2) + (2/3) + (3/6) = 5/3

バイナリ ソート ツリーのノード操作を削除します。

ここに画像の説明を挿入
示されているバイナリ ソート ツリーの場合、ノード X を削除する場合:
(1) X がリーフ ノードの場合は、それを直接削除します。
(2) X が非リーフ ノードであり、X にサブツリーが 1 つしかない場合 (左と両方の両方) (3) X に左と右の両方のサブツリーがある
場合は、右のサブツリーの順序トラバーサルの最初のノードを使用して、次のようにします。 X を埋める 位置の分析
: X を埋めるために右サブツリーの順序トラバーサルの最初のノードを使用するのはなぜですか?
X を削除した後でも、埋め込みは左が小さく右が大きいという原則を満たすことができるため、X の右の子の順序トラバーサルの最初の要素は、左のサブツリーのすべての要素よりも大きくなければなりません。 time は右のサブツリーになります。 の最小要素であるため、X 位置に配置されます。これは、左が小さく、右が大きいという原則をちょうど満たします。
ここに画像の説明を挿入

時間計算量を求めます。

バイナリ ソート ツリーの検索プロセスはバイナリ サーチと似ていますが、挿入順序が一致しない同じグループの配列に対して異なるバイナリ ソート ツリーが生成されます。極端な場合には、ルート ノード a がすべてのデータの中で最小となり、他のすべての原因 ノードはすべて a の右側に積み重なっています。挿入されたデータが順序付けされている場合 (つまり、後の要素が前の要素より小さい/大きい必要がある)、片側バイナリ ソートが発生します。 (n) ; 二分探索は
通常、指定された順序付けされた配列に対して直接実行されるため、そのスパニング ツリーは一意である必要があり、探索の各ラウンドでデータの半分が削除される可能性があるため、その時間は複雑さは次のとおりです: O (log2n)

[2013] 空ではないバイナリソートツリー T1 で、ノード V を削除してバイナリソートツリー T2 を形成し、次に V を T2 に挿入してバイナリソートツリー T3 を形成します。T1 と T3 に関する次の記述のうち、正しいものはどれですか。

V が T1 の葉ノードの場合、T1 と T3 は同じです。
分析: 上記の削除されたデモンストレーションから、リーフ ノードが削除されてから元のリーフ ノードに戻った場合、バイナリ ソート ツリーはまったく変化しないことがわかります。V が T1 のリーフ ノードでない場合、T1
とT3は違います。
分析: リーフ ノードでない場合は、削除後、右サブツリーの順序トラバーサルの最初の要素を先頭にする必要があります。V が戻ってきた場合、元の位置に戻る方法はなく、データは新しいバイナリ ソート ツリーが追加されます。要素はリーフ ノードである必要があります。したがって、T1 と T3 は異なります。明らかに異なります。

注 ⚠️: 2019 年にも同様の質問がありました。しかし、それはバランスの取れた二分木です

空ではない任意の平衡二分木(AVLツリー)T1において、ノードVを削除して平衡二分木T2を形成し、次にVをT2に挿入して平衡二分木T3を形成する。したがって、T1 と T3 に関する次の記述は正しいことになります。

V が T1 のリーフ ノードである場合、T1 と T3 は異なる可能性があります。
分析:
バランスのとれた二分木であるため、リーフ ノードを削除するとバランスの回転が発生する可能性があるため、ツリー全体の形状に影響します。このとき、T1 と T3 は異なりますが、
リーフノード V を削除してもバランスのとれた回転が発生しない場合は、 T1=T3 となるため
、同じになる場合もあれば、同じでない場合もあります。

V が T1 の葉ノードでない場合、T1 と T3 は同じである可能性があります。V
は葉ノードではありません。削除すると、ツリーは確実に変化します。このときに再度 V を挿入すると、バランスが崩れて復元される可能性があります。それを T1 に変換する場合の例は次のとおりです。
ここに画像の説明を挿入

バイナリ ソート ツリーを事前順序で走査することによって得られるシーケンスは (50, 38, 30, 45, 40, 48, 70, 60, 75, 80) です。バイナリ ソート ツリーを描画して等しい確率を見つけてみてください。成功した検索と失敗した検索の長さ

事前順序走査シーケンスはバイナリ ツリーに復元されます。最初の 50 はルート ノードである必要があり、50 より小さいものは左側のサブツリーにスローされ、50 より大きいものは右側のサブツリーにスローされます。左側のサブツリーでは、 , 最初に
訪問されるものです。到着した 38 は、左側のサブツリーのルート ノードでなければなりません。38 より小さいものはすべて左側にスローされ、38 より大きいものは、右側の右のサブツリーにスローされます。最初に訪問した 70 は、左側のサブツリーにスローされます
。右のサブツリーのルートノードとする 点は、70より小さいものはすべて左に投げられ、70より大きいものは右に投げられます。繰り返しれば回復できます。タイトルは等確率と言われているので

直接Pi*Ci を計算します。
ここに画像の説明を挿入

シーケンス (40、72、38、35、67、51、90、8、55、21) に従ってバイナリ ソート ツリーを構築し、ツリーを描画し、確率長が等しい場合に成功した検索の平均検索を求めます。

ルート ノードとして 40 を指定し、バイナリ ソート ツリーのデフォルトの原則に従って、左が小さく、右が大きく、ツリーを描画し、次の式に従って ASL の成功を計算します。
ここに画像の説明を挿入

最適なバイナリ ソート ツリー: 高さが最も小さく、左右のサブツリーのノード数の差が 1 を超えない、最適なバイナリ ソート ツリーです。最良の点は、クエリ効率が高いことです。ソートツリーを検索する利便性を備えているだけでなく、バ​​ランスの取れた二分木であり、左右のノードの差が以下を超えないバランスの取れた二分木でもあります。 1.
キーワードのセット {25, 18, 34, 9, 14, 27, 42, 51, 38} が与えられた場合、各キーワードが見つかる確率が同じであると仮定して、最適なバイナリ ソート ツリーを描画してください。

アイデア: まず、キーワード シーケンスをソートし、ルート ノードとして中央の要素を見つけます。次に、ルート ノードを決定したので、左小と右大に従ってツリーに要素を追加し続けます。サブツリーが発生する アンバランスな場合、サブツリー内のみが調整され、ルート ノードは調整できません; そうしないと、左右の要素の差が 1 より大きくなり、最適ではありません。左右のサブツリーを生成するプロセスでは、
ルート ノードを調整することはできません。
ここに画像の説明を挿入

指定されたバイナリ ツリーがバイナリ ソート ツリーであるかどうかを判断するアルゴリズムを作成する / バイナリ ソート ツリー内の最小キーワードと最大キーワードを見つける

アイデア: 事前順序走査に従って、それが昇順であるかどうかを確認します。逆の順序が発生した場合は、バイナリ ソート ツリーではありません。最小キーワードと最大キーワードを見つけるには、事前順序走査のみが必要です。最初のものが最小で、最後のものが最大です (またはそれ以上 直接、while ループで左下隅の要素 (最小要素) を見つけます。while ループで右下隅の要素を見つけます。これが最大の要素です)

大規模なルート ヒープとバイナリ ソート ツリーの両方の要件を満たすバイナリ ツリーは、値がルート ノードの値より小さい左の子を 1 つだけ持つ片方向ツリーでなければなりません。

大きなルート ヒープではルート ノードの値が左右の子の値より大きくなければならず、バイナリ ソート ツリーは左側が小さく右側が大きいため、左側の子のみが存在できます。バイナリソートツリーの右側の子はルートより大きくなければならないため、存在できません。
第二に、大きなルート ヒープは完全なバイナリ ツリーであり、上位レベルがいっぱいでない (右側の子がない) 場合、次のレベルの子ノードは生成できないため、修飾された一方的なバイナリ ツリーの高さは 2 しかありません。

おすすめ

転載: blog.csdn.net/whiteBearClimb/article/details/128074229