构建非完全10叉树Word文档下载推荐.docx
《构建非完全10叉树Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《构建非完全10叉树Word文档下载推荐.docx(13页珍藏版)》请在冰豆网上搜索。
根据作业要求,本次设计采用标准方式,其节点类型为:
structGTreeNode
{
ElemTypedata;
//节点值域
GTreeNode*t[k];
//节点指针域,k为树的度
}
由于本次作业要求操作对象是10叉非完全树,所以k=10。
建立树的存储结构就是在内存中生成一棵树的链表,同二叉树一样,需要首先确定输入树的方法,然后再写出相应算法。
考虑到节点是从文本文件里读取的,为了区分节点及父子节点关系,在树的节点存储中以‘(’来表示某节点的子节点开始,以‘,’区分某节点的不同子节点,以‘)’表示某节点的子节点结束。
例如,图1的节点存储形式为:
另外,假定每个节点的非空子树都是靠前面、按序排列的子树,把所有空子树都留在后面。
其次要设计一个头文件tree.h,该头文件内实现10叉树的基本运算,例如,树的存储结构构建、树的遍历、求树的深度、树的输出等。
在树的存储结构构建算法中,需要设置两个堆栈,一个用来存储指向根节点的指针,以便子节点向双亲节点链接之用;
另一个用来存储待链接子节点的序号,以便能正确的链接到双亲节点的指针域。
树的存储结构构建算法如下:
voidCreateGTree(GTreeNode*&
GT,char*a)
//根据广义表字符串a所给出的k叉树建立对应的存储结构
constintMS=10;
//定义栈空间大小
GTreeNode*s[MS];
//s数组作为存储树中节点指针的栈使用
intd[MS];
//d数组存储孩子节点链接到双亲节点
//指针域的序号栈使用
inttop=-1;
//top为两个栈的栈顶指针
GT=NULL;
//树根指针置空
GTreeNode*p;
//定义p为指向树节点的指针
inti=0;
while(a[i])
{
switch(a[i])
{
case'
'
:
break;
//空格不处理
('
//子节点进栈,链接到所指节点的第一个指针域
top++;
s[top]=p;
d[top]=0;
break;
)'
//退栈
top--;
'
//链接到所指节点的下一个指针域
d[top]++;
default:
//字符处理
p=newGTreeNode;
p->
data=a[i];
for(inti=0;
i<
k;
i++)p->
t[i]=NULL;
if(GT==NULL)
GT=p;
else
s[top]->
t[d[top]]=p;
}
i++;
//准备处理下一个字符
}
根据要求,树的输出基本按广义表形式。
首先输出树根节点的值,然后若存在非空子树则接着输出表的左括号及输出第一棵子树,再依次输出每个逗号和每棵子树,最后输出表的右括号。
算法描述如下:
voidPrintGTree(GTreeNode*GT,FILE*fp)//将树存储到fp指向的文件
if(GT!
=NULL)//若树不为空,继续处理
fputc(GT->
data,fp);
//存储根节点
inti;
for(i=0;
i++)
if(GT->
t[i]!
=NULL)break;
//判断GT节点是否有子树
if(i<
k)//有子树向下递归
fputc('
fp);
//输出表的左括号
PrintGTree(GT->
t[0],fp);
//输出第一棵子树
for(i=1;
i++)//输出其余各子树
{
fputc('
PrintGTree(GT->
t[i],fp);
}
//输出表的右括号
}
由于节点要存储到文件中去,所以又涉及到文件的基本操作fopen、fread、fputc、ftell等函数。
各函数的参数如下:
1fopen函数
fopen(文件名,打开方式)
其中,文件名包含文件路径;
打开方式主要有只读“r”、只写“w”等。
②fputc函数
fopen(ch,fp)
其中,ch为输出字符;
fp是一个文件指针。
③ftell函数
ftell(fp)
ftell函数用于位置指针的当前位置。
四、测试
1.程序编译
在linux里,编译器有gcc与g++,分别用于对C程序和C++程序的编译,单个程序的编译方法如下:
#gccfilename[options]resultname
其中,gcc代表要使用的编译器;
option是编译器需要的编译选项,-o代表确定可执行文件名,-c代表只编译,不链接成为可执行文件;
filename表示源文件名,包括后缀;
resultname代表要输出的可执行文件名。
但是,对于工程的编译,此种方法太繁琐,多采用makefile文件进行编译,本次设计就采用此编译方法。
具体makefile内容见附录。
2.程序测试
要进行程序测试,首先要构建一棵树,然后对输出结果进行分析。
本次设计的测试树的结构如图1所示:
图1测试树的结构
测试方案1:
在主函数中,打开当前目录下的Ftree节点存储文件,将其内容读到临时缓存空间中,然后根据读取的节点内容重构树,并进行先根和后根遍历输出,并分析树的重构时间。
测试结果如图2所示:
图2测试结果1
从图中可以看出,内存重构图1测试树的时间约为3us。
测试方案2:
在主函数中,打开当前目录下的Ftree节点存储文件,将其内容读到临时缓存空间中,然后根据读取的节点内容重构树,并进行先根和后根遍历输出。
然后,对数进行遍历输出到节点文件Resulttree中,并将其内容与Ftree的节点文件比较是否一致。
最后,分析树的输出时间和空间复杂度。
测试结果如图3所示:
图3测试结果2
五、对本课程或本作业的建议和意见
通过本次作业,对树的数据结构有了进一步的熟悉和掌握,对linux下的工程编译方法及其工作原理有了一定的理解,对于文件的操作更加了解。
通过本次课程设计,我发现,有关一个课题的所有知识不仅仅是在课本上,多查阅一些资料能够更好的完成课题,这就需要一种能力,即自学能力。
本次课程设计还让我认识到自己的缺点。
本次选的课题是二叉树的遍历,因为本学期所学的就是二叉树等数据结构,所以认为比较适合。
刚开始认为会很简单,但到后来就出现一些难以解决的问题,就像老师请教,并查阅相关资料。
经过慢慢的调试,最终测试成功。
这次课程设计让我所学到的数据结构知识发挥的淋漓尽致,而且还拓展了我的知识面,使我更加熟练的掌握各种方法。
总之,这次课程设计增强了我的自学能力,拓展了我的知识面,让我对数据结构更加了解。
六、附录
1.树运算头文件程序tree.h:
#ifndeftree_H_
#definetree_H_
constintk=10;
//树的叉定义
structGTreeNode//标准方式定义树的结构类型
chardata;
//节点值域
GTreeNode*t[k];
//节点指针域
};
voidInitGTree(GTreeNode*&
GT);
//树初始化函数
GT,char*a);
//构建树函数
voidPreRoot(GTreeNode*GT);
//先根遍历树函数
voidPostRoot(GTreeNode*GT);
//后根遍历树函数
voidPrintGTree(GTreeNode*GT,FILE*fp);
//树节点输出
intGTreeDepth(GTreeNode*GT);
//求树深度函数
#endif
2.树运算程序tree.cpp:
#include<
iostream>
stdlib.h>
#include"
tree.h"
usingnamespacestd;
GT)//初始化树,即树根指针置空
//s数组作为存储树中节点指针的栈使用
//d数组存储孩子节点链接到双亲节点
//指针域的序号栈使用
while(a[i]!
='
#'
)
//子节点开始,p进s栈,0进d栈
//子节点结束,退栈
//将待读入子节点链接到s栈顶元素的下一个指针域
//使p节点成为树节点
voidPreRoot(GTreeNode*GT)//先根遍历树函数
=NULL)
cout<
<
GT->
da