團體程式設計天梯賽-玩轉二叉樹(簡潔建樹)

dylolorz發表於2020-11-18

題目來源

https://pintia.cn/problemsets/994805046380707840/problems/994805065406070784

題目描述

在這裡插入圖片描述

題解思路

知道中序和前序,就可以唯一確定二叉樹.

1 2 3 4 5 6 7 中序
4 1 3 2 6 5 7 前序

樣例中,4為整棵樹的根節點,從4進入,在中序中找到4,因為中序遍歷先訪問左子樹,再根節點,再右子樹,因此中序中4左側就為左子樹結點,記此時根節點左子樹結點數為a,右側為右子樹結點,記此時根節點右子樹結點數為b。而前序遍歷先訪問根,再左子樹再右子樹,所以在前序中從根下一個節點開始算,接下去a個數則為4的左子樹結點,在左子樹結束的下一個到結束則為右子樹結點。設定好邊界,接下去遞迴處理左子樹右子樹。題中的反轉,只需要在遞迴時,將lchild和rchild時候反過來即可。最後利用佇列進行層序遍歷。

題解程式碼

#include <iostream>
#include <queue>
using namespace std;
const int N=100010;
int sz1[1010],sz2[1010];
int n,flag;
typedef struct node
{
	int data;
	struct node *lchild;
	struct node* rchild;
}node,*root;
root build(int l1,int r1,int l2,int r2)//在前序中樹範圍為l1到r1,中序中樹的範圍為l2到r2
{
	if(l1>r1)return NULL;
	int pos=l2;
	while(pos<=r2&&sz1[l1]!=sz2[pos])pos++;//找到中序中在l2到r2之間和此時的根節點sz1[l1]相等的座標pos
	node *no=(root)malloc(sizeof(node));
	no->data=sz1[l1];//根節點建立按
	no->rchild=build(l1+1,l1+pos-l2,l2,pos-1);//反轉後右子樹指標指向左子樹的遞迴。
	no->lchild=build(l1+pos-l2+1,r1,pos+1,r2);
	return no;
}
void fun(root p)
{
	//cout<<p->data<<" ";
	queue<root>q;
	q.push(p);
	while(q.size())
	{
		root now=q.front();
		q.pop();
		if(!flag)cout<<now->data,flag=1;
		else cout<<" "<<now->data;
		if(now->lchild!=NULL)q.push(now->lchild);
		if(now->rchild!=NULL)q.push(now->rchild);
	}
}
int main(void)
{
	cin>>n;
	for(int i=1;i<=n;i++)cin>>sz2[i];
	for(int i=1;i<=n;i++)cin>>sz1[i];
	node *roo=build(1,n,1,n);//建立二叉樹
	fun(roo);//層序遍歷
	//system("pause");
	return 0;
}

相關文章