二叉树:已知先序遍历和中序遍历求后序遍历(同时也是华科某年上机题)

这篇博客介绍了如何根据已知的先序和中序遍历,来求解二叉树的后序遍历。内容包括解决思路和通用方法,适用于不同形式的数据输入。
#include<bits/stdc++.h>
using namespace std;

/*已知先序和中序求后序*/
void transfer(char *preorder,char *inorder,int len)
{
    int i,left_len,right_len;//left_len,right_len分别表示每次找到根之后左右子树的节点个数
    left_len=right_len=0;
    char *p,*q;//q指向先序,p指向中序
    if(len==0)//长度为0就返回
        return;
    q=preorder;
    p=inorder;
    while(*p++!=*q)//循环结束时,说明找到了根的位置,然而此时的p指向根的后面一个元素因为++了,并且可以算出left_len,right_len
        left_len++;
    right_len=len-left_len-1;
    transfer(q+1*sizeof(char),inorder,left_len);//左子树递归
    transfer(q+(left_len+1)*sizeof(char),p,right_len);//右子树递归,注意这里的p不需要++,它已经指向刚才相等元素的后一个地址了,因为while语句中写的是*p++
    printf("%c",*q);//打印元素,在左右之后打印也符合后序遍历的特点吧
}

int main()
{
    char preorder[100],inorder[100];
    while(scanf("%s%s",preorder,inorder)!=EOF)
    {
        transfer(preorder,inorder,strlen(preorder));
        printf("\n");
    }
}


2018.7.3更新

有一种更为通用的方法,若出的不是字符串就麻烦了,但是基本思路是一样的。

#include <bits/stdc++.h>
using namespace std;
#define MAX 1000
int pre[MAX];//先序遍历输出
int mid[MAX];//中序遍历输出

typedef struct bnode//二叉树结构体定义
{
    int data;
    struct bnode *lchild,*rchild;
}BNode,*bitree;

/*根据递归定义,这个二叉树是先构造一个根节点,然后它的左指针和它的右指针分别又是递归定义*/
bitree construct_tree(int pre_left,int pre_right,int mid_left,int mid_right)//通过先序和中序构建一个二叉树
{
    int index,cn;//index确定根节点在中序遍历中数组下标,cn表示根的左子树的结点个数
    bitree bt;
    if(pre_left>pre_right||mid_left>mid_right)//边界条件,左边不可能大于右边,顶多等于,因此直接返回为空
        return NULL;
    bt=new BNode[sizeof(BNode)];//构造一个二叉树
    bt->data=pre[pre_left];//这个二叉树的根节点就是先序遍历的第一个元素
    if(pre_left==pre_right)//如果此时左右相等,说明此时就只有一个结点,就说明递归到叶子结点了,直接让左右孩子为NULL就行了
    {
        bt->lchild=bt->rchild=NULL;
        return bt;
    }
    for(index=mid_left,cn=0;index<=mid_right;index++,cn++)//找到中序遍历中根的下标,同时更新cn
    {
        if(mid[index]==pre[pre_left])
            break;
    }
    bt->lchild=construct_tree(pre_left+1,pre_left+cn,mid_left,mid_left+cn-1);//左子树递归
    bt->rchild=construct_tree(pre_left+cn+1,pre_right,index+1,mid_right);//右子树递归
}

void posorder(bitree bt)//后序遍历
{
    if(bt)
    {
        posorder(bt->lchild);
        posorder(bt->rchild);
        cout<<bt->data<<" ";
    }
}

int main()
{
    int n,i;
    while(cin>>n)
    {
        bitree bt;
        for(i=0;i<n;i++)
            cin>>pre[i];
        for(i=0;i<n;i++)
            cin>>mid[i];
        bt=construct_tree(0,n-1,0,n-1);
        posorder(bt);
        cout<<endl;
    }
}

在C语言中,如果你已经知道了二叉树序遍历(Preorder Traversal)序遍历(Inorder Traversal),可以通过这两个序列重构出后序遍历(Postorder Traversal)。这是因为对于任何一个节点,它的后序遍历顺序通常是左子树 -> 右子树 -> 节点本身。 首,我们需要三个指针分别表示当前节点、前驱节点待访问的左子树。后序遍历的算法步骤如下: 1. 初始化后序遍历结果数组 `postorder` 长度 `size`。 2. 使用序遍历构建线索(即通过第一个元素找到根节点): - 序遍历的第一个元素作为根节点的线索。 3. 对于线索所指的节点,递归地处理左子树右子树: - 如果线索指向的是左子节点,那么它就是后序遍历中的下一个节点,将其添加到 `postorder` 并更新线索到下一个元素。 - 如果线索指向的是右子节点,那么需要完成左子树的后序遍历,然后继续这个右子节点。 4. 当线索为空时,说明已经处理完了当前节点及其所有子节点,将当前节点添加到 `postorder` 的最后一位,并返回 `size`。 5. 最终 `postorder[0:size-1]` 就是后序遍历的结果。 以下是一个简单的C语言实现示例: ```c #include <stdio.h> typedef struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; } TreeNode; // 从序遍历序遍历构造后序遍历 void buildPostorder(int preorder[], int inorder[], TreeNode* root, int size, int *postorder, int postSize) { if (root == NULL || size <= 0) return; // 找到根节点在中序遍历中的位置 for (int i = 0; i < size && inorder[i] != root->val; i++) ; // 递归处理左右子树 buildPostorder(preorder, inorder, root->left, i, postorder, postSize); buildPostorder(preorder + i + 1, inorder + i + 1, root->right, size - (i + 1), postorder, postSize); // 将根节点添加到后序遍历的末尾 postorder[postSize++] = preorder[size - 1]; } int main() { // 示例输入:序遍历 [1, 2, 4, 5, 3, 6] // 中序遍历 [4, 2, 5, 1, 3, 6] int preorder[] = {1, 2, 4, 5, 3, 6}; int inorder[] = {4, 2, 5, 1, 3, 6}; int size = sizeof(preorder) / sizeof(preorder[0]); int postSize = 0; TreeNode* root = createTreeFromPreAndInOrder(preorder, inorder); // 根据给定的中序创建二叉树 int postorder[size]; // 后序遍历结果数组 buildPostorder(preorder, inorder, root, size, postorder, &postSize); // 输出后序遍历结果 for (int i = 0; i < postSize; i++) { printf("%d ", postorder[i]); } return 0; } ``` 注意,这里假设有一个 `createTreeFromPreAndInOrder` 函数用于根据给定的序遍历序遍历构建二叉树,你需要自定义这个函数。此外,上述代码未包含错误处理边界条件检查,实际应用时请确保适当增加。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值