最近機考,複習一下。之前做這道題時候沒有用遞歸,今天用遞歸寫了一下。
前序:4,3,1,2,5,6,7
中序: 1,3,2,4,6,5,7
後序: 1,2,3,6,7,5,4
思想很簡單,就是前序的第一個一定是根,在中序的輸出中,這個點左側的都是左子樹,右邊的都是右子樹。然後再遞歸的分別找左右子樹的根。
代碼如下:
#include <iostream>
using namespace std;
int Left[100001]={0},Right[100001]={0},weight[100001]={0};
int root;
int find_root(int pre[],int mid[],int length)
{
int index=0;
if(length==0)
return 0;//葉用0來表示
for(;index<length;++index)
{
if(mid[index]==pre[0])
break;
}
Right[mid[index]]=find_root(pre+index+1,mid+index+1,length-index-1);
Left[mid[index]]=find_root(pre+1,mid,index);
return mid[index];
}
void postOrder(int root)
{
if(Left[root]!=0)
postOrder(Left[root]);
if(Right[root]!=0)
postOrder(Right[root]);
cout<<root;
}
int main()
{
int pre[]={4,3,1,2,5,6,7};
int mid[]={1,3,2,4,6,5,7};
root = find_root(pre,mid,7);
postOrder(root);
return 0;
}
之前寫了個非遞歸的很長的代碼,不適合機考。【話說你們這幫人機考一個類都不寫真的好麼==】
非遞歸的核心代碼:
void BinaryTree::creatTree()
{
ifstream fin("chenrenwangaijiexi.txt");
char A[100],B[100];
int i(0);int j(0);
char ch = fin.get();
while(ch!='\n')
{
if(ch!=' ')
A[i++]=ch;
ch = fin.get();
}
A[i]='\0';
while(fin>>ch)
{
B[j++]=ch;
}
B[j]='\0';
////////////////////////////
int len_a = strlen(A);
root = new Node(A[0]);
for(i=1;i<len_a;++i)
{
ch = A[i];
Node* curr = root;
while(1)
{
if(isLeft(B,ch,curr->data)){
if(curr->left==NULL){curr->left=new Node(ch);break;}
else {curr=curr->left;continue;}
}
else{
if(curr->right==NULL)
{curr->right=new Node(ch);break;}
else{curr = curr->right;continue;}
}
}
}
}
裏面的isLeft是用於判斷在中序遍歷B中的相對位置,進而判斷在做子樹或者右子樹上面。
inline bool isLeft(char a[],int ch1,int ch2)
{
return strchr(a,ch1)<strchr(a,ch2);
}
strchr是<cstring>裏面的一個判斷位置的函數。
非遞歸的函數比較難以理解,就是先找到跟,然後不斷地去判斷pre輸出裏面的每一個節點的值再中序遍歷中是在這個點的左邊還是右邊,如果是在根的左邊,就和跟的左邊比較,在右邊就和右邊的比較,直到左或者有子樹爲空,這樣就可以插入這個節點的值了。不斷地插入,直到所有的節點值都插入就結束了。