對於二叉樹T,可以遞歸定義它的先序遍歷、中序遍歷和後序遍歷如下: PreOrder(T)=T的根節點+PreOrder(T的左子樹)+PreOrder(T的右子樹) InOrder(T)=InOrder(T的左子樹)+T的根節點+InOrder(T的右子樹) PostOrder(T)=PostOrder(T的左子樹)+PostOrder(T的右子樹)+T的根節點 其中加號表示字符串連接運算。例如,對下圖所示的二叉樹,先序遍歷爲DBACEGF,中序遍歷爲ABCDEFG。
輸入一棵二叉樹的先序遍歷序列和中序遍歷序列,輸出它的廣度優先遍歷序列。
第一行爲一個整數t(0<t<10),表示測試用例個數。 以下t行,每行輸入一個測試用例,包含兩個字符序列s1和s2,其中s1爲一棵二叉樹的先序遍歷序列,s2爲中序遍歷序列。s1和s2之間用一個空格分隔。序列只包含大寫字母,並且每個字母最多隻會出現一次。
爲每個測試用例單獨一行輸出廣度優先遍歷序列。
2 DBACEGF ABCDEFG BCAD CBAD
DBEACGF BCAD
先序遍歷的第一個字符就是根,因此只需在中序遍歷中找到它,就知道左右子樹的先序和中序遍歷了。例如:
先序:D BACEGF 中序:ABCD EFG
由先序遍歷的第一個字符D 可知,此二叉樹的根節點爲D ,並且:
左子樹的先序遍歷爲:BAC 中序遍歷爲:ABC
右子樹的先序遍歷爲:EGF 中序遍歷爲:EFG
根據此規律,可通過遞歸來重構二叉樹,然後層序遍歷輸出。
#include<iostream>
#include<queue>
#include<string>
using namespace std;
string pre,mid;
int len,pos;
struct Node{
Node *left;
Node *right;
char item;
Node(char ch=0)
{
left=right=NULL;
item=ch;
}
};
void build(Node *&root,int begin,int end)
{
if(begin>end||pos>=pre.size()) return ;//遞歸停止條件
root = new Node(pre[pos]);;
int mpos=mid.find(pre[pos++]); //由前序遍歷的首字母可以在中序遍歷序列中查找對應位置,將中序的序列切開左子樹跟右子樹
build(root->left,begin,mpos-1);//遞歸構建
build(root->right,mpos+1,end);
}
int main()
{
int time;
cin>>time;
while(time--)
{
cin>>pre>>mid;
len=pre.size();
pos=0;
Node *root=new Node();
build(root,0,len-1); //根據輸入的前序遍歷跟中序遍歷,構建一棵樹
queue<Node*>q;
q.push(root);
while(!q.empty()) //層序遍歷輸出
{
Node *midd=q.front();
q.pop();
cout<<midd->item;
if(midd->left) q.push(midd->left);
if(midd->right) q.push(midd->right);
}
cout<<endl;
}
return 0;
}
(程序實現參考來自網絡)自己實現還是有問題,樹果然沒學好。o(︶︿︶)o唉