树结构练习——排序二叉树的中序遍历

Problem Description

在树结构中,有一种特殊的二叉树叫做排序二叉树,直观的理解就是——(1).每个节点中包含有一个关键值 (2).任意一个节点的左子树(如果存在的话)的关键值小于该节点的关键值 (3).任意一个节点的右子树(如果存在的话)的关键值大于该节点的关键值。现给定一组数据,请你对这组数据按给定顺序建立一棵排序二叉树,并输出其中序遍历的结果。

Input

输入包含多组数据,每组数据格式如下。
第一行包含一个整数n,为关键值的个数,关键值用整数表示。(n<=1000)
第二行包含n个整数,保证每个整数在int范围之内。
Output

为给定的数据建立排序二叉树,并输出其中序遍历结果,每个输出占一行。

Example Input

1
2
2
1 20
Example Output

2
1 20

Think: 基本的排序二叉树的题,如果是排序二叉树的升级版(平衡二叉树)的话就棘手了,因为在建树的过程中还要满足左右子树的深度(高度)差保持1(|1|)。本题就不用考虑这点。。。不过后台的数据似乎有坑点,在排序建树过程中“存在”两个节点数值相同的情况?我一开始做 的时候:如果当前的值比根大则在此根的右子树上继续判断(如果右子树不存在,当前值就成为此根的右子树了),如果小的话,类似。。。不过问题就出在这里,我要么大要么小,符合定义,不过如果数据值相同怎么办?(超时了。。。)所以我后来改为要么大要么else。。。就AC了。另外听名字“排序二叉树”,中序遍历的结果会是一组有序的序列(好神奇O(∩_∩)O哈哈~

纯C代码如下:(说实话我的代码有点长。。。)

#include<stdio.h>
#include<malloc.h>
#define OVERFLOW -1
typedef struct node
{
    int data;
    struct node *l, *r;
}Lnode;
int f;  //因为输出要求相邻两个数之间用空格隔开,最后一个数后没空格23333
Lnode *Creat(int n);  //创建有N个节点的排序二叉树
void mid(Lnode *t);  //中序输出排序二叉树
int main()
{
    int n;
    while(scanf("%d", &n) != EOF){
        if(n > 0){
            Lnode *t;
            t = NULL;
            f = 0;
            t = Creat(n);
            mid(t);
            printf("\n");
        }
    }
    return 0;
}
Lnode *Creat(int n)
{
    Lnode *head, *pr, *p;
    head = (Lnode *)malloc(sizeof(Lnode));  //祖宗节点
    if(!head)
        exit(OVERFLOW);
    head->l = NULL;
    head->r = NULL;
    int i;
    scanf("%d", &head->data);  //先解决祖宗节点问题N==1
    for(i = 2; i <= n; i++){
        p = (Lnode *)malloc(sizeof(Lnode));
        if(!p)  //开辟空间失败,结(不)束(能)程(玩)序(耍)2333
            exit(OVERFLOW);
        p->l = NULL;
        p->r = NULL;
        scanf("%d", &p->data);
        pr = head;  //每次从祖宗开始比较,接着下一代下一代~哈哈~
        while(pr){
            if(p->data > pr->data){  //如果当前值比“根”的值大,在右子树
                if(pr->r == NULL){ //如果这个跟无右子树
                    pr->r = p;     //那么当前的值就为它的右子树了
                    break;
                }
                else pr = pr->r;  //否则与其右子树上的节点比较出适合的位置
            }
            else{  //Think里我说的直接else情况
                if(pr->l == NULL){
                    pr->l = p;
                    break;
                }
                else pr = pr->l;
            }
        }
    }
    return head;  //返回祖宗节点
}
void mid(Lnode *t)  //中序遍历访问输出
{
    if(t){
        mid(t->l);  //递归调用自身。。。
        if(!f){  //如果f==0
            printf("%d", t->data); //后面没空格,只有一个节点的情况也适用
            f++;  //本身+1                               //Yeah
        }
        else printf(" %d", t->data); //从第二个节点到最后就输出前有空格了
        mid(t->r);
    }
    return ;
}
用C++求二叉树中序遍历的结果并打印可以使用递归方法实现,具体步骤如下: 1. 如果当前结点为空,返回。 2. 递归遍历左子。 3. 输出当前结点。 4. 递归遍历右子中序遍历的最后一个结点即为二叉树的最右下角结点,可以在递归遍历时记录最后一个结点。 中序遍历的第n个结点可以在递归遍历时使用一个计数器来记录当前是第几个结点,并在遍历到第n个结点时输出。 以下是示例代码: ```c++ #include <iostream> using namespace std; // 二叉树结点定义 struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; void inorderTraversal(TreeNode* root) { if (root == NULL) { return; } inorderTraversal(root->left); cout << root->val << " "; inorderTraversal(root->right); } TreeNode* getInorderLastNode(TreeNode* root) { if (root == NULL) { return NULL; } while (root->right != NULL) { root = root->right; } return root; } int getInorderNthNode(TreeNode* root, int n, int& count) { if (root == NULL) { return -1; } int res = getInorderNthNode(root->left, n, count); if (count == n) { return root->val; } count++; if (res != -1) { return res; } return getInorderNthNode(root->right, n, count); } int main() { // 构建一个二叉树 TreeNode* root = new TreeNode(1); root->left = new TreeNode(2); root->right = new TreeNode(3); root->left->left = new TreeNode(4); root->left->right = new TreeNode(5); // 中序遍历 inorderTraversal(root); cout << endl; // 中序遍历的最后一个结点 TreeNode* lastNode = getInorderLastNode(root); cout << lastNode->val << endl; // 中序遍历的第n个结点 int n = 3; int count = 1; int nthNode = getInorderNthNode(root, n, count); cout << nthNode << endl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值