数据结构实验五
南昌航空大学实验报告
二0 21 年 5 月 27 日
课程名称: 数据结构实验 实验名称: 线性表的链式存储结构
班级: 姓名: 同组人:
指导教师评定: 签名:
必做1:
一、 需求分析
题目:设计并验证如下算法:按后序序列建立二叉树的二叉链表结构,求其单分支结点数目,双分支结点数目,并交换该二叉树。
1、在本次实验中,首先,从键盘输入,按照输入字符构建二叉树,在进行二叉树交换与先序递归遍历并输出,输出单分支结点数目与双分支结点数目。
2. 演示程序以用户和计算机对话的方式进行,即在计算机终端上显示“提示信息”之后,按照提示信息输入。
3. 程序执行的命令包括:
(1) 输入二叉树信息;
(2) 后序递归构建二叉树
(3) 交换二叉树
(4) 交换前先序递归遍历
(5) 交换后先序递归遍历
4. 测试数据
请输入:
##b##d#ca
单分支节点数目:1,双分支节点数目:1
先序遍历:
a b c d
交换后先序遍历为:
a c d b
二、 概要设计
1. 抽象数据类型定义
为实现上述程序功能,需要一个抽象数据类型:图。
ADT Graph{
基本操作:
InitBiTree(BiTree *BT)
操作结果:二叉树初始化
CreateBiTree(BiTree *BT,char ch[],int &count1,int &count2,int &count3)
操作结果:后序递归建立二叉树
Exchange(BiTree *BT)
操作结果:交换二叉树
PreOrder(BiTree BT)
操作结果:先序遍历二叉树
2.程序模块
(1)主程序流程
void main{
初始化两个二叉树;
输入;
后序遍历创建二叉树;
输出单分支,双分支结点数目;
先序遍历二叉树;
交换二叉树;
先序遍历交换后的二叉树;
}
(2)二叉树初始化;
(3)后序遍历建二叉树;
(4)交换二叉树;
(5)先序遍历二叉树;
3.程序结构图
各模块之间的调用关系如图所示。
图1 模块之间调用关系图
三、 详细设计
1.数据类型及结构体
typedef int Status;
typedef char TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef BiTree SElemType;
typedef BiTree QElemType;
Status InitBiTree(BiTree *BT){/*构造空二叉树*/
Status CreateBiTree(BiTree *BT,char ch[],int &count1,int &count2,int &count3){/*后序递归建立二叉树*/
Status Exchange(BiTree *BT){/*交换二叉树*/
Status PreOrder(BiTree BT){/*先序递归遍历*/
- 主函数
int main(){
BiTree BT,BT1;
InitBiTree(&BT);
InitBiTree(&BT1);
int count1=0,count2=0,count3=0;
printf("请输入:\n");
TElemType ch1[100],ch2[100];
scanf("%s",&ch1);
int i=0;
int k=strlen(ch1);
for(int j=0,i=k-1;j<k;j++,i--)
{
ch2[j]=ch1[i];
}
CreateBiTree(&BT,ch2,count1,count2,count3);/*创建二叉树,返回根节点BT*/
printf("单分支结点数目:%d,双分支结点数目:%d\n",count2,count1);
printf("先序遍历为:\n");
PreOrder(BT);
printf("\n");
Exchange(&BT);
printf("交换后先序遍历为:\n");
PreOrder(BT);
return 0;
}
四、 调试分析
1. 第一次为了得到单分支与双分支结点数目采用了全局变量,改正后采用传地址来达到记录数据的目的:CreateBiTree(&BT,ch2,count1,count2,count3)。
2.后序遍历建树最开始没思路,后来将输入字符串颠倒借助先序遍历建数(先序建树时先建右孩子在建左孩子)来实现。
3.整体代码的时间复杂度为O(n),每种操作对于每个结点而言都只遍历了一次,
五、 用户手册
1. 本程序的运行环境为DOS操作系统,执行文件为:main.exe。
2. 进入演示程序后即显示文本方式的用户界面。
3. 程序运行后,按照提示信息输入后序遍历二叉树的结果
4. 建树后输出先序遍历的结果,单分支双分支结点数目,先序遍历交换左右孩子后树的结果。
六、 测试结果
测试结果
请输入:
##b##d#ca
单分支节点数目:1,双分支节点数目:1
先序遍历:
a b c d
交换后先序遍历为:
a c d b
七、 附录
源代码:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#define OK 1
#define ERROR 0
typedef int Status;
typedef char TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef BiTree SElemType;
typedef BiTree QElemType;
Status InitBiTree(BiTree *BT){/*构造空二叉树*/
*BT=NULL;
}
Status CreateBiTree(BiTree *BT,char ch[],int &count1,int &count2,int &count3){/*后序递归建立二叉树*/
if(ch[count3]=='#'){
*BT=NULL;
count3++;
}
else{
*BT=(BiTree)malloc(sizeof(BiTree));
int k=ch[count3];
count3++;
CreateBiTree(&((*BT)->rchild),ch,count1,count2,count3);
CreateBiTree(&((*BT)->lchild),ch,count1,count2,count3);
(*BT)->data = k;
if((*BT)->lchild!=NULL&&(*BT)->rchild!=NULL)
count1++;
if(((*BT)->lchild!=NULL&&(*BT)->rchild==NULL)||((*BT)->lchild==NULL&&(*BT)->rchild!=NULL))
count2++;
}
}
Status Exchange(BiTree *BT){/*交换二叉树*/
if(*BT){
BiTree p;
p = (*BT)->lchild;
(*BT)->lchild = (*BT)->rchild;
(*BT)->rchild = p;
Exchange(&(*BT)->lchild);
Exchange(&(*BT)->rchild);
}
}
Status PreOrder(BiTree BT){/*先序递归遍历*/
if(BT){
if(!(BT->data))
return ERROR;
printf("%c ",BT->data);
PreOrder(BT->lchild);
PreOrder(BT->rchild);
return OK;
}
}
int main(){
BiTree BT,BT1;
InitBiTree(&BT);
InitBiTree(&BT1);
int count1=0,count2=0,count3=0;
printf("请输入:\n");
TElemType ch1[100],ch2[100];
scanf("%s",&ch1);
int i=0;
int k=strlen(ch1);
for(int j=0,i=k-1;j<k;j++,i--)
{
ch2[j]=ch1[i];
}
CreateBiTree(&BT,ch2,count1,count2,count3);/*创建二叉树,返回根节点BT*/
printf("单分支结点数目:%d,双分支结点数目:%d\n",count2,count1);
printf("先序遍历为:\n");
PreOrder(BT);
printf("\n");
Exchange(&BT);
printf("交换后先序遍历为:\n");
PreOrder(BT);
return 0;
}
必做2:
一、 需求分析
题目:设计并验证如下算法:输入一棵二叉树的广义表形式,建立该二叉树的二叉链表结构,并求其总结点数目。
1、在本次实验中,首先,从键盘输入二叉树广义表形式,按照输入字符构建二叉树,输出二叉树的先序遍历以及总结点数目。
2. 演示程序以用户和计算机对话的方式进行,即在计算机终端上显示“提示信息”之后,按照提示信息输入。
3. 程序执行的命令包括:
(1) 输入二叉树信息;
(2) 构建二叉树;
(3) 输出总结点数目;
(4) 先序遍历二叉树
4. 测试数据
请输入:
C(E,(I,J),F(,G(K,H))#
总结点数目为:8
输出先序遍历:
C E I J F G K H
二、 概要设计
1. 抽象数据类型定义
为实现上述程序功能,需要一个抽象数据类型:图。
ADT Graph{
基本操作:
PreOrder(BiTree BT)
操作结果:输出先序递归遍历二叉树
CreatTree(BiTree & BT)
操作结果:建立二叉树
2.程序模块
(1)主程序流程
void main{
初始化二叉树;
创建二叉树;
先序遍历二叉树;
}
(2)二叉树初始化;
(3)建二叉树;
(4)先序遍历二叉树
3.程序结构图
各模块之间的调用关系如图所示。
图1 模块之间调用关系图
三、 详细设计
1.数据类型及结构体
typedef int Status;
typedef char TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
Status PreOrder(BiTree BT)/*先序递归遍历*/
Status CreatTree(BiTree & BT);/*建立二叉树*/
2.主函数
int main(){
BiTree BT;
printf("请输入:\n");
CreatTree(BT);
printf("输出先序序列:\n");
PreOrder(BT);
return 0;
}
四、 调试分析
1. 第一次建树用了for循环发现很混乱,便改用switch语句,使得代码更加清楚简洁
2.第一次入队列出队列的条件没搞清楚,什么时候该不该进队列,改进后:switch(a[i])
{
case '(':
rear++;
A[rear] = p;
flag = 1;
break;
case ')':
rear--;
break;
case ',':
flag = 0;
break;
default:
p = (BiTNode *)malloc(sizeof(BiTNode));
p->data = a[i];
p->lchild = p->rchild = NULL;
if(BT==NULL)
BT=p;
else
{
if ( flag == 1)
A[rear]->lchild = p;
else
A[rear]->rchild = p;
}
}
3.整体代码的时间复杂度为O(n),每种操作对于每个结点而言都只遍历了一次,
五、 用户手册
1. 本程序的运行环境为DOS操作系统,执行文件为:main.exe。
2. 进入演示程序后即显示文本方式的用户界面。
3. 程序运行后,按照提示信息输入二叉树的顺序表形式
4. 建树后输出先序遍历的结果,输出总结点数目。
六、 测试结果
测试结果
请输入:
C(E,(I,J),F(,G(K,H))#
总结点数目为:8
输出先序遍历:
C E I J F G K H
七、 附录
源代码:
#include<stdio.h>
#include<stdlib.h>
#define STACK_SIZE 100
typedef int Status;
typedef char TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
Status PreOrder(BiTree BT){/*先序递归遍历*/
if(BT){
printf("%c ",BT->data);
PreOrder(BT->lchild);
PreOrder(BT->rchild);
}
}
Status CreatTree(BiTree & BT){
TElemType a[STACK_SIZE];
scanf("%s",a);
BiTree p;
BiTree A[100];
int rear = -1;
BT=NULL;
int flag=0;//1指左,0指右
int i=0,j=0;
while(a[i]!='#')
{
if(a[i]!=','&&a[i]!='('&&a[i]!=')')
j++;
switch(a[i])
{
case '(':
rear++;
A[rear] = p;
flag = 1;
break;
case ')':
rear--;
break;
case ',':
flag = 0;
break;
default:
p = (BiTNode *)malloc(sizeof(BiTNode));
p->data = a[i];
p->lchild = p->rchild = NULL;
if(BT==NULL)
BT=p;
else
{
if ( flag == 1)
A[rear]->lchild = p;
else
A[rear]->rchild = p;
}
}
i++;
}
printf("总结点数目为:%d\n",j);
}
int main(){
BiTree BT;
printf("请输入:\n");
CreatTree(BT);
printf("输出先序序列:\n");
PreOrder(BT);
return 0;
}