二叉树无法输出,问题出在哪里啊,还有输出是ERROR的时候咋判断啊

7-9 还原二叉树
分数 10
作者 王云武
单位 浙大城市学院
给出一颗二叉树的中序遍历和后序遍历,请你实现以下两个需求:

(1)请你输出这颗二叉树的层序遍历。

(2)请你输出这颗二叉树的树高。

输入格式:
第一行包含一个整数N(N<=1000)。二叉树的节点将从1到N编号。

第二行包含N个节点编号,表示这颗二叉树的中序遍历。

第三行包含N个节点编号,表示这颗二叉树的后序遍历。

输出格式:
第一行输出二叉树的层序遍历,节点编号之间用空格分隔,末尾没有多余空格。

第二行输出一个整数,代表二叉树的树高。

题目不保证输入的序列合法,如果遇到不合法的情况,请在一行中输出"ERROR",直接退出程序。

输入样例:
在这里给出一组输入。例如:

6
6 5 4 3 2 1
5 6 2 3 1 4
输出样例:
在这里给出相应的输出。例如:

4 6 1 5 3 2
4
输入样例:
在这里给出一组输入。例如:

3
2 1 3
3 2 1
输出样例:
在这里给出相应的输出。例如:

ERROR


```c++
#include <iostream>
using namespace std;
#define MAX 1010
typedef struct Tnode
{
    int data;
    Tnode *lchild, *rchild;
}Tnode, *Tree;

typedef struct
{
    Tree *base;
    int front;
    int rear;
}Queue;

int treehigh ( Tree T )
{
    if ( T == NULL )
    {
        return 0;
    }
    int len1 = treehigh (T->lchild);
    int len2 = treehigh (T->rchild);
    return len1 > len2 ? len1+1:len2+1;
}

void creat ( Tree &T, int *in, int *post, int n)
{
    T = new Tnode;
    if ( n == 0 )
    {
        return;
    }
    int i;
    T->data = post[n-1];
    for ( i = 0; i < n; i ++ )
    {
        if ( in[i] == T->data )
        {
            break;
        }
    }
    creat (T->lchild, in, post, i);
    creat (T->rchild, in+i+1, post+i, n-i-1);
} 

void init ( Queue &Q )
{
    Q.base = new Tree[MAX];
    Q.front = Q.rear = 0;
}
void enqueue ( Queue &Q, Tree e )
{
    if (Q.rear == Q.front)
    {
         return;
    }
    Q.base[Q.rear] = e;
    Q.rear = Q.rear+1;
}

void dequeue( Queue Q, Tree &p )
{
    if ( Q.front == Q.rear )
    {
         return;
    }
    p = Q.base[Q.front];
    Q.front = Q.front + 1;
}

void LevelOrder( Tree T )
{
     Queue Q;
     init (Q);
     Tree p = T;
     enqueue (Q, T);
     while ( Q.front != Q.rear )
     {
          dequeue (Q, p);
          cout << p->data<<" ";
          if ( p->lchild != NULL )
          {
               enqueue (Q, p->lchild); 
          }
          if ( p->rchild != NULL )
          {
               enqueue(Q, p->rchild);
          }
     } 
}

int main ()
{
    Tree T;
    int n;
    cin >> n;
    int a[n], b[n];
    for ( int i = 0; i < n; i ++ )
    {
        cin >> a[i];
    }
    for ( int i = 0; i < n; i ++ )
    {
        cin >> b[i];
    }
    int *in = a;
    int *post = b; 
    creat (T, in, post, n);
    LevelOrder (T);
    cout <<endl;
    int high = treehigh (T);
    cout << high;
}

```

看起来代码实现还比较完整,不过有一个错误我注意到了。在 enqueuedequeue 函数中,队列传参类型是 Queue &Q,也就是引用,然而在这两个函数中又定义了一个新的队列 Queue Q,并且用它来实现队列的入队和出队操作,并没有传入作为参数的队列 Q,也没有通过指向队列的指针来进行操作。这样操作并不安全,可能会导致不可预期的结果。

因此,正确的写法应该是将 Queue Q 声明在 main 函数中,通过指针参数的方式将其传给入队和出队函数。具体地:

void init ( Queue &Q )
{
    Q.base = new Tree[MAX];
    Q.front = Q.rear = 0;
}

void enqueue ( Queue &Q, Tree e )
{
    if (Q.rear == Q.front)
    {
         return;
    }
    Q.base[Q.rear] = e;
    Q.rear = Q.rear+1;
}

void dequeue( Queue &Q, Tree &p )
{
    if ( Q.front == Q.rear )
    {
         return;
    }
    p = Q.base[Q.front];
    Q.front = Q.front + 1;
}

void LevelOrder( Tree T, Queue &Q )
{
     Tree p = T;
     enqueue (Q, T);
     while ( Q.front != Q.rear )
     {
          dequeue (Q, p);
          cout << p->data<<" ";
          if ( p->lchild != NULL )
          {
               enqueue (Q, p->lchild); 
          }
          if ( p->rchild != NULL )
          {
               enqueue(Q, p->rchild);
          }
     }
}

int main ()
{
    Tree T;
    int n;
    cin >> n;
    int a[n], b[n];
    for ( int i = 0; i < n; i ++ )
    {
        cin >> a[i];
    }
    for ( int i = 0; i < n; i ++ )
    {
        cin >> b[i];
    }
    int *in = a;
    int *post = b;
    creat (T, in, post, n);
    Queue Q;
    init (Q);
    LevelOrder (T, Q);
    cout <<endl;
    int high = treehigh (T);
    cout << high;
}

建议在以后编程时多留意这类传参方式和变量命名的问题,它们可能会影响到代码的正确性和可读性。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/7492818
  • 除此之外, 这篇博客: C语言实现八大排序算法详解及其性能之间的中的 名字已经暴露了他的算法,就是往里面插入数据,就拿我们生活中的例子来说,打扑克牌。我们往手里码牌的时候,是一张一张的码,先码一张,抓手心,不需要修改位置,因为只有一张牌,一定是有序的。再接一张,和手里的牌对比大小,调整位置,选择放在它的左边或者右边。然后接着码,又接到一张牌,拿到先和右边的牌比,比右边还大就放到最右边,如果比右边这张小呢,在和左边这张比。同样,我们这里也是这样的,首先我们默认第一个元素,一定是有序,OK吧。然后第二个,元素比较,大,放到左边,小放到右边。然后第三个元素,直到第N个,比它前一个大,继续往前找位置,直到找到对应位置了,就是有序数列了。(当然每次找位置都是在一个有序的序列中找,所以完全可以用二分查找找位置,数据大的话,二分明显快于我们一张一张比) 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    算法思想

  • 以下回答来自chatgpt:

    先分析问题:对于本题,首先需要将二叉树重建,然后需要输出它的层序遍历和树高,层序遍历可以用队列来实现,树高的求解可以递归实现。那么,我们的第一步就是将中序遍历和后序遍历重建为二叉树。

    对于输入数据的读取,可以先用fgets()函数读入一整行字符串,然后用sscanf()函数解析出整数和字符序列。下面给出相应的代码:

        int n;
        fgets(s, 1500, stdin);
        sscanf(s, "%d", &n);
        while(n--){
            fgets(s, 1500, stdin);
            sscanf(s, "%s", zhong);
            fgets(s, 1500, stdin);
            sscanf(s, "%s", hou);
            len = strlen(zhong);
            head = pai(hou+strlen(hou)-1, zhong+len-1, len);
            if(head == NULL) printf("ERROR\n");
            else{
                levelorder(head); //输出层序遍历
                printf("\n%d\n", height(head)); //输出树高
            }
        }
    

    对于重建二叉树,可以参考上文的递归建树代码,只需稍加改动就能解决本题的问题。

    对于输出层序遍历和树高,可以用队列和递归的方式来实现。下面给出输出层序遍历的伪代码和相应的代码:

    void levelorder(tree *head){
        queue Q;
        initialize(&Q); //初始化队列
        enqueue(&Q, head); //入队
        while(!isempty(&Q)){
            tree *temp = dequeue(&Q);
            if(temp){ //如果队列不为空
                printf("%c ", temp->data);
                enqueue(&Q, temp->Lchild);
                enqueue(&Q, temp->Rchild);
            }
        }
    }
    

    对于求解树高,由于是递归,所以可以用一个树高的回调函数,每次往下递归时就将相应的树高加1,那么树高的回调函数就可以写为:

    int height(tree *head){
        if(head == NULL) return -1; //空树的树高是0
        return max(height(head->Lchild), height(head->Rchild))+1; //递归调用求树高
    }
    

    至此,我们就解决了本题,完整代码如下:


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^