一、先序+中序
先序遍历会先遍历根,所以从左到右遍历,然后找到其在中序里的位置,将中序分为左右两个部分,递归下去,如果l==r,则代表为叶子结点,那么就返回该结点。
#include <iostream>
using namespace std;
string pre, in;
int pos = -1;
struct NODE {
char data;
NODE *left = nullptr, *right = nullptr;
};
int findt(char c) {
for (int i = 0; i < in.size(); i++)
if (c == in[i])
return i;
return -1;
}
NODE *creat(int l, int r) {
NODE *now_node = new NODE();
++pos;
now_node->data = pre[pos];
if (l == r)
return now_node;//叶子结点
int t = findt(pre[pos]);
now_node->left = creat(l, t - 1);
now_node->right = creat(t + 1, r);
return now_node;
}
int main() {
int n;
cin >> n >> pre >> in; //结点总数、先序、中序
NODE *root = creat(0, n - 1);
return 0;
}
二、后序+中序
这个代码非常的巧妙,(我看懂要好久,泪目了o(╥﹏╥)o)。不如直接理解:
利用后序,在中序中找根,记根在中序的位置为i,而这个i将中序分为左右两部分。
找左子树的时候,结点数变为了i-1,然后就在前i-1个位置中找根;
找右子树的时候,结点数则变为了num-i,中序数组往后偏移i个位置(因为前i个位置是左子树),后序数组往后偏移i-1个位置(因为前i-1个位置是左子树)。
输入:
结点个数,后序遍历的数组,中序遍历的数组
输出:
先序遍历的结果
#include <iostream>
using namespace std;
int in[31],post[31];
// in为中序遍历结果,post为后序遍历的结果, num代表当前的节点数
void pre(int post[], int in[], int num) {
if(num==0) return;
cout<<" "<<post[num];
int i;
for (i = 1; i <= num; i++) {
if (in[i] == post[num])
break;
}
pre(post, in, i-1);
pre(post + i-1, in + i , num - i);
}
int main() {
int num;
cin>>num;
for (int i = 1; i <= num; i++)
cin>>post[i];
for (int i = 1; i <= num; i++)
cin>>in[i];
cout<<"Preorder:";
pre(post, in, num);
return 0;
}
再写了一个字符串版本的,完全抄上面的xs:
#include <iostream>
using namespace std;
// in为中序遍历结果,post为后序遍历的结果, num代表当前的节点数
void pre(string post, string in, int num) {
if(num==0) return;
cout<<post[num];
int i;
for (i = 1; i <= num; i++) {
if (in[i] == post[num])
break;
}
pre(post, in, i-1);
pre(post.substr(i-1),in.substr(i), num - i);
}
int main() {
string post,in;
cin>>post>>in;
int num=post.size();
post='#'+post;
in='#'+in; //就硬抄数组,因为数组下标从1开始,就让字符串前面弄个没用的东西
pre(post,in,num);
return 0;
}
再写一个建树的版本:
#include <iostream>
#define MAXN 10000
using namespace std;
int post[MAXN],in[MAXN],n;
struct NODE{
int data;
NODE* left=nullptr,*right=nullptr;
};
int findl(int item){
for(int i=1;i<=n;i++){
if(item==in[i]) return i;
}
return -1;
}
NODE* creat(int l,int r,int L,int R){
if(l>r) return nullptr;
NODE *now=new NODE();
now->data=post[r];
if(l==r) return now;
int len=findl(post[r])-L;
now->left=creat(l,l+len-1,L,L+len-1),now->right=creat(l+len,r-1,L+len+1,R);
return now;
}
void dfs(NODE* now){
cout<<" "<<now->data;
if(now->left) dfs(now->left);
if(now->right) dfs(now->right);
}
int main() {
cin>>n;
for(int i=1;i<=n;i++) cin>>post[i];
for(int i=1;i<=n;i++) cin>>in[i];
cout<<"Preorder:";
dfs(creat(1,n,1,n));
cout<<endl;
return 0;
}