二分探索木は何である(BST)
1. BSTとは何ですか
二分木Xの各ノードに対して、その左部分木の値は、アイテムXの全てよりも少ない、その右側のサブツリーは、すべての項目の値よりも大きいX. このようなバイナリツリーは二分探索木です。
上記のことを特徴とする二分探索木です。
(1)その左サブツリーが空でない場合、そのノードの左の部分木は、そのルートのすべての値の値未満である;
(2)その右サブツリーが空でない場合、右サブツリー全てのノードの値はルートノードの値よりも大きい;
(3)左及び右サブツリーの他はまた、二分探索木である;
(4)二分探索木を追加および削除する過程で見て分かるように、動的なルックアップテーブルであります対応する要素は、これらの動作は、上記特性のバイナリ検索ツリーに残ってする必要があります。
二分探索木の2の定義
二分探索木の要件によると、私たちはBinaryNodeはComparableインタフェースを実装してみましょう。
// 树节点
class BinaryNode implements Comparable {
Integer element;
BinaryNode left;
BinaryNode right;
public BinaryNode{
}
public BinaryNode(Integer element, BinaryNode left, BinaryNode right) {
this.element = element;
this.left = left;
this.right = right;
}
@Override
public int compareTo(@NonNull Object o) {
return this.element - (Integer) o;
}
}
のは(唯一のキーのプロファイルを定義し、分析のための特定のインターフェイスに従う)のBinarySearchTreeの定義を完了してみましょう。
public class BinarySearchTree {
//定义树的根节点
BinaryNode root;
public BinarySearchTree() {
this.root = null;
}
public void makeEmpty() {
this.root = null;
}
public boolean isEmpty() {
return this.root == null;
}
// 判断是否包含某个元素
public boolean contains(Integer x) {
//TODO:后续讲解
return false;
}
// 查找最小值
public BinaryNode findMin(){
//TODO:后续讲解
return null;
}
// 查找最大值
public BinaryNode findMax(){
//TODO:后续讲解
return null;
}
// 按照顺序插入值
public void insert(Integer x){
//TODO:后续讲解
}
// 删除某个值
public void remove(Integer x){
//TODO:后续讲解
}
// 打印树
public void printTree(){
//TODO:后续讲解
}
}
3. contaions操作
ツリー内のノードは、アイテムX Tが含まれている場合は、動作は、そうでない場合はfalse trueを返します。
Tが空集合、偽ダイレクトリターンであれば木は、この操作は非常に簡単になり、あなたはX.見つけるそう、我々はTの左または右のサブツリーサブツリーの再帰検索まで
コードは次のように実装されています。
/**
* 是否包含某个元素
* @param x 待查找对象
* @return 查找结果
*/
public boolean contains(Integer x) {
// 首次查找从根节点开始
return contains(x,root);
}
private boolean contains(Integer x, BinaryNode node) {
// 根节点为空的情况,不需要再查找
if (node == null) {
return false;
}
// 与当前节点进行比较
int compareResult = x.compareTo(node.element);
// 小于当前节点的值,就递归遍历左子树
if (compareResult < 0) {
return contains(x, node.left);
}
// 大于当前节点的值,就递归遍历右子树
else if (compareResult > 0) {
return contains(x, node.right);
}
// 等于当前节点值,直接返回
else {
return true;
}
}
最下位ノードを4.検索
そして限り、開始から左側に左サブツリーのルートが存在するように、エンドポイントは、最小の要素ノードです。
// 查找最小值
public BinaryNode findMin() {
return findMin(root);
}
private BinaryNode findMin(BinaryNode node) {
// 当前节点为null,直接返回null
if (node == null) {
return null;
}
// 不存在左子树,返回当前节点
if (node.left == null) {
return node;
}
// 递归遍历左子树
return findMin(node.left);
}
5.最大ノードを探します
そして、限り、あなたは最初から右のサブツリーのルートを持っているように、エンドポイントは、最大の要素ノードがあります。findMin、findMaxとは対照的に、我々は共通見つけるためにwhileループを使用して、再帰の通常の方法を放棄しました。
// 查找最大值
public BinaryNode findMax() {
return findMax(root);
}
private BinaryNode findMax(BinaryNode node) {
if (node != null) {
while (node.right != null) {
node = node.right;
}
}
return node;
}
6.挿入操作
X-木Tを挿入するために、操作は概念的には簡単で挿入し、私たちは木に沿って同じ外観が含まれているのが好きです。
あなたがXを見つけた場合、我々は何もできない、あなたはまた、いくつかの更新を行うことができます。
それ以外の場合は、トラバーサルパスの最後のノードXに挿入されます。(これは実際には疑問を開いています)
コードは次のように実装されています。
public void insert(Integer x) {
root = insert(x, root);
}
// 返回的插入节点的根节点
private BinaryNode insert(Integer x, BinaryNode node) {
// 如果当前节点为null,新建节点返回
if (node == null) {
return new BinaryNode(x, null, null);
}
// 与当前节点比较
int compareResult = x.compareTo(node.element);
// 小于当前节点值,递归插入左子树,并将返回值设置为当前节点的left
if (compareResult < 0) {
node.left = insert(x, node.left);
}
// 大于当前节点值,递归插入右子树,并将返回值设置为当前节点的right
if (compareResult > 0) {
node.right = insert(x, node.right);
}
// 等于当前的值,不做任何处理
if (compareResult == 0) {
// do some update or do noting
}
return node;
}
7.削除
最も困難な操作と同じくらい多くのデータ構造我々は、削除する要素を発見したら、いくつかの可能なシナリオを考慮する必要がある、削除されています。
ノードを削除するリーフノードである場合は、それを削除します。
ノードを削除するときに一つだけの息子ノード、息子ノードの代わりに、ノードの位置を持ち、その後、ノードを削除します。
削除されたノードであるノードは、2人の息子を持っている場合、一般的な戦略は、その右部分木の最小のデータとデータの代わりに、ノードを削除して、再帰的に(今は空である)ノードを削除することで、最小の右サブツリーためノードは、彼の息子を残していないので、第二簡単に削除します。
// 删除某个值
public void remove(Integer x) {
remove(x, root);
}
private BinaryNode remove(Integer x, BinaryNode node) {
if (node == null) {
return null;
}
int compareResult = x.compareTo(node.element);
if (compareResult < 0) {
node.left = remove(x, node.left);
}
if (compareResult > 0) {
node.right = remove(x, node.right);
}
if (compareResult == 0) {
if (node.left != null && node.right != null) {
node.element = findMin(node.right).element;
node.right = remove(node.element, node.right);
} else {
node = (node.left != null) ? node.left : node.right;
}
}
return node;
}
8.制限事項バイナリ検索ツリー
次のように同一のデータが、異なるバイナリ検索ツリーに対応することができます。
バイナリ検索ツリーは、リンクされたリストに退化し、それに応じて、ルックアップ動作バイナリ検索ツリーとツリーは二分探索しながら、木の高さは、ノードの数Nのツリーがある時に非常に関連していますアルゴリズムを対応するツリーは、すべてのO(n)のレベルに退化します。
明らかに、彼は二分探索木は、見つけ挿入し、これらの3つの操作は、特定の形状とバイナリ検索ツリー関連するO(LGN)レベル、唯一の概算見積もり、ある削除すると言います。しかし、O(LOGN)で全体の時間の複雑さ
はO(n)の間。
9.要約
二分探索木は、いくつかは、線形構造に傾斜ツリー構造を避けるため、より「均衡」することができた場合には、木の高さに関連したノードのバイナリ検索ツリーのクエリ構造とパフォーマンスを削除するには、かなりの時間の複雑さを低減することが可能です。線形構造よりもストレージのバイナリ検索ツリー、ツリーノードに格納された値は、追加のスペースを節約するために、ノード間の親子関係を必要とする要素に関してのみ線形構造なので、ストレージの消費量。