各大公司招聘每次笔试都碰到这种题,今天来把它说清楚.
三序中知道其中两个就可以推出第三个,但前提是我们必须知道中序.因为:
先序和后序给我们提供的信息是一样的--告诉我们谁是根节点
中序则告诉我们左右子树在哪儿
例:已知先序为eacbdgf,中序为abcdefg,求后序
由先序我们知道e为根节点,我们在中序中把左右子树括起来 --(abcd)e(fg)
同样对左子树abcd进行分析,先序为acbd,中序为abcd.--a(bcd)
递归下去就可以了
后序为bdcafge
代码实现上述例子:
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
//定义二叉树的节点
typedef struct node{
char data;
struct node* left;
struct node* right;
}NODE;
//后根遍历打印二叉树
void postTrav(NODE* root){
//遍历左子树
if(root->left!=NULL)
postTrav(root->left);
//遍历右子树
if(root->right!=NULL)
postTrav(root->right);
//输出本节点
printf("%c",root->data);
}
//根据前序和中序建立二叉树
void buildTree(char* pre,char* mid,NODE* root){
int len=strlen(pre); //实际下先序序列和后序序列的长度是一样的
//序列长度为0,说明上一级已经是叶子节点,返回
if(len==0)
return;
//返回先序的第一个元素在中序中出现的位置
char* p=strchr(mid,pre[0]);
int pos=(int)(p-mid);
//建设子树的根节点
//先序中第一个元素作为本子树的根节点
root->data=pre[0];
if(pos!=0){ //当前节点的左子树是存在的
NODE* left=(NODE*)malloc(sizeof(struct node));
root->left=left;
//左子树根节点上的元素就是先序中的第2个元素
left->data=pre[1];
char* left_pre=(char*)malloc(pos*sizeof(char));
char* left_mid=(char*)malloc(pos*sizeof(char));
//找到左子树的先序和中序
strncpy(left_pre,pre+1,pos);
strncpy(left_mid,mid,pos);
//递归建立左子树
buildTree(left_pre,left_mid,left);
}
if(pos!=len-1){ //当前节点的右子树是存在的
NODE* right=(NODE*)malloc(sizeof(struct node));
root->right=right;
//右子树根节点上的元素就是先序中的第pos+2个元素
right->data=pre[pos+1];
char* right_pre=(char*)malloc((len-1-pos)*sizeof(char));
char* right_mid=(char*)malloc((len-1-pos)*sizeof(char));
//找到右子树的先序和中序
strncpy(right_pre,pre+pos+1,len-1-pos);
strncpy(right_mid,mid+pos+1,len-1-pos);
//递归建立右子树
buildTree(right_pre,right_mid,right);
}
}
//主函数
int main(){
printf("input number of elements:\n");
int size=0;
scanf("%d",&size);
char* pre=(char*)malloc(size*sizeof(char));
char* mid=(char*)malloc(size*sizeof(char));
printf("input preorder:\n");
scanf("%s",pre);
printf("input midorder:\n");
scanf("%s",mid);
NODE* root=(NODE*)malloc(sizeof(struct node));
buildTree(pre,mid,root);
printf("the postorder is:\n");
postTrav(root);
printf("\n");
return 0;
}
这里顺便再介绍几个C语言里面的函数
首先对于指针变量必须先初始化malloc后才能使用,比如在上面的main函数中你没有char* pre=(char*)malloc(size*sizeof(char));就来个scanf("%s",pre);会发生段错误.
第1个函数:
表头文件#include<string.h>
定义函数char * strchr (const char *s,int c);
函数说明strchr()用来找出参数s字符串中第一个出现的参数c地址,然后将该字符出现的地址返回。
返回值如果找到指定的字符则返回该字符所在地址,否则返回0。
#include<string.h>
main()
{
char *s="0123456789012345678901234567890";
char *p;p=strchr(s,'5');
printf("%d\n",p-s);
}
第2个函数:
表头文件#include <string.h>
定义函数char *strpbrk(const char *s,const char *accept);
函数说明strpbrk()用来找出参数s 字符串中最先出现存在参数accept 字符串中的任意字符。
返回值如果找到指定的字符则返回该字符所在地址,否则返回0。
#include <string.h>
main()
{
char *s="0123456789012345678901234567890";
char *p;
p=strpbrk(s,"a1 839"); /*1会最先在s字符串中找到*/
printf("%d\n",(p-s));
p=strpbrk(s,"4398");/*3 会最先在s 字符串中找到*/
printf("%d\n",(p-s));
}
第3个函数:
表头文件#include<string.h>
定义函数char * strncpy(char *dest,const char *src,size_t n);
函数说明strncpy()会将参数src字符串拷贝前n个字符至参数dest所指的地址。
前提是dest必须能够容纳下n个字符.
返回值返回参数dest的字符串起始地址。
#inclue <string.h>
main()
{
char a[30]="string(1)";
char b[]="string(2)";
printf("before strncpy() : %s\n",a);
printf("after strncpy() : %s\n",strncpy(a,b,6));
}
C语言里面没有substr这样的函数,截取子串的功能就是通过strncpy来实现的,比如在我们的代码中有:
strncpy(left_pre,pre+1,pos);
这就是从pre的第2个元素开始,截取pos个字符放到left_pre中