根据先序遍历和中序遍历的结果,求后序遍历

题目:
先序遍历:abdce —> a bd ce
中序遍历:dbaec —> db a ec
可看出 根结点为a,左子是bd,右子就是ce

先序 bd
中序 bd
二叉树中,位置是b为父,d为右子。

先序 ce
中序 ec
位置是 e为左子,c为右子。

Node* build(char pre_str[] , char in_str[] , int len) //前序建立二叉树 
{ 
	//根据输入的先序遍历和中序遍历的结果,创建链表树 
    Node *p = init(pre_str[0]);//将先序遍历的第一个字符存于树根, 
    int pos = strchr(in_str , pre_str[0]) - in_str;//找到树根第一次在中序遍历中出现的位置
    //返回第一处在in_str中出现的 pre_str[0]的位置 
    if (pos > 0) {
		p->lchild = build(pre_str + 1 , in_str , pos);
    }
    if (pos < len - 1) {
		p->rchild = build(pre_str + pos + 1 , in_str + pos + 1 , len - pos - 1);
    }
    return p;
}

树的代码总结

//构造完全二叉树的顺序存储结构
//按照层数从左到右存储,空元素存符号 
#define maxsize 1000
typedef char sqtree[maxsize]//属的元素类型为datatype 
void CreatBtree(sqtree bt)
{
	int i=1;
	char ch;
	ch=getchar();
	while(ch!='#')
	{
		bt[i]=ch;i++;ch=getchat();
	}
	bt[i]='#';
}

//链式存储结构
typedef char datatype;
typedef struct Bnode
{
	char data;
	struct Bnode*Lchild,*Rchild;
}Btnode,*BTptr;//结点,结点指针 

CreateLBtree(BTptr BT)//画出了树的图像,(已知左孩子右孩子) 
{
	datatype ch;//树结点的值 
	int i=0;
	BTptr p,q;//结点指针 
	Clearqueue(Q);//清空队列
	BT=NULL;//结点初始化 
	ch=getchar();
	while(ch!='#')//输入#作为结束树的标志 
	{
		p =NULL;
		if(ch!='@')//如果不等于虚结点 建立新结点,链入到父节点下 
					//虚结点就是相对完全二叉树来说本该有的孩子却为空,这时i++并且NULL入队 不做链接 
					//走流程p=NULL,不入本if,i++,NULL入队,i!=1进入else p为空不链接。 
		//使用队列技术确保正确链入 
		{
			p=(BTptr)malloc(sizeof(Btnode));//申请新结点 
			p->data=ch;//存入数据 
			p->Lchild=p->Rchild=NULL;//先初始化为空节点 
		}
		i++;//序号计数 
		Enqueue(Q,p);//队列Q存在且不满 将p元素插入队尾成为新元素
					//新结点地址入队 或者虚结点地址NULL入队 
		if(i==1) //有效节点从1开始
		{
			BT=p;//第一输入节点为根 
		}
		else	 //不是第一个 
		{
			q=Getqtop(Q);
			if(p&&q)//p和q都不为空
			{
				if(i%2==0)//偶数为左孩子
				q->Lchild=p;
				else//奇数为右孩子 从1开始算
				q->Rchild=p;
			} 
			if(i%2==1)
				Delqueue(Q);//两个孩子都找到了 出队。  Q->top++; 
		}
		ch=getchar();
	}
	return (BT);
}

//二叉树递归遍历
/*将层次结构线性化,得到类似线性表的序列
对节点p的访问 需要根据结点的datatype(数据类型)访问: 
	链表L->data 数组L[i] 队列Q->data[Q->top] 栈S->data[s->top]
	记得输出! 
记为visit(p)  是函数 根据数据类型和题目需要 补全 
*/
//1.前序遍历:
void preorder(BTptr T)//根节点指针为T 
{
	if(T)
	{
		visit(T);			//前   就是递归的结束标志 
		preorder(T->Lchild);//左 
		preorder(T->Rchile);//右 
	} 
}
//中序遍历 
void inorder(BTptr T)
{
	if(T)
	{
		inorder(T->Lchild);	//左 
		visit(T);			//前 
		inorder(T->Rchile);	//右
	}
} 
//后序
void postorder(BTptr T)
{
	if(T)
	{
		postorder(T->Lchild);
		postorder(T->Rchild);
		visit(T);
	}
} 

//前序建立二叉树 
BTptr creat()
{
	bitree *t;
	char ch;
	ch=getchar();
	if(ch==' ')
		t=NULL;
	else
	{
		t=(BTptr*)malloc(sizeof(Btnode));
		t->data = ch;
		t->lchild=creat();
		t->rchile=creat();
	}
	return t;
} 

//求二叉树的高度
int depth(BTptr *t)
{
	int dep1,dep2;//递归 左孩子高度和右孩子高度
	if(t==NULL)		//已经遍历完了 
	{
		return 1;	//深度加一 
	}
	else 
	{
		dep1=t->lchild();
		dep2=t->rchild();
		if(dep1>dep2) return dep1+1; //记得加一,还得算上自己 
		else return dep2+1;
	} 
} 

//二叉树镜像
		//即交换所有结点的左右子树
void change(BTptr t)  //传入参数 头指针 
{
	Btnode temp;
	if(t)
	{
		temp=t->lchild;
		t->lchild=t->rchild;
		t->rchiled=temp;		//自己的左子右子完成了交换 
		change(t->rchild);
		change(t->lchild); 
	} 
}

//统计叶子节点数目  左孩子结点加右孩子节点,直到左右孩子都为空返回1;
int leaf(Btptr t)
{
	if(t->rchild==NULL&&t->lchild==NULL)
	 return 1;
	else 
	return leaf(t->rchild)+leaf(t->lchild);
} 

//复制二叉树 复制结点的数值,左孩子,右孩子。直到 左右孩子都为空返回该节点指针
//本质是 创建新的树s 需要申请新的空间 
Btptr copy(btptr t) //t是当前需要复制的结点指针 
{
	btptr s;//创建新节点
	s=(btptr)malloc(sizeof(btnode)); 
	if(t!=NULL)
	{
		s->data=t->data;
		if(t->lchild!=NULL)
			{
			s->lchild=copy(t->lchild);
			}
		else
			s->lchild=NULL;
		if(t->rchild!=NULL)
			{
			s->rchild=copy(t->rchild);
			}
		else
			s->rchild=NULL;
	}
	return s;
} 
代码片
先序遍历后序遍历是树的两种遍历方法。在某些情况下,如果已知一棵树的先序遍历序列和后序遍历序列,可以通过特定的算法得该树的中序遍历序列。这里的关键在于利用先序和后序遍历的特性,先序遍历的第一个元素总是树的根节点,而后序遍历的最后一个元素也是树的根节点,此外后序遍历的最后一个元素之前的部分是所有子树的后序遍历序列,先序遍历的第二个元素开始到某个元素之间的部分是同一子树的先序遍历序列。通过这个特性,可以递归地构造整棵树,进而得到中序遍历序列。 具体步骤如下: 1. 先序遍历的第一个元素是树的根节点。 2. 在后序遍历序列中找到根节点,那么根节点之前的部分就是左子树的后序遍历,根节点之后的部分就是右子树的后序遍历。 3. 在先序遍历中,找到左子树的先序遍历序列(从根节点的下一个元素开始,直到左子树的节点数结束)和右子树的先序遍历序列(从左子树的结束位置开始,直到右子树的节点数结束)。 4. 对左子树和右子树递归地应用以上步骤,直到子树只有一个节点或者为空。 5. 对于每个子树,按照左子树的中序遍历、根节点、右子树的中序遍历的顺序组合成子树的中序遍历序列。 6. 最后,将所有子树的中序遍历序列拼接起来,即得到整棵树的中序遍历序列。 注意,这种方法假设树中没有重复元素,并且我们需要知道树的结构或者节点之间的关系才能使用这种方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值