实习三 树、二叉树及其应用 (题目:唯一地确定一棵二叉树 )
一、需求分析
1.问题描述:如果给出了遍历二叉树的前序序列和中序序列,则可以构造出唯一的一棵二叉树。试编写实现上述功能的程序。
2.基本要求: 已知一棵二叉树的前序和中序序列,试设计完成下列任务的一个
算法:
(1)构造一棵二叉树;
(2)证明构造正确(即分别以前序和中序遍历该树,将得到的结
果与给出的序列进行比较)。
3.测试数据: 前序序列为ABDEGCFHIJ,中序序列为DBGEAHFIJC。
#include<stdio.h> #include<malloc.h> #include<string.h> typedef char DataType; typedef struct Node { DataType data; struct Node *leftChild; struct Node *rightChild; }*BiTreeNode; void PrintTree(BiTreeNode root,int n) //树的凹形输出 { int i; if(root==NULL)return; PrintTree(root->rightChild,n+1); for(i=0;i<n-1;i++)printf(" "); if(n>0) { printf("---"); printf("%c\n",root->data); } if(n==0) { printf("-"); printf("%c\n",root->data); } PrintTree(root->leftChild,n+1); } void Initiate(BiTreeNode *root) // 树的初始化 { *root=(BiTreeNode)malloc(sizeof(struct Node)); (*root)->leftChild=NULL; (*root)->rightChild=NULL; } void PreOrder(BiTreeNode bt) //前序遍历以bt为根结点指针的二叉树 { if (bt==NULL) return; printf("%c",bt->data); PreOrder(bt->leftChild); PreOrder(bt->rightChild); } void InOrder(BiTreeNode bt) //中序遍历以bt为根结点指针的二叉树 { if (bt==NULL) return; InOrder(bt->leftChild); printf("%c",bt->data); InOrder(bt->rightChild); } int Creattree(DataType *pre,DataType *in,int al,BiTreeNode &T) { //树的创建 int k; DataType *i; if(al<=0) { T=NULL; return 0; } for(i=in;i<in+al;i++) //查找根结点 if(*pre==*i) { k=i-in; //k为根结点在中序序列中相对头结点的距离 T=(BiTreeNode)malloc(sizeof(struct Node)); T->data=*i; break; }; Creattree(pre+1,in,k,T->leftChild); //建立左子树 Creattree(pre+k+1,in+k+1,al-k-1,T->rightChild);//建立右子树 } int main() { DataType a[50],b[50]; int al,bl; int k=0; BiTreeNode root; printf("请输入前序遍历:"); scanf("%s",&a); printf("请输入中序遍历:"); scanf("%s",&b); al=strlen(a); bl=strlen(b); Initiate(&root); if(al==bl)Creattree(a,b,al,root); else k=1; if(k){printf("序列不匹配");printf("\n");} else{ PrintTree(root,0);PreOrder(root);printf("\n"); InOrder(root);printf("\n");} }
实习三 树、二叉树及其应用
题目:唯一地确定一棵二叉树 实习时间:2012/10/30
一、需求分析
1.问题描述:如果给出了遍历二叉树的前序序列和中序序列,则可以构造出唯一的一棵二叉树。试编写实现上述功能的程序。
2.基本要求: 已知一棵二叉树的前序和中序序列,试设计完成下列任务的一个
算法:
(1)构造一棵二叉树;
(2)证明构造正确(即分别以前序和中序遍历该树,将得到的结
果与给出的序列进行比较)。
3.测试数据: 前序序列为ABDEGCFHIJ,中序序列为DBGEAHFIJC。
二、设计
二、 1. 设计思想
二、 (1)存储结构
二、 用两个一维数组A和B分别存放前序和中序序列。
(2)主要算法基本思想
①将前序和中序序列分别读入数组A和B。
②根据定义,前序序列中第一个元素一定是树根,在中序序列中该
元素之前的所有元素一定在左子树中,其余元素则在右子树中。所以,
首先从数组A中取出第一个元素A[0]作根结点,然后在数组B中找到A[0],
以它为界,在其前面的是左子树中序序列,在其后面的是右子树中序序列。
③若左子树不为空,沿前序序列向后移动,找到左子树根结点,转②。
④左子树构造完毕后,若右子树不为空,沿前序序列向后移动,找到
右子树根结点,转②。
⑤前序序列中各元素取完则二叉树构造完毕。
⑥对二叉树进行前序和中序遍历,并将结果分别与数组A和B进行
比较,若相同,则证明二叉树构造正确。
2. 设计表示
(1)函数调用关系图
main→StackPush→QueueAppend→QueueAd→StackPop→QueueGet
(2)函数接口规格说明
void PrintTree(BiTreeNode root,int n) //以root为根节点的树凹形输出
void Initiate(BiTreeNode *root) // 以root为根节点的树初始化
void PreOrder(BiTreeNode bt) //前序遍历以bt为根结点指针的二叉树
void InOrder(BiTreeNode bt) //中序遍历以bt为根结点指针的二叉树
int Creattree(DataType *pre,DataType *in,int al,BiTreeNode &T) //用前序序列和中序序列构造以T为根节点的树,其中pre,in分别为前序序列和中序序列的首地址,al为中序序列的长度。
3. 实现注释 (即各项功能的实现程度)
(1)必须正确输入前序序列和中序序列;
(2)若前序序列和中序序列的长度不一样,则输出“不匹配”;
(3)若前序序列和中序序列的长度一样,但不能构成一棵二叉树,则程序会出错,即程序缺乏健壮性。
4. 详细设计 (即主要算法的细化。略,见上课笔记)
【1】void Initiate(BiTreeNode *root) // 树的初始化
{
*root=(BiTreeNode)malloc(sizeof(struct Node));
(*root)->leftChild=NULL;
(*root)->rightChild=NULL;
}
【2】int Creattree(DataType *pre,DataType *in,int al,BiTreeNode &T)
{ //树的创建
int k;
DataType *i;
if(al<=0)
{
T=NULL;
return 0;
}
for(i=in;i<in+al;i++) //查找根结点
if(*pre==*i)
{
k=i-in; //k为根结点在中序序列中相对头结点的距离
T=(BiTreeNode)malloc(sizeof(struct Node));
T->data=*i;
break;
};
Creattree(pre+1,in,k,T->leftChild); //建立左子树
Creattree(pre+k+1,in+k+1,al-k-1,T->rightChild);//建立右子树
}
【3】void PrintTree(BiTreeNode root,int n) //树的凹形输出
{
int i;
if(root==NULL)return;
PrintTree(root->rightChild,n+1);
for(i=0;i<n-1;i++)printf(" ");
if(n>0)
{
printf("---");
printf("%c\n",root->data);
}
if(n==0)
{
printf("-");
printf("%c\n",root->data);
}
PrintTree(root->leftChild,n+1);
}
【4】void PreOrder(BiTreeNode bt) //前序遍历以bt为根结点指针的二叉树
{
if (bt==NULL) return;
printf("%c",bt->data);
PreOrder(bt->leftChild);
PreOrder(bt->rightChild);
}
【5】void InOrder(BiTreeNode bt) //中序遍历以bt为根结点指针的二叉树
{
if (bt==NULL) return;
InOrder(bt->leftChild);
printf("%c",bt->data);
InOrder(bt->rightChild);
}
三、调试分析
1.调试过程中遇到的主要问题是如何解决的;
调试过程中存在少许C语言的基础语法错误,经独立仔细观察和调试修改正确,最大的难题是创建树时,递归调用自身函数的中序序列数组下标表示。在自己独立多次修改下,终于完成。
2.对设计和编码的回顾讨论和分析;
总的来说,这个程序写的比较顺畅,毕竟老师已经把整个算法思路都已给出。但是,每次写程序都有的感觉是,对好多的基本语法还不是特别熟悉,写到某些刚学的数据结构知识时得在书中找代码和代码思想。所以,应该多练习才好。
3.时间和空间复杂度的分析;
【1】创建二叉树的函数: 时间O(n),空间O(n)
【2】二叉树的凹形输出函数:时间O(n),空间O(1)。
4.改进设想;
【1】在递归创建二叉树的算法中,若能判断前序序列和中序序列是否能构成二叉树,这样就能增强程序的健壮性。向同学请教过,也找了部分电子和书本知识,但均未发现解决办法。
【2】重新设计创建二叉树的非递归算法,这样能较好的解决程序的健壮性问题。但非递归算法过程较复杂。
5.经验和体会等。
多动手编程,才能熟练灵活的掌握C语言基础知识,才能更好的理解掌握数据结构的精髓。从而避免基础语法错误,让代码变得更简洁高效。如此才能准确高效的解决问题。在今后的编程过程中要更注重代码整体设计的提纲记录,用更多的注释。
四、用户手册(即使用说明)
仅需按照提示正确输入前序序列和中序序列。若出错,则表明前序序列和中序序列不能构成一颗二叉树。
五、运行结果
运行环境:C-free
【1】 前序序列为ABDEGCFHIJ,中序序列为DBGEAHFIJC。
【2】 前序序列为ABC,中序序列为BAC。
【3】 前序序列为ABCEFDGH,中序序列为ECFBGDHA。
【4】 若长度不一:前序序列为ABDEGCFHIJ,中序序列为DBGEAHFIJCZ。
【5】 若前序序列和中序序列的长度一样,但不能构成一棵二叉树。前序序列为ABC,中序序列为CAB。
【6】 若前序序列和中序序列的长度一样,但不能构成一棵二叉树。前序序列为ABC,中序序列为GHJ。
六、源程序清单
https://wenku.baidu.com/view/7b6254df640e52ea551810a6f524ccbff121cab5