BST では、ノードの左側で下降するすべての値は、ノード自体よりも小さい (または等しい、後述)。同様に、ノードの右側で下降するすべての値は、そのノード値(a)より大きい (または等しい) ことになります。
一部の BSTは、重複する値を許可することを選択する場合があるため、上記の「または等しい」修飾子です。次の例は、明確にすることができます。
14
/ \
13 22
/ / \
1 16 29
/ \
28 29
これは、重複を許可する BST を示しています(b) - 値を見つけるには、ルート ノードから開始し、検索値がノード値より小さいか大きいかに応じて、左または右のサブツリーを下っていくことがわかります。
これは、次のような方法で再帰的に実行できます。
def hasVal (node, srchval):
if node == NULL:
return false
if node.val == srchval:
return true
if node.val > srchval:
return hasVal (node.left, srchval)
return hasVal (node.right, srchval)
そしてそれを呼び出す:
foundIt = hasVal (rootNode, valToLookFor)
値が見つかったら、同じ値の他のノードを検索し続ける必要がある場合があるため、重複すると少し複雑になります。hasVal
少なくとも1つ存在するかどうかだけで、いくつあるかは問題ではないため、明らかにそれは問題ではありません。ただしcountVal
、いくつあるかを知る必要があるため、 のようなものには問題があります。
(a)特定のキーの検索方法を調整すれば、必要に応じて実際に逆方向に並べ替えることができます。BST は、昇順か降順かに関係なく、ソートされた順序を維持するだけで済みます (または、すべての奇数が昇順で、次にすべての偶数が降順のような奇妙な多層ソート方法でさえ) は関係ありません。
(b)興味深いことに、ソート キーがノードに保存されている値全体を使用する場合 (同じキーを含むノードがそれらを区別するための他の追加情報を持たないようにするため)、各ノードにカウントを追加することでパフォーマンスが向上する可能性があります。ノードの複製を許可します。
主な利点は、重複を追加または削除すると、新しいノードを挿入または削除するのではなく、単純にカウントが変更されることです (ツリーの再バランスが必要になるアクション)。
したがって、アイテムを追加するには、まずそれが既に存在するかどうかを確認します。その場合は、カウントを増やして終了します。そうでない場合は、カウントが 1 の新しいノードを挿入してから再調整する必要があります。
アイテムを削除するには、それを見つけてカウントを減らします。結果のカウントがゼロの場合にのみ、ツリーから実際のノードを削除してバランスを取り直します。
ノードが少ないため、検索も高速になりますが、大きな影響ではない可能性があります。
たとえば、次の 2 つのツリー (左側にカウントなし、右側にカウント) は同等です (カウント ツリーでは、 item のコピーをi.c
意味します)。c
i
__14__ ___22.2___
/ \ / \
14 22 7.1 29.1
/ \ / \ / \ / \
1 14 22 29 1.1 14.3 28.1 30.1
\ / \
7 28 30
22
左側のツリーからリーフ ノードを削除するには、リバランスが必要です (高さの差が 2 になっているため)22-29-28-30
以下のような結果のサブツリー (これは1 つのオプションであり、「高さの差は 0 または 1 でなければならない」を満たすものもあります) " ルール):
\ \
22 29
\ / \
29 --> 28 30
/ \ /
28 30 22
右側のツリーで同じ操作を行うのは、ルート ノードを から22.2
に変更する22.1
だけです (リバランスは必要ありません)。