二叉查找树(BST)基本操作(建立、查找并修改、插入、删除)——附带完整C++代码

1 建立二叉查找树

typedef int ElemType;
struct node
{
    ElemType data;
    node* lchild;
    node* rchild;
};

2 建立树

2.1 新建结点

//新建结点
node* newNode(int v){
    node* Node = new node;
    Node->data = v;
    Node->lchild = Node->rchild = NULL;
    return Node;
}

2.2 插入结点

//插入结点
void  Insert(node* &root, int x){
    if(root == NULL){//空树查找失败,即插入位置
        root = newNode(x);//新建结点,权值为x
        return;
    }

    if(root->data == x){//说明结点已存在
        return;
    }else if(x < root->data){
        Insert(root->lchild, x);
    }else{
        Insert(root->rchild, x);
    }

}

2.3 建立树

//二叉查找树建立
node* Create(int data[], int n){
    node* root = NULL;
    for (int i = 0; i < n; ++i)
    {
        Insert(root, data[i]);
    }

    return root;
}
//同一组数据,插入的顺序不同,建立的二叉查找树也不同

3 删除结点

3.1 删除前的准备

  • 寻找以root为根结点的树中,最大权值结点
//寻找以root为根结点的树中,最大权值结点
node* findMax(node* root){
    while(root->rchild != NULL){
        root = root->rchild;
    }

    return root;
}
  • //寻找以root为根结点的树中,最小权值结点
//寻找以root为根结点的树中,最小权值结点
node* findMin(node* root){
    while(root->lchild != NULL){
        root = root->lchild;
    }

    return root;
}

3.2 删除结点

void Delete(node* &root, int x){
    if (root == NULL)
    {
        return;
    }

    if(root->data == x){//找到欲删除结点
        if(root->lchild == NULL && root->rchild == NULL){//如果是叶子结点,直接删除
            root = NULL;
        }else if(root->lchild != NULL){//左子树非空
            node* pre =  findMax(root->lchild);//找root前驱结点
            root->data = pre->data;            //用前驱覆盖root
            Delete(root->lchild, pre->data);    //在左子树中删除结点pre
            //删除前驱方法二:用前驱的pre的孩子结点(一定是左孩子)代替pre成为pre父结点S的右孩子结点
        }else{                         //右子树非空
            node* next = findMin(root->rchild);//找root的后继
            root->data = next->data;          //用后继覆盖root
            Delete(root->rchild, next->data);   //在右子树中删除结点next
            //删除后继方法二:用后继的next的孩子结点(一定是右孩子)代替next成为next父结点的左孩子结点
        }
    }else if(root->data > x){
        Delete(root->lchild, x);//往左子树删除x
    }else{
        Delete(root->rchild, x);//往右子树删除x
    }

}

4 测试实例

#include <cstdio>
#include <queue>

using std::queue;

typedef int ElemType;
struct node
{
    ElemType data;
    node* lchild;
    node* rchild;
};

//查找
void Search(node* root, int x){
    if(root == NULL){   //空树,查找失败
        printf("searcjh fail!\n");
        return;
    }

    if(root->data == x){//查找成功,访问之
        printf("%d\n", root->data);
    }else if(x < root->data){//如果x比根结点小,说明x在左子树
        Search(root->lchild, x);
    }else{                  // 如果x比根结点大,说明x在右子树
        Search(root->rchild, x);
    }

}


//新建结点
node* newNode(int v){
    node* Node = new node;
    Node->data = v;
    Node->lchild = Node->rchild = NULL;
    return Node;
}

//插入结点
void  Insert(node* &root, int x){
    if(root == NULL){//空树查找失败,即插入位置
        root = newNode(x);//新建结点,权值为x
        return;
    }

    if(root->data == x){//说明结点已存在
        return;
    }else if(x < root->data){
        Insert(root->lchild, x);
    }else{
        Insert(root->rchild, x);
    }

}

//二叉查找树建立
node* Create(int data[], int n){
    node* root = NULL;
    for (int i = 0; i < n; ++i)
    {
        Insert(root, data[i]);
    }

    return root;
}
//同一组数据,插入的顺序不同,建立的二叉查找树也不同


//寻找以root为根结点的树中,最大权值结点
node* findMax(node* root){
    while(root->rchild != NULL){
        root = root->rchild;
    }

    return root;
}

//寻找以root为根结点的树中,最小权值结点
node* findMin(node* root){
    while(root->lchild != NULL){
        root = root->lchild;
    }

    return root;
}

void Delete(node* &root, int x){
    if (root == NULL)
    {
        return;
    }

    if(root->data == x){//找到欲删除结点
        if(root->lchild == NULL && root->rchild == NULL){//如果是叶子结点,直接删除
            root = NULL;
        }else if(root->lchild != NULL){//左子树非空
            node* pre =  findMax(root->lchild);//找root前驱结点
            root->data = pre->data;            //用前驱覆盖root
            Delete(root->lchild, pre->data);    //在左子树中删除结点pre
            //删除前驱方法二:用前驱的pre的孩子结点(一定是左孩子)代替pre成为pre父结点S的右孩子结点
        }else{                         //右子树非空
            node* next = findMin(root->rchild);//找root的后继
            root->data = next->data;          //用后继覆盖root
            Delete(root->rchild, next->data);   //在右子树中删除结点next
            //删除后继方法二:用后继的next的孩子结点(一定是右孩子)代替next成为next父结点的左孩子结点
        }
    }else if(root->data > x){
        Delete(root->lchild, x);//往左子树删除x
    }else{
        Delete(root->rchild, x);//往右子树删除x
    }

}

const int MAXN = 110;
int pre[MAXN] = {5,1,0,3,2,4,8,6,7,9};
int in[MAXN] = {0,1,2,3,4,5,6,7,8,9};

//前序、中序创建二叉树
node* Create2(int preL, int preR, int inL, int inR){
    if(preL > preR){
        return NULL;
    }

    node* root = new node;
    root->data = pre[preL];

    int k;
    for (k = inL; k <= inR; ++k)
    {
        if(in[k] == root->data){
            break;
        }
    }

    int numLeft = k - inL;
    root->lchild = Create2(preL + 1, preL + numLeft, inL, k - 1);
    root->rchild = Create2(preL + numLeft + 1, preR, k + 1, inR);

    return root;
}

//中序遍历
void layorder(node* root){
    queue<node*> q;
    q.push(root);
    while(!q.empty()){
        node* now = q.front();
        q.pop();

        printf("%d\n", now->data);

        if(now->lchild != NULL){
            q.push(now->lchild);
        }
        if(now->rchild != NULL){
            q.push(now->rchild);
        }
    }
}


int main(int argc, char const *argv[])
{
    node* root;
    root = Create2(0, 9, 0, 9);
    Delete(root, 5);
    layorder(root);

    return 0;
}
发布了321 篇原创文章 · 获赞 51 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_33375598/article/details/104143286
今日推荐