検索 - ツリーテーブルの検索 - バイナリソートツリー

バイナリソートツリーの定義

バイナリ ソート ツリー (バイナリ検索ツリーとも呼ばれます) は、並べ替えと検索の両方に役立つ特別なバイナリ ツリーです。
定義:
バイナリ ソート ツリーは、空のバイナリ ツリー、または次のプロパティを持つバイナリ ツリーのいずれかです。

  • 左側のサブツリー上のすべてのノードのキーは、ルート ノードのキーよりも小さくなります。
  • 右側のサブツリー上のすべてのノードのキーは、ルート ノードのキーよりも大きくなります。
  • 左側のサブツリーと右側のサブツリーはそれぞれ二分木です。
//二叉排序树结点
typedef int KeyType;
typedef struct {
    
    
    KeyType key;
    char info[];
}ElemType;

typedef struct BSTNode{
    
    
    ElemType data;
    struct BSTNode * lchild;
    struct BSTNode * rchild;
}BSTNode,*BSTree;

ここに画像の説明を挿入します

左サブツリー ノード値 < ルート ノード値 < 右サブツリー ノード値 "
> \quad\qquad\qquad\qquad \Downarrow">
順序トラバーサルを実行して、増加する順序シーケンスを取得します。

検索操作

バイナリ ソート ツリーは順序付きリストとみなすことができるため、バイナリ ソート ツリーでの検索は二分探索に似ており、徐々に検索範囲を狭めるプロセスでもあります。

アルゴリズムの説明:

① バイナリソートツリーが空の場合、検索は失敗し、null ポインタが返されます。
② バイナリソートツリーが空でない場合は、指定されたキーをルートノードのキーと比較します。

  • それらが等しい場合、検索は成功し、ルート ノード ポインタが返されます。
  • ルート ノードより小さい場合は、左側のサブツリーを再帰的に検索します。
  • ルート ノードより大きい場合は、右側のサブツリーを再帰的に検索します。
    アルゴリズムの説明:
BSTree SearchBST(BSTree T,KeyType key){
    
    
    if((!T)||key==T->data.key)
        return T;
    else if(key<T->data.key)
        return SearchBST(T->lchild,key);
    else
        return SearchBST(T->rchild,key);
}

挿入操作

バイナリソートツリーの挿入操作は検索に基づいています。バイナリソートツリーに key のキー値を持つノード * S を挿入するには、ルートノードから下方向に検索し、ツリーの途中に key と等しいキーを持つノードがある場合にのみ挿入する必要があります。新しく挿入されたノードは、新しく追加されたリーフ ノードである必要があり、検索部分が成功したときに検索パス上で最後に訪問したノードの左または右の子ノードである必要があります。

アルゴリズムの説明

① 2分ソートツリーが空の場合、挿入対象のノード *S をルートノードとして空のツリーに挿入します。
② バイナリ ソート ツリーが空でない場合は、指定されたキーとルート ノードのキー (T->data.key) を比較します。

  • key< T->data.key の場合、*S を左側のサブツリーに挿入します。
  • key>T->data.key の場合、*S を右側のサブツリーに挿入します。
int InsertBST(BSTree &T, ElemType e) {
    
    
    if (!T) {
    
    
        T = (BSTree) malloc(sizeof(BSTNode));
        T->data = e;
        T->lchild = T->rchild = NULL;
        return 1;
    } else if (e.key == T->data.key)
        return 0;
    else if (e.key < T->data.key)
        return InsertBST(T->lchild, e);
    else if (e.key > T->data.key)
        return InsertBST(T->rchild, e);
}

削除操作

削除されるノードは、バイナリ ソート ツリー内の任意のノードであり、ノードの削除後、バイナリ ソート ツリーの特性を維持するために、その位置に応じて親ノードとその関連ノードのポインタを変更する必要があります。
ここに画像の説明を挿入します

削除されたノード z がリーフ ノードの場合は、直接削除され、バイナリ ソート ツリーのように動作しません。
ここに画像の説明を挿入します

ノード z に左側のサブツリーしかない場合、z のサブツリーを z の親ノードのサブツリーにして、z の位置を置き換えます。
ここに画像の説明を挿入します
ノード z に右のサブツリーしかない場合、z のサブツリーを z の親ノードのサブツリーにして、z の位置を置き換えます。
ここに画像の説明を挿入します
ノード z の左右のサブツリーが空でない場合は、z を z の直接の先行者に置き換えてから、バイナリ ソート ツリーから直接の先行者を削除して、状況①または②に変換します。
ここに画像の説明を挿入します
ノード z の左右のサブツリーが空でない場合は、z を z の直接後続ノードに置き換え、次にこの直接後続ノードをバイナリ ソート ツリーから削除し、状況①または②に変換します。

アルゴリズムの説明:

  1. まず、キーワード key を使用して削除するノードを検索します。
    ① 削除されたノード z が葉ノードの場合は、直接削除され、バイナリ ソート ツリーの特性はありません。
    ② ノード z が左サブツリーのみ、または右サブツリーのみを持つ場合、z のサブツリーを z の位置を置き換えて z の親ノードのサブツリーにします。
    ③ ノード z の左右のサブツリーが空でない場合は、z を z の直接の後続者 (または直接の先行者) に置き換えてから、バイナリ ソート ツリーから直接の後続者 (または直接の先行者) を削除して、① または②の状況。
void DeleteBST(BSTree &T, KeyType key) {
    
    
    BSTNode *z = T; //待删除的结点
    BSTNode *f = NULL; //待删除结点 *z 的双亲结点
    /**----------------------- while循环从根开始查找关键字等于key的结点*z -----------------------*/
    while (z) {
    
    
        if (z->data.key == key)
            break; //找到关键字等于key的结点 *z
        f = z; //*f 为 *p的双亲结点
        if (z->data.key > key)
            z = z->lchild; //在*z 的左子树中继续查找
        else
            z = z->rchild;    //在 *p的右子树中继续查找
    }

    if (!z)return; //找不到待删除的结点;
    /**------------ 考虑3中情况实现p所指子树内部的处理:*p左右子树不为空、无左子树、无右子树 ------------*/
    BSTNode *q = z;
    if (z->lchild && z->rchild) {
    
     //待删除结点*z 左右子树均不为空
        BSTNode *s = z->lchild;
        while (s->rchild) {
    
     //在*p的左子树中继续查找其前驱结点,即最右下结点
            q = s;
            s = s->rchild; //向右到尽头
        }
        z->data = s->data; //s指向待删除结点的前驱
        if (q != z)
            q->rchild = s->lchild; //重接*q的右子树
        else
            q->lchild = s->lchild; //重接*q的左子树
        delete s;
        return;
    } else if (!z->rchild) {
    
    //待删除结点*p无右子树结点,只需重接其左子树
        z = z->lchild;
    } else if (!z->lchild) {
    
    //待删除结点*z 无左子树结点,只需重接其右子树
        z = z->rchild;
    }
    /**------------------------- 将p所指的子树挂接到其双亲结点*f相应的位置 -------------------------*/
    if (!f)  //被删除结点为根结点
        T = z;
    else if (q == f->lchild)
        f->lchild = z; //挂接到*f的左子树位置
    else
        f->rchild = z; //挂接到*f的右子树位置
    delete q;

}

作成オペレーション

バイナリ ソート ツリーの作成操作は、空のバイナリ ソート ツリーから開始され、ノードは入力されません。検索操作の後、新しいノードが現在のバイナリ ソート ツリーの適切な位置に挿入されます。

アルゴリズムの説明:

① 二分ソート木 T を空の木に初期化する。
②キーワードがkeyのノードを読み込みます。
③ 読み取ったキーワードキーが入力終了マークでない場合、以下の処理をループで実行します。

  • これらの点をバイナリソートツリー T に挿入します。
  • キーワードが key のノードを読み込みます。
void CreatBST(BSTree &T) {
    
    
    T = NULL;
    ElemType e;
    cin >> e;
    while (e.key != '\0') {
    
    
        InsertBST(T, e);
        cin >> e;
    }
}

検索効率分析

おすすめ

転載: blog.csdn.net/QQ657205470/article/details/127427327
おすすめ