【数据结构与算法】二叉排序树构造与遍历

【问题描述】

从标准输入中读入n个数值元素,请将它们用二叉排序树存储,并输出该二叉排序树的层次和中序序列.

【输入形式】

首先输入一个整数n表示元素个数,然后再依次输入n个元素的值,每个元素之间用空格分割.例如:
8
50 35 70 40 50 65 20 80
说明:表明有8个元素,分别为50,35,70,40,50,65,20,和80.

【输出形式】

输出形式为两行,第一行为二叉排序树的层次数,第二行为二叉排序树的中序序列.

【样例输入】

10
50 30 80 10 90 95 70 75 60 40

【样例输出】

4
10 30 40 50 60 70 75 80 90 95

【样例说明】

样例输入表明有10个元素,分别为50,30,80,10,90,95,70,75,60和40,所建立的二叉排序树为
在这里插入图片描述
则上述二叉树的层次为4,中序序列为10 30 40 50 60 70 75 80 90 95。
所以输出应该为:
4
10 30 40 50 60 70 75 80 90 95


从题目中可以看出,这是一道考察有关二叉排序树的问题。有关二叉排序树,它有如下特点:

  1. 对于任意一个非叶子节点,其值大于其左子节点的值并且小于右子节点的值;
  2. 对二叉排序树进行中序遍历可以得到一个递增的数列;
  3. 在一般情况下,其查询效率要大于一般的线性链表。

根据百度百科,二叉排序树有以下三种定义:

  • 一棵空树,或者是具有下列性质的二叉树:
    (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    (3)左、右子树也分别为二叉排序树;
    (4)没有键值相等的结点。
  • 一棵空树,或者是具有下列性质的二叉树:
    (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    (2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
    (3)左、右子树也分别为二叉排序树;
  • 一棵空树,或者是具有下列性质的二叉树:
    (1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;
    (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    (3)左、右子树也分别为二叉排序树;


    其实不论哪种定义都是为了更加准确的描述一件事物,所以对以上三种定义都可以加以思考,进而得出自己对于二叉排序树的定义。

代码

#include <bits/stdc++.h>
using namespace std;

typedef struct NODE
{
    int val;
    NODE *left;
    NODE *right;
} Node;

void del(Node *head)
{
    if (head->left != nullptr)
        del(head->left);
    if (head->right != nullptr)
        del(head->right);
    head->left = nullptr;
    head->right = nullptr;
    free(head);
    head = nullptr;
}

void insert(Node *&head, int val)
{
    Node *tmp = (Node *)malloc(sizeof(Node));
    Node *cur = head;
    if (tmp == nullptr)
        exit(-1);
    tmp->val = val;
    tmp->left = nullptr;
    tmp->right = nullptr;

    if (head == nullptr)
        head = tmp;
    else
    {
        while (true)
        {
            if (cur->val >= val)
            {
                if (cur->left == nullptr)
                {
                    cur->left = tmp;
                    return;
                }
                else
                    cur = cur->left;
            }
            else
            {
                if (cur->right == nullptr)
                {
                    cur->right = tmp;
                    return;
                }
                else
                    cur = cur->right;
            }
        }
    }
}

void dfs(Node *head, vector<int> &lds, int &a, int dep)
{

    a = max(a, dep);
    if (head->left != nullptr)
        dfs(head->left, lds, a, dep + 1);
    lds.push_back(head->val);
    if (head->right != nullptr)
        dfs(head->right, lds, a, dep + 1);
}

int main(int argc, char *argv[])
{
    cin.tie(NULL);
    cout.tie(NULL);
    ios::sync_with_stdio(false);

    int n, depth = 0, a;
    Node *head = nullptr;
    vector<int> lds;

    cin >> n;
    lds.reserve(n);
    for (int i = 0; i < n; i++)
    {
        cin >> a;
        insert(head, a);
    }

    dfs(head, lds, depth, 1);

    cout << depth << endl;
    for (int tmp : lds)
        cout << tmp << " ";

    del(head);

    return 0;
}
  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A91A981E

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值