二叉排序树的创建、插入、查找和删除【数据结构】

二叉排序树

  • 若它的左子树不空,则左子树上所有结点的值均小于它根结点的值。
  • 若它的右子树不空,则右子树上所有结点的值均大于它根结点的值。
  • 它的左、右树又分为⼆叉排序树

二叉排序树也叫二叉查找树、二叉搜索树

二叉排序树的创建、插入、查找和删除

创建和插入

题目描述

给出一个数据序列,建立二叉排序树,并实现插入功能。

在建立和插入操作后,都输出二叉树的先序遍历结果i

输入

第1行输入n,表示序列包含n个数据

第2行输入n个数据,都是自然数且互不相同,数据之间用空格隔开

第3行输入m,表示要插入m个数据

输入m行,每行一个要插入的数据,都是自然数且和前面的数据不等

输出

第一行输出一开始构建的二叉排序树的先序遍历结果

从第二行起,输出m行,每行输出插入一个数据到二叉排序树后的先序遍历结果

每行输出的遍历结果中,每个数据后面都带一个空格,最后一个数据也带。

输入样例1

6

22 33 55 66 11 44

3

77

50

10

输出样例1

22 11 33 55 44 66

22 11 33 55 44 66 77

22 11 33 55 44 50 66 77

22 11 10 33 55 44 50 66 77

输入样例2

6

33 55 22 66 11 44

3

25

88

50

输出样例2

33 22 11 55 44 66

33 22 11 25 55 44 66

33 22 11 25 55 44 66 88

33 22 11 25 55 44 50 66 88

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
//树节点
struct tree
{
    int value=0;
    tree* left=NULL;
    tree* right=NULL;
};
//插入操作
tree* insert(tree* t,int a)
{
    tree* root=t;
    while(1)
    {
        if(t->value==0) 
        {
            t->value=a;
            break;
        }
        if(a<t->value) 
        {
            if(!t->left) t->left=new tree;
            t=t->left;
        }
        else 
        {
            if(!t->right) t->right=new tree;
            t=t->right; 
        }
    }
    return root;
}
//先序遍历
void prior(tree* t)
{
    if(t==NULL) return ;
    cout<<t->value<<" ";
    prior(t->left);
    prior(t->right);
}
int main()
{
    int n;
    cin>>n;
    tree* root=new tree;
    for(int i=0;i<n;i++)
    {
        int x;
        cin>>x;
        root=insert(root,x);
    }
    prior(root);
    cout<<endl;
    int m;
    cin>>m;
    for(int i=0;i<m;i++) 
    {
        int x;
        cin>>x;
        //插入
        root=insert(root,x);
        prior(root);
        cout<<endl;
    }
    return 0;
}

查找

题目描述

给出一个数据序列,建立二叉排序树,并实现查找功能

输入

第1行输入n,表示首个序列包含n个数据

第2行输入n个数据,都是自然数且互不相同,数据之间用空格隔开

第3行输入m,表示要查找m个数据

接着输入m行,每行一个要查找的数据,都是自然数

以此类推输入下一个示例

输出

第一行输出有序的数据序列,对二叉排序树进行中序遍历可以得到

从第二行起,输出查找结果,如果查找成功输出查找次数,如果查找失败输出-1

输入样例1

6

22 33 55 66 11 44

7

11

22

33

44

55

66

77

输出样例1

11 22 33 44 55 66

2

1

2

4

3

4

-1

输入样例2

6

33 22 55 11 66 44

4

88

11

44

66

输出样例2

11 22 33 44 55 66

-1

3

3

3

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
//树节点
struct tree
{
    int value=0;
    tree* left=NULL;
    tree* right=NULL;
};
//插入
tree* insert(tree* t,int a)
{
    tree* root=t;
    while(1)
    {
        if(t->value==0) 
        {
            t->value=a;
            break;
        }
        if(a<t->value) 
        {
            if(!t->left) t->left=new tree;
            t=t->left;
        }
        else 
        {
            if(!t->right) t->right=new tree;
            t=t->right; 
        }
    }
    return root;
}
//中序遍历
void middle(tree* t)
{
    if(t==NULL) return ;
    middle(t->left);
    cout<<t->value<<" ";
    middle(t->right);
}
//查找
int find(tree* t,int a,int time)
{
    while(1)
    {
        time++;
        if(t->value==0)
        {
            time=-1;
            break;
        }
        if(t->value==a) break;
        if(a<t->value)
        {
            if(!t->left) t->left=new tree;
            t=t->left;
        }
        else
        {
            if(!t->right) t->right=new tree;
            t=t->right;
        }
    }
    return time;
}
int main()
{
    int n;
    cin>>n;
    tree* root=new tree;
    for(int i=0;i<n;i++)
    {
        int x;
        cin>>x;
        root=insert(root,x);
    }
    middle(root);
    cout<<endl;
    int m;
    cin>>m;
    for(int i=0;i<m;i++)
    {
        int x;
        cin>>x;
        cout<<find(root,x,0)<<endl;
    }
    return 0;
}

删除

题目描述

给出一个数据序列,建立二叉排序树,并实现删除功能

对二叉排序树进行中序遍历,可以得到有序的数据序列

输入

第一行输入t,表示有t个数据序列

第二行输入n,表示首个序列包含n个数据

第三行输入n个数据,都是自然数且互不相同,数据之间用空格隔开

第四行输入m,表示要删除m个数据

从第五行起,输入m行,每行一个要删除的数据,都是自然数

以此类推输入下一个示例

输出

第一行输出有序的数据序列,对二叉排序树进行中序遍历可以得到

从第二行起,输出删除第m个数据后的有序序列,输出m行

以此类推输出下一个示例的结果

输入样例1

1

6

22 33 55 66 11 44

3

66

22

77

输出样例1

11 22 33 44 55 66

11 22 33 44 55

11 33 44 55

11 33 44 55

提示

当删除数据不在序列中,那么删除操作等于不执行,所以输出序列不变化

  1. 被删除的节点是叶子节点,将双亲节点中相应的指针域的值改为空
  2. 被删除的节点只有左子树或右子树,将要删除的节点的双亲节点相应指针域的值指向被删除节点的左子树或者右子树
  3. 被删除节点既有左子树又有右子树,将左子树中的最大值或者右子树中的最小值代替该节点
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
//树节点
struct tree
{
    int value=0;
    tree* left=NULL;
    tree* right=NULL;
};
//插入
tree* insert(tree* t,int a)
{
    tree* root=t;
    while(1)
    {
        if(t->value==0) 
        {
            t->value=a;
            break;
        }
        if(a<t->value) 
        {
            if(!t->left) t->left=new tree;
            t=t->left;
        }
        else 
        {
            if(!t->right) t->right=new tree;
            t=t->right; 
        }
    }
    return root;
}
//中序遍历
void middle(tree* t)
{
    if(t==NULL||t->value==0) return ;
    middle(t->left);
    cout<<t->value<<" ";
    middle(t->right);
}
//删除
void del(tree* t,int a)
{
    //记录父节点
    tree* p=NULL;
    while(1)
    {
        if(t->value==0) break;
        if(t->value==a)
        {
            //叶子结点直接删除
            if(!t->left&&!t->right)
            {
                if(p->left==t) p->left=NULL;
                else p->right=NULL;
                break;
            }
            //只有左子树或只有右子树
            if(!t->left||!t->right)
            {
                //左子树不空
                if(t->left)
                {
                    if(p->left==t) p->left=t->left;
                    else p->right=t->left;
                    break;
                }
                //右子树不空
                if(t->right)
                {
                    if(p->left==t) p->left=t->right;
                    else p->right=t->right;
                    break;
                }
            }
            //左右子树都不空
            //本做法是用左子树最大值代替该节点值
            tree* now=t->left;
            tree* par=t;
            while(now->right) 
            {
                par=now;
                now=now->right;
            }
            //左子树最大值
            int value=now->value;
            //更新值
            t->value=value;
            //这里注意!!!
            if(!now->left&&!now->right) 
            {
                //直接删除左子树的根节点
                if(par==t) par->left=NULL;
                //删除的不是左子树的根节点
                else par->right=NULL;
            }
            //有子节点肯定是左子节点
            else par->right=now->left;
            break;
        }
        if(a<t->value)
        {
            if(!t->left) t->left=new tree;
            p=t;
            t=t->left;
        }
        else
        {
            if(!t->right) t->right=new tree;
            p=t;
            t=t->right;
        }
    }
}
int main()
{
    int t;
    cin>>t;
    for(int i=0;i<t;i++)
    {
        int n;
        cin>>n;
        tree* root=new tree;
        for(int i=0;i<n;i++)
        {
            int x;
            cin>>x;
            root=insert(root,x);
        }
        middle(root);
        cout<<endl;
        int m;
        cin>>m;
        for(int i=0;i<m;i++) 
        {
            int x;
            cin>>x;
            del(root,x);
            middle(root);
            cout<<endl;
        }
    }
    return 0;
}
相关推荐
popcorn_min7 分钟前
Digits 手写数字识别:随机森林多分类 + 像素级特征热力图
算法·随机森林·分类
liulilittle43 分钟前
拥塞控制:排水终止的两种决策:OR 与 AND
网络·tcp/ip·计算机网络·算法·信息与通信·tcp·通信
花间相见1 小时前
【LeetCode02】—— 两数之和:哈希表入门经典详解
数据结构·散列表
weixin_307779131 小时前
从脚本执行到智能体协作:AI辅助测试能力的范式重构
运维·开发语言·人工智能·算法·测试用例
量化君也1 小时前
从回测到全自动实盘交易,全天候策略需要经历哪些改造?
大数据·人工智能·python·算法·金融
fox_lht2 小时前
第十五章 函数式语言:迭代器和闭包
开发语言·后端·学习·算法·rust
zhengzhouliuhaha3 小时前
智能医疗设备控费系统:以全院一体化管控,筑牢医疗资源“安全阀”
大数据·数据结构·人工智能·算法·安全·机器学习·软件需求
June`3 小时前
CUDA程序效率如何计算以及工具如何使用
算法·cuda
兰令水3 小时前
leecodecode【树形DP】【2026.6.11打卡-java版本】
java·算法·深度优先
装不满的克莱因瓶3 小时前
RLHF中的PPO算法——大语言模型对齐优化的核心引擎
人工智能·python·深度学习·算法·机器学习·语言模型·自然语言处理