DS二叉排序树之查找

Description

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

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

Input

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

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

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

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

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

以此类推输入下一个示例

Output

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

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

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

Sample

#0
Input

Copy

1
6
22 33 55 66 11 44
7
11
22
33
44
55
66
77
Output

Copy

11 22 33 44 55 66 
2
1
2
4
3
4
-1

思路:

1.构建二叉排序树:

       这里我的想法是与查找一样的,从根节点开始比较,然后每次遇到一个节点与他的值相比较,小的话就往左子树走,大的话就往右子树走。
       构建二叉树的时候,那肯定是插入一个新节点,那肯定那个节点插入之前是空的,所以找到符号位置条件的空节点就好啦!

手绘实操:

假设有22 11 33 三个数据,要构建一个平衡树:
1.选择第一个为根节点,22为根节点


2.插入数据11,11<22,所以往左子树走,然后遇到空值,就在这插入


3.然后插入33,33>22,往右子树走,且遇到空值就插入


4.这时候可能疑惑如果又要往左子树走,又要往右子树走的呢?
这里我们假设插入13,13<22,往左子树走,
然后13>11,13往右子树走,遇到空值,这个位置就是适合13插入的点


构建二叉排序树代码主要实现:

1.构建树必须的创造一个树节点的结构体:


2.建立树,其中分为两步,第一步构建根节点
ss队列是我用来存输入的数据,这样可以按顺序取


然后将后面的数据插入


插入的实现步骤:

tips:

因为我这里先创建了根节点,然后插入的时候每次传了root根节点进去,然后insert()函数里面会改变节点状态,所以为了让改变起作用,需要用到引用
void insert(nod*& root, int val);

2.查找元素

1.这里用到其实跟插入的思想一样,比这个节点小就往左走,比这个节点大就往右走
2.本题需要计算查找的时候需要的次数,所以我们可以传一个times进去,初始为1,因为进去就有个判断是否与根节点相等,也是一次查找
3.若根节点与值不相等,就按大小去递归查找,查找一次次数就+1
有点dfs计算高度那个味道了


全部代码:

#include <iostream>
#include <queue>
using namespace std;
struct nod///树节点
{
    int val;///节点的值
    nod* left, * right;///节点的左右子树指针
    nod()
    {
        left = NULL;
        right = NULL;
    }
    nod(int x)
    {
        val = x;
        left = NULL;
        right = NULL;
    }
};
queue<int>ss;
void insert(nod*& root, int val)
{
    if (root == NULL)///先看下面两个if 2,3
    {
        root = new nod(val);///我们经历了下面的两个if里的递归会走到一个合适的空节点,这个时候插入这个val
        return;
    }
    ///2
    if (val < root->val)///如果val的值小于这个节点的值,那就要往左子树走,然后利用递归
    {
        insert(root->left, val);///往左子树走插入
    }
    ///3
    if (val > root->val)///如果val的值大于这个节点的值,那就要往右子树走,然后利用递归
    {
        insert(root->right, val);///往右子树走插入
    }
}
nod* buildtree()///构建树的代码
{
    if (ss.empty())///这里是判断是否有数据可以构建树
        return NULL;
    nod* root;///构建根节点
    root = new nod(ss.front());///序列的第一个数作为根节点
    ss.pop();
    while (!ss.empty())///判断是否还有可以插入的数据
    {
        int val = ss.front();///按顺序取数据
        ss.pop();
        insert(root, val);///插入进树里
    }
    return root;
}
void zhonxu(nod* root)
{
    if (root == NULL)
        return;
    zhonxu(root->left);
    cout << root->val << " ";
    zhonxu(root->right);
}
int search(nod* root, int num, int times)
{
    if (root == NULL)///遇到空节点就是没有找到就返回-1
        return -1;
    if (root->val == num)///节点值相等就返回查找次数
        return times;
    if (num < root->val)///查找值小于节点值
    {
        return search(root->left, num, times + 1);///往左子树查找,且查找次数+1
    }
    if (num > root->val)///查找值大于节点值
    {
        return search(root->right, num, times + 1);///往右子树查找,且查找次数+1
    }
}
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
            int num;
            cin >> num;
            ss.push(num);///将所有数据放入队列里方便按顺序取出
        }
        nod* root = buildtree();///构建查找二叉树
        zhonxu(root);///本题需要输出一次中序遍历,也可以用来检验你的树建立的对不对
        cout << endl;
        int t;
        cin >> t;//查找数据次数
        while (t--)
        {
            int num;
            cin >> num;///查找的值
            int times = 1;
            times = search(root, num, times);///查找num需要用到多少次times
            cout << times << endl;///输出查找num需要的次数
        }
    }
    return 0;
}

今天的分享就到这啦!
晚安晚安晚安晚安!!!!!!

  • 41
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值