#include<bits/stdc++.h>
using namespace std;
const int N=100+10;
const int inf=0x3f3f3f3f;
struct node
{
char data;
struct node *l,*r;
}*root;
void built(char x[],char z[],int len,node* &tmp)
{
if(len==0) return;
int index=0;
tmp=new node;//申请空间
tmp->data=*x;
tmp->l=NULL;
tmp->r=NULL;
while(index<len)
{
if(z[index]==*x) break;
index++;
}
built(x+1,z,index,tmp->l);
built(x+1+index,z+index+1,len-index-1,tmp->r);
}
void print(node *t)//三序遍历
{
if(t){
printf("%c ",t->data);
print(t->l);
print(t->r);
}
}
void bfs(node *t)//层序遍历
{
queue<node*> q;
q.push(t);
while(!q.empty())
{
node* tmp =q.front();q.pop();
printf("%c ",tmp->data);
if(tmp->l) q.push(tmp->l);
if(tmp->r) q.push(tmp->r);
}cout<<endl;
}
int high(node *t)//深度
{
if(!t) return 0;
return max(high(t->l),high(t->r))+1;
}
int main()
{
int n;cin>>n;
char xian[N],zhong[N];
for(int i=0;i<n;i++) cin>>xian[i];
for(int i=0;i<n;i++) cin>>zhong[i];
built(xian,zhong,n,root);
print(root);cout<<endl;
printf("%d\n",high(root));
bfs(root);
return 0;
}
根据后序和中序遍历输出先序遍历 (25分)
#include<bits/stdc++.h>
using namespace std;
const int N=100+10;
const int inf=0x3f3f3f3f;
int a[N],b[N],c[N];//前中后
int k=0,n;
void solve(int h[],int z[],int len)
{
if(len<=0) return;
int tmp=h[len-1];
a[k++]=tmp;
int index=0;
while(index<len)
{
if(z[index]==tmp) break;
index++;
}
solve(h,z,index);
solve(h+index,z+index+1,len-index-1);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>c[i];
for(int i=0;i<n;i++) cin>>b[i];
solve(c,b,n);
printf("Preorder:");
for(int i=0;i<n;i++) printf(" %d",a[i]);
printf("\n");
return 0;
}
根据两种遍历顺序确定树结构(build-tree)
题目描述
输入
第1行:二叉树的前序遍历顺序
第2行:中序遍历顺序
输出
二叉树的后序遍历顺序
样例输入
ABCDEFGH
CBEDAGHF
样例输出
CEDBHGFA
分析:
这道题最核心的问题在于如何建树(或模拟建树),类似于分治(递归) ,我们设先序串为a,中序串为b,用全局变量s表示在a中查找到了第几个数
先看样例,从a可知A是根节点,再根据中序遍历的性质判定在b中,A的左儿子一定在A的左边,右儿子一定在A的右边
再由先序遍历的性质得B是A的左儿子,此时s=1,再递归搜索B的左右儿子,当B搜完后,s=5(F),那么A的右儿子就是F,再递归搜索F的左右儿子,整个程序就可以递归了
当带参数的时候应该规定当前结点的左右儿子应该在哪个范围里找,否则会错乱
#include<bits/stdc++.h>
using namespace std;
const int N=1000+10;
const int inf=0x3f3f3f3f;
char a[N],b[N],c[N];//前中后
int s=1,n;
struct node
{
int l,r;
}f[260];
void dfs(int q,int w,int o)
{
if(s==n+1) return;
for(int i=1;i<=w;i++)
if(b[i]==a[s])
{
if(!f[o].l) f[o].l=b[i];
else f[o].r=b[i];
s++;
dfs(q,i-1,b[i]);
dfs(i+1,w,b[i]);
}
}
void hdfs(int a)
{
if(a)
{
hdfs(f[a].l);
hdfs(f[a].r);
printf("%c",a);
}
}
int main()
{
scanf("%s%s",a+1,b+1);
n=strlen(a+1);
dfs(1,n,0);
hdfs(a[1]);
return 0;
}
还原二叉树 (25分)
#include<bits/stdc++.h>
using namespace std;
struct Tree{ //树的节点
char data;
struct Tree *lchild;
struct Tree *rchild;
}treenode,*tree;
tree t = NULL;
void xianzhong(char x[],char z[],int size,tree &tmp){ ///根据先序中序构造二叉树
if(size == 0) return; ///注意引用的使用
int index = 0;
tmp = (tree)malloc(sizeof(treenode)); ///需要为节点分配空间
tmp->data = *x; ///先序的子序列的第一个元素是其根节点
tmp->lchild = NULL; ///注意这里的初始化很重要
tmp->rchild = NULL;
while(index < size){ ///每次找到先序的根节点的位置
if(*(z+index) == *x) break;
index++;
}
xianzhong(x+1,z,index,tmp->lchild); ///构造左孩子
xianzhong(x+1+index,z+index+1,size-index-1,tmp->rchild); ///构造右孩子
}
void print(tree t){ //先序输出,调试时使用
if(t != NULL){
printf("%d ",t->data);
print(t->lchild);
print(t->rchild);
}
}
int high(tree t){ ///计算树的深度
if(!t) return 0;
int lh = high(t->lchild); ///递归找到叶子,然后从叶子节点一层一层往上数
int rh = high(t->rchild);
if(lh > rh) return ++lh; ///那边高度高就在那边加1
return ++rh;
}
int main()
{
int n;
scanf("%d",&n);
char xianxu[55]; ///先序序列
char zhongxu[55]; ///中序序列
scanf("%s%s",xianxu,zhongxu);
xianzhong(xianxu,zhongxu,n,t);
printf("%d\n",high(t));
return 0;
}