BST二叉搜索树(查找树)实现 代码+详解(C/C++)

写了一下午,终于把这个整理完了,也相当于复习了一波数据结构吧。。。

 

概念

二叉查找树(Binary Search Tree),又被称为二叉搜索树,二叉排序树。

为什么叫二叉查找树呢,因为它一般的树不同,它具有如下性质

  1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值。
  2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。
  3. 它的左、右子树也分别为二叉查找树。
  4. 在二叉查找树中,没有值相等的节点。

操作

知道了它是一棵什么树,那么它有哪些操作呢?

首先 它是一棵树 那么就有  树的遍历(前序 中序 后序)

树肯定还要建树 树怎么建立   插入建树啊

然后 既然是查找树 肯定可以查找

然后 还有一个删除操作

当然了 它是个数据结构嘛 所以不是只有这么多操作  很灵活 你想要的其他操作  就自己加呗

代码

 

前边是分块讲解     整体代码 在文末~

 

结构

这个不用多说了  都理解  不理解的话先去学学普通二叉树

typedef struct BSTnode{
    int data;
    struct BSTnode *lchild;
    struct BSTnode *rchild;
}BSTnode,*PBSTnode;

插入

插入 同时也是建树的过程

那么 刚才说了 二叉搜索树必须符合他的性质(左子树比根节点小 右子树比根节点大)

那么 我们插入的时候  就按照规则来

      如果 根节点为空 那么直接赋值

      如果要插入的值大于根节点 那么递归往右子树插入

      如果要插入的值小于根节点 那么递归往左子树插入

代码也很容易理解 就不放图了

PBSTnode insert(int data,PBSTnode *root){//插入  此处函数形参是个双重指针
    if(*root == NULL)
    {
        *root=(PBSTnode)malloc(sizeof(BSTnode));
        (*root)->data=data;
        (*root)->lchild=NULL;
        (*root)->rchild=NULL;
        return *root;
     }
     if(data<(*root)->data)//小的放左边
        (*root)->lchild=insert(data,&( (*root)->lchild) );
     else if(data>(*root)->data)//大的放右边
        (*root)->rchild=insert(data,&( (*root)->rchild) );
     return *root;
}

查找

理解了插入 那么其实很容易想到查找的做法

       如果要查找的值大于根节点 那么递归在右子树查找

       如果要查找的值小于根节点 那么递归在左子树查找

但是由于递归(这里还是个尾递归)很耗时间  所以我们一般把这里写成循环

所有的递归程序 理论上都是可以转换成循环的    两种写法如下

PBSTnode Find(int x,PBSTnode root){//查找 递归写法
    if(root==NULL){
        return root;
    }
    if(x>root->data){//大的往右找
        return Find(x,root->rchild ) ;
    }
    if(x<root->data){//小的往左找
        return Find(x,root->lchild );
    }
    if(x==root->data){
        return root;
    }
}
PBSTnode Find_fdg(int x,PBSTnode root){//查找 非递归写法
    while(root!=NULL){
        if(x>root->data)
            root=root->rchild;
        else if(x<root->data)
            root=root->lchild;
        else if(x==root->data)
            return root;
    }
    return root;
}

查找最大值和最小值

最大值嘛 一直往右边找

同理 最小值 一直往最左边找

这两个操作也很好理解 看看代码就懂了

PBSTnode Find_min(PBSTnode root){//查找最小值
    if(root==NULL) return root;
    while(root->lchild){
        root=root->lchild;
    }
    return root;
}
PBSTnode Find_max(PBSTnode root){//查找最大值
    if(root==NULL) return root;
    while(root->rchild){
        root=root->rchild;
    }
    return root;
}

删除

这个操作呢 是二叉查找树所有操作里面最复杂的一个了 

因为你在删除的时候 必须要保证树的性质不被破坏  (也就是删除完了之后仍然是一棵二叉查找树)

怎么删呢

首先 删除某个数 必须先找到这个数  所以我们删除的时候有点类似查找

先找到这个数

  如果要删除的数大于根节点 那么递归去右子树里面找

  如果要删除的数小于根节点 那么递归去左子树里面找

找到了之后呢  怎么删除呢   分两种情况

  1. 要删除的节点有右孩子和左孩子
  2. 要删除的节点没有孩子或者只有一个孩子(左孩子或右孩子)

如果没孩子  很好解决  直接将这个节点置为NULL就好了

如果只有一个孩子 也好解决  把孩子的值给根节点 然后把孩子置为空

那么比较难解决的就是  要删除的节点有两个孩子的情况

如下图 加入我们要删除41 的话  他有两个儿子

《BST二叉搜索树(查找树)实现 代码+详解(C/C++)》

我们的做法是  将他转化成  所删节点只有一个儿子或没有儿子的情况

要删除41  从左子树中找最大的 替换41 然后删除这个左子树中值最大的节点

                或者右子树中找最小的 替换41 然后删除这个右子树中值最小的节点

这样的做法 首先保证了   删除后 二叉查找树的性质不会被改变    

并且左子树中最大的节点一定没有两个儿子   同理 右子树最小的节点也没有两个节点

《BST二叉搜索树(查找树)实现 代码+详解(C/C++)》

PBSTnode Delete(int x,PBSTnode root){
    PBSTnode tmp;
    if(root==NULL){
        printf("要删除的元素未找到\n");
    }
    else if(x>root->data){//在右子树里找
        root->rchild=Delete(x,root->rchild);
    }
    else if(x<root->data){//在左子树里找
        root->lchild=Delete(x,root->lchild);
    }
    else{//找到了
            
        if(root->lchild && root->rchild){//有两个孩子

            tmp=Find_min(root->rchild);//找到右子树中最小的
            root->data=tmp->data;//替换值
            
            //删掉右子树中最小的 并将删除后的右子树连上root
            root->rchild=Delete(tmp->data,root->rchild);

            //或者是在左子树中找最大的替换并删掉 然后连上
            //tmp=Find_max(root->lchild);
            //root->data=tmp->data;
            //root->lchild=Delete(tmp->data,root->lchild);
            
        }
        else{//只有一个孩子 或者没孩子
                
            if(!root->lchild){//没有左孩子
                root=root->rchild;
            }
            else if(!root->rchild){//没右孩子
                root=root->lchild;
            }
        }
    }
    free(tmp);
    return root;
}

 

所有操作整合代码

提供两组验证数据

输入  1,4,5,3,2,6  

结果是     《BST二叉搜索树(查找树)实现 代码+详解(C/C++)》

 

输入    30,15,41,33,35,34,50

《BST二叉搜索树(查找树)实现 代码+详解(C/C++)》

 

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<malloc.h>
#include<bits/stdc++.h>
using namespace std;
typedef struct BSTnode{
    int data;
    struct BSTnode *lchild;
    struct BSTnode *rchild;
}BSTnode,*PBSTnode;
PBSTnode insert(int data,PBSTnode *root){//插入  此处函数形参是个双重指针
    if(*root == NULL)
    {
        *root=(PBSTnode)malloc(sizeof(BSTnode));
        (*root)->data=data;
        (*root)->lchild=NULL;
        (*root)->rchild=NULL;
        return *root;
     }
     if(data<(*root)->data)//小的放左边
        (*root)->lchild=insert(data,&( (*root)->lchild) );
     else if(data>(*root)->data)//大的放右边
        (*root)->rchild=insert(data,&( (*root)->rchild) );
     return *root;
}
PBSTnode Find(int x,PBSTnode root){//查找 递归写法
    if(root==NULL){
        return root;
    }
    if(x>root->data){//大的往右找
        return Find(x,root->rchild ) ;
    }
    if(x<root->data){//小的往左找
        return Find(x,root->lchild );
    }
    if(x==root->data){
        return root;
    }
}
PBSTnode Find_fdg(int x,PBSTnode root){//查找 非递归写法
    while(root!=NULL){
        if(x>root->data)
            root=root->rchild;
        else if(x<root->data)
            root=root->lchild;
        else if(x==root->data)
            return root;
    }
    return root;
}
PBSTnode Find_min(PBSTnode root){//查找最小值
    if(root==NULL) return root;
    while(root->lchild){
        root=root->lchild;
    }
    return root;
}
PBSTnode Find_max(PBSTnode root){//查找最大值
    if(root==NULL) return root;
    while(root->rchild){
        root=root->rchild;
    }
    return root;
}
PBSTnode Delete(int x,PBSTnode root){
    PBSTnode tmp;
    if(root==NULL){
        printf("要删除的元素未找到\n");
    }
    else if(x>root->data){//在右子树里找
        root->rchild=Delete(x,root->rchild);
    }
    else if(x<root->data){//在左子树里找
        root->lchild=Delete(x,root->lchild);
    }
    else{//找到了

        if(root->lchild && root->rchild){//有两个孩子

            tmp=Find_min(root->rchild);//找到右子树中最小的
            root->data=tmp->data;//替换值

            //删掉右子树中最小的 并将删除后的右子树连上root
            root->rchild=Delete(tmp->data,root->rchild);

            //或者是在左子树中找最大的替换并删掉 然后连上
            //tmp=Find_max(root->lchild);
            //root->data=tmp->data;
            //root->lchild=Delete(tmp->data,root->lchild);

        }
        else{//只有一个孩子 或者没孩子

            if(!root->lchild){//没有左孩子
                root=root->rchild;
            }
            else if(!root->rchild){//没右孩子
                root=root->lchild;
            }
        }
    }
    free(tmp);
    return root;
}
void QX(PBSTnode root){//前序遍历
    if(root!=NULL)
    {
        printf("%d ",root->data);
        QX(root->lchild);
        QX(root->rchild);
    }
}

void ZX(PBSTnode root){//中序遍历
    if(root!=NULL)
    {
        ZX(root->lchild);
        printf("%d ",root->data);
        ZX(root->rchild);
    }
}
void HX(PBSTnode root){//后序遍历
    if(root!=NULL)
    {
        HX(root->lchild);
        HX(root->rchild);
        printf("%d ",root->data);
    }
}
int n,x,minn,mixx,cnt;
int main(){
    PBSTnode root=NULL;

    //插入
    int g[6]={1,4,5,3,2,6};
    int G[7]={30,15,41,33,35,34,50};
    for(int i=0;i<7;i++){
        insert(G[i],&root);
    }

    //前中后 遍历
    printf("前序序列:"); QX(root);printf("\n");
    printf("中序序列:"); ZX(root);printf("\n");
    printf("后序序列:"); HX(root);printf("\n");

    //查找最大值 最小值
    if(Find_min(root)!=NULL){
        minn=(Find_min(root)->data);
        printf("最小值是%d\n",minn);
    }
    else{
        printf("树是空的,没有最小值\n");
    }

    if(Find_max(root)!=NULL){
        mixx=(Find_max(root)->data);
        printf("最大值是%d\n",mixx);
    }
    else{
        printf("树是空的,没有最大值\n");
    }

    //查找
    printf("请输入3个要查找的元素\n");
    cnt=3;
    while(cnt--){
        cin>>x;
        if(Find(x,root)==NULL){
            printf("没有找到\n");
        }
        else{
            printf("找到了\n");
        }
    }

    //删除
    printf("请输入2个要删除的元素\n");
    cnt=2;
    while(cnt--){
        cin>>x;
        Delete(x,root);
        printf("删除%d之后 二叉树的前序遍历序列\n",x);
        QX(root);
        printf("\n");
    }

}

 

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/holly_Z_P_F/article/details/85165281
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞