安徽省巢湖学院计算机与信息工程学院课程设计报告课程名称《数据结构》课题名称完全二叉树操作演示专业班级计算机科学与技术专升本1班学号********、********、********姓名李鹏王帅李泳波联系方式指导教师严小燕完成日期: 2014年12月27 日目录1 数据结构课程设计任务书 (1)1.1题目 (1)1.2目的 (1)1.3要求 (1)2 总体设计 (1)2.1功能模块设计 (1)2.2所有功能模块流程图 (1)3 详细设计 (2)3.1程序中所采用的数据结构及存储结构的说明 (2)3.2算法设计思想 (3)3.3主要的功能函数 (3)4 调试与测试 (3)4.1调试方法与步骤 (4)4.2测试结果分析与讨论 (4)4.3测试过程中遇到的主要问题及采取的解决措施 (5)5 时间复杂度分析 (6)6 程序清单 (6)7 总结 (12)参考文献 (13)1 数据结构课程设计任务书1.1题目完全二叉树操作演示1.2目的(1)掌握二叉树的概念和性质。
(2)掌握完全二叉树存储结构。
(3)掌握完全二叉树的基本操作。
1.3 要求(1)创建完全二叉树(用字母表示节点)(用顺序方式存储)。
(2)求二叉树的深度和叶子结点数。
(3)实现二叉树的前序、中序、后序和层次遍历。
(4)查找给定结点的双亲、祖先和左右孩子节点。
2 总体设计2.1 功能模块设计根据课程设计题目的功能要求,各个功能模块的组成框图如图1:图 1 功能组成框图2.2 所有功能模块流程图设计好功能模块后,各个模块的关系如下图2:图 2 流程图3 详细设计3.1程序中所采用的数据结构及存储结构的说明(1)整个程序采用结构体与顺序表相结合的编程方法一共完成了7个功能。
在你输入错误时有报错消息,这样使整个程序运行起来更加完整。
程序中有若干个子函数被主函数调用执行。
结构体定义如下:#define MAX 100 //定义100个节点typedef struct{char dat; //节点信息}node;typedef struct Tree //节点组成树{int length;node *r; //指向根节点}Tree;3.2 算法设计思想完全二叉树具有以下几个性质,由此可设计出相应算法。
性质1 完全二叉树约定编号从根节点起,自上而下,自左自由。
由此设计出顺序存储结构且进行层次遍历时,只需输出顺序表中存储的元素即可。
性质2 具有n 个结点的完全二叉树的深度为 。
由此设计出深度计算函数。
性质3 完全二叉树第i 层上的结点数目最多为2i-1(i≥1)。
由此设计出每层节点个数函数,在显示完全二叉树时可以找到其最左边的孩子节点。
性质4 在完全二叉树中,若某个结点没有左孩子,则它一定没有右孩子,即该结点必是叶结点且叶子节点个数为(n+1)/2。
由此设计出叶子节点函数。
性质5 在完全二叉树中,若根节点为i ,则左孩子节点为2i,右孩子节点为2i+1。
由此采用递归思想,可以对完全二叉树进行前序、中序、后序遍历和给定节点找其双亲及孩子。
3.3主要的功能函数CreatTree(Tree &t) //创建完全二叉树 LevCount(int n) //统计每层最多节点个数 OutputTree(Tree &t) //显示完全二叉树 Depth(Tree &t) //求树深 Leaf(Tree &t) //叶子节点PreOrder(Tree &t,int r) //先序遍历 InOrder(Tree &t,int r) //中序遍历 PostOrder(Tree &t,int r) //后序遍历 LeOrder(Tree &t) //层次遍历Search(Tree &t,char q) //查找给定结点的双亲、左右孩子 完善以上函数,就可以设计出完全二叉树的操作了。
4 调试与测试1log 2 n4.1调试方法与步骤第一步:建立完全二叉树,输入节点个数和节点。
第二步:选择要操作的对象,比如显示完全二叉树,按下电脑键盘1。
查找双亲及孩子功能函数在操作时需要输入信息,按照相应提示输入相应信息即可运行,输入不对时,程序会有报错提示信息。
4.2测试结果分析与讨论假定完全二叉树节点数为9个,节点信息为a、b、c、d、e、f、g、h、i。
操作结果如下图所示:(1)操作界面图3 操作界面(2)创建完全二叉树图4 创建完全二叉树(3)显示完全二叉树图5 显示完全二叉树(4)完全二叉树深度图6 完全二叉树深度(5)完全二叉树层次遍历图7 完全二叉树层次遍历(6)完全二叉树前序、中序、后序图8 前序、中序、后序遍历(7)查找给定节点双亲及孩子图9 查找给定节点双亲及孩子(8)完全二叉树叶子节点数图10 节点数4.3 测试过程中遇到的主要问题及采取的解决措施在建立完全二叉树时操作不当会出现程序错误。
如下图:图11 错误界面导致以上错误的原因是,再输入第一个字母元素时,不能空格,程序中的getchar()函数只能接收上一个空格字符,即输入节点产生的空格,解决方法是重新编译运行程序按要求输入即可。
5 时间复杂度分析这里主要分析查找节点时的时间复杂度,当给定节点时,需要在顺序表中进行一一比对查找,即顺序查找,那么最坏的情况就是找最后一个叶子节点了,这就跟表长有关系了,所以时间复杂度为n=length。
6 程序清单#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX 100 //定义100个节点typedef struct{char dat; //节点信息}node;typedef struct Tree //节点组成树{int length;node *r; //指向根节点}Tree;int CreatTree(Tree &t){int i;t.r =(node *)malloc(MAX*sizeof(node));//r[MAX]printf("请输入完全二叉树节点个数,输入后继续:");scanf("%d",&t.length);printf("请输入完全二叉树节点,以字母空格隔开且不要以空格开头:");for(i=0;i<t.length;i++){getchar();scanf("%c",&t.r[i+1].dat);}return 1;}int LevCount(int n) //统计每层最多节点个数{int p=1;for(int i=1;i<=n;i++)p=p*2;return p;}void OutputTree(Tree &t) //显示完全二叉树{int k=0,n=t.length;//求树的层数 Kwhile(n){k++;n=n/2;} //层数控制行每层节点个数控制列for(inti=1;i<=k;i++)//j<LevCount(i)-LevCount(i-1)&&LevCount(i-1)+j<=t.length { //判断条件是每层节点个数且以最左边孩子节点开始不小于表长for(intj=0;j<LevCount(i)-LevCount(i-1)&&LevCount(i-1)+j<=t.length;j++)printf("%2c",t.r[LevCount(i-1)+j].dat); //输出每层各个节点printf("\n");}}void Depth(Tree &t) //求树深{int k=0,n=t.length;while(n){k++;n=n/2;}printf("二叉树深度:%2d\n",k);}void Leaf(Tree &t) //叶子节点{int lef;lef=(t.length+1)/2;printf("叶子节点个数:%2d\n",lef);}void PreOrder(Tree &t,int r) //先序遍历 DLR{if(t.length<r) return;printf("%c",t.r[r].dat);PreOrder(t,2*r);PreOrder(t,2*r+1);}void InOrder(Tree &t,int r) //中序遍历 LDR{if (t.length<r) return;InOrder(t,2*r);printf("%c",t.r[r].dat);InOrder(t,2*r+1);}void PostOrder(Tree &t,int r) //后序遍历 LRD{if(t.length<r)return;PostOrder(t,2*r);PostOrder(t,2*r+1);printf("%c",t.r[r].dat);}void LeOrder(Tree &t) //层次遍历{int i;for(i=0;i<t.length;i++)printf("%c",t.r[i+1].dat);printf("\n");}void Search(Tree &t,char q) //查找给定结点的双亲、左右孩子{bool flag=false;int i;printf("请输入查找节点:");getchar();scanf("%c",&q);for(i=1;i<=t.length;i++){if(t.r[i].dat==q) //找到给定节点下标且默认节点0号单元无节点{if(i/2==0) //根节点无双亲printf("此节点无双亲");elseprintf("此节点的双亲: %c",t.r[i/2].dat);if(2*i>t.length) //左孩子下标值大于表长,肯定无孩子 printf("此节点无左右孩子");else{printf(" 此节点左孩子: %c",t.r[2*i].dat);if(2*i+1>t.length) //右孩子下标值大于表长,只是无右孩子printf(" 此节点无右孩子");else{printf(" 此节点右孩子: %c",t.r[2*i+1].dat);}}flag=true;break;}}if(flag==false)printf("二叉树中没有此节点\n");printf("\n");}void menu(){printf("*****************************菜单************************************\n"); printf(" \n"); printf(" \n"); printf(" 1. 创建完全二叉树 2. 显示完全二叉树\n"); printf(" \n"); printf(" 3. 完全二叉树深度 4. 完全二叉树层次遍历\n"); printf(" \n"); printf(" 5. 完全二叉树的前序、中序、后序 6. 查找给定结点双亲、左右孩子\n");printf(" \n"); printf(" 7.完全二叉树叶子结点数8. 退出系统\n"); printf(" \n"); printf(" \n"); printf(" 请先对菜单1 操作后,再进行其它操作\n"); }void main(){Tree t;int chose;char p;menu();while(1){printf("请选择操作:");scanf("%d",&chose);switch (chose){case 1: CreatTree(t);printf("\n"); break; //建树case 2: OutputTree(t);printf("\n"); break; //显示树case 3: Depth(t);printf("\n"); break; //深度case 4: printf("层次遍历:");LeOrder(t); printf("\n"); break;case 5: printf("先序遍历:");PreOrder(t,1); printf("\n");printf("中序遍历:"); InOrder(t,1);printf("\n");printf("后序遍历:"); PostOrder(t,1);printf("\n"); printf("\n"); break;case6: Search(t,p);printf("\n"); break; //查找case 7: Leaf(t);printf("\n"); break; //叶子case 8: printf(" 谢谢你的使用\n");exit(0);break;default: printf("输入错误,请重新选择\n"); break;}}}7 总结通过这次课程设计,让我们知道了很多,特别是平时做作业时,在很多问题上一知半解就过去了的问题,在操作中都不太懂。