课题数据结构二叉树家谱管理系统.docx
《课题数据结构二叉树家谱管理系统.docx》由会员分享,可在线阅读,更多相关《课题数据结构二叉树家谱管理系统.docx(19页珍藏版)》请在冰豆网上搜索。
![课题数据结构二叉树家谱管理系统.docx](https://file1.bdocx.com/fileroot1/2023-1/2/2565c1b3-93e6-4d55-81ec-1bf84ace2b9f/2565c1b3-93e6-4d55-81ec-1bf84ace2b9f1.gif)
课题数据结构二叉树家谱管理系统
数学与计算机学院
课程设计说明书
课程名称:
数据结构与算法课程设计
课程代码:
题目:
二叉树生成家谱
年级/专业/班:
学生姓名:
学 号:
开始时间:
2015年12月09日
完成时间:
2015年12月29日
课程设计成绩:
学习态度及平时成绩(30)
技术水平与实际能力(20)
创新(5)
说明书(计算书、图纸、分析报告)撰写质量(45)
总分(100)
指导教师签名:
年月日
目录(小三黑体,居中)
摘要
随着计算机科学技术、计算机产业的迅速发展,计算机的应用普及也在以惊人的速度发展,计算机应用已经深入到人类社会的各个领域。
计算机的应用早已不限于科学计算,而更多地应用在信息处理方面。
计算机可以存储的数据对象不再是纯粹的数值,而扩展到了字符、声音、图像、表格等各种各样的信息。
对于信息的处理也不再是单纯的计算,而是一些如信息存储、信息检索等非数值的计算。
那么,现实世界的各种数据信息怎样才能够存储到计算机的内存之中,对存入计算机的数据信息怎样进行科学处理,这涉及计算机科学的信息表示和算法设计问题。
为解决现实世界中某个复杂问题,总是希望设计一个高效适用的程序。
这就需要解决怎样合理地组织数据、建立合适的数据结构,怎样设计适用的算法,以提高程序执行的时间效率和空间效率。
“数据结构”就是在此背景下逐步形成、发展起来的。
在各种高级语言程序设计的基本训练中,解决某一实际问题的步骤一般是:
分析实际问题;确定数学模型;编写程序;反复调试程序直至得到正确结果。
所谓数学模型一般指具体的数学公式、方程式等,如牛顿迭代法解方程,各种级数的计算等。
这属于数值计算的一类问题。
而现实生活中,更多的是非数值计算问题,如手机中的通讯录,人们对它的操作主要是查找、增加、删除或者修改电话记录。
再如,人们经常在互联网上查阅各种新闻,或查阅电子地图,人们可以在某城区地图上查找自己所需的街道或店铺,其操作主要是搜索和查询。
下面再来分析几个典型实例,它们的主要特点是:
不同实例的数据元素之间存在不同的关系;对数据信息的处理主要有插入、删除、排序、检索等。
关键词:
网络化;计算机;对策;二叉树
引言
课程设计的目的:
通过本项课程设计,培养学生独立思考、综合运用所学有关相应知识的能力,使学生巩固《数据结构》课程学习的内容,掌握工程软件设计的基本方法,强化上机动手编程能力,闯过理论与实践相结合的难关;为了培养学生综合运用所学知识、独立分析和解决实际问题的能力,培养创意识和创新能力,使学生获得科学研究的基础训练。
为后续各门计算机课程的学习和毕业设计打下坚实基础。
同时,可以利用这次机会来检验自己的c/c++/数据结构水平,提高自己的写作水平,锻炼自己的动手能力。
而此次课程设计的意义在于:
增强自己的动手能力,熟悉和掌握二叉树各种遍历的算法,以及递归在遍历二叉树中的应用,增强自己的调试程序和测试程序的能力。
1需求分析
1.1任务与分析
1.建立输入文件以存放最刜家谱中各成员的信息。
2.成员的信息中均应包含以下内容:
姓名、出生日期、婚否、地址、健在否、死亡日期(若其已死亡)也可附加其它信息、但不是必需的。
3.能对修改后的家谱存盘以备以后使用。
4.能从文件中读出已有的家谱,形成树状关系。
5.家谱建立好之后,以图形方式显示出来。
6.显示第n代所有人的信息。
7.按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息)。
8.按照出生日期查询成员名单。
9.输入两人姓名,确定其关系。
10.给某人添加孩子。
11.删除某人(若其还有后代,则一并删除)。
12.修改某人信息。
13.用括号法输出家谱成员信息
1.2测试数据
1徐朝嬴m1938-1-201彭代芳0此人相当的热心0234510000
2徐廷文m1964-8-32李太群1此人相当有责任心06710000
3徐素华w1966-4-62李奉光1此人很好010000
4徐军华m1969-7-82曲舞1此人很有正义感010000
5徐廷国m1972-9-22木玛1此人心的很善良010000
6徐光勇m1989-1-273Nomarry2此人很牛逼010000
7徐光超m1992-9-53Nomarry2此人亦很牛逼010000
2概要设计
2.1ADT描述
1.ADTPerson{
数据对象:
D={Pj|Pj={姓名、出生日期、婚否、地址、健在否(如过世,还应有其死亡日期)},j=0,1,2,……n,其中n>=0}
数据关系:
R={}基本操作:
无。
}ADTPerson
2.ADTFamilytreeFile{
数据对象:
D={Aj|Aj属于Person,j=1,2,3,……,n其中n>=1}
数据关系:
D中每个对象用换行符隔开,R={ |Aj属于D,j=1,2,3,……,n其中n>=1,String属于字符串类型,为Aj父亲姓名(若String=-1,Aj无父亲,若String=Aj的姓名,表示家谱文件结束)}
基本操作:
1.打开家谱类型文件,并建立兄弟、孩子二叉树。
2.从内存中读取兄弟、孩子二叉树,并建立家谱类型文件。
}
ADTFamilytreeFlie
3.ADTFamilytree{
数据对象:
D={Aj|Aj属于Person,j=1,2,3,……,n其中n>=0}
数据关系:
V={ |Aj-1,Aj属于D,j=2,3,……,n其中n>=2,且Aj-1与Aj为祖先与后代关系(parent)、后代与祖先关系(child)、兄弟之间关系(sibling)}
基本操作:
1.显示某人信息。
2.修改某人信息。
3.增加某人孩子。
4.删除某人。
5.通过某人查找其双亲、孩子、兄弟。
}ADTFamilytree
2.2程序模块结构
2.2.1 结构体定义
structPeople//定义结构体People
{
intnum;
charname[20];
charsex;
charborndate[15];
intgeneration;
charmatename[20];
intparent;
charinfor[100];
LinkListchild;
};
structNode//定义结构体Node
{
inta;
structNode*next;
};
structLinkList//定义链表
{
NodePointLa;
};
structTree//定义树
{
PeoplePointTr;
intLength;
intTREE_INIT_SIZE;
};
2.3 各功能模块
voidInitTree(Tree&TR);//在树已定义的情况下,初始化树TR
LinkListInitLinkList(void);//在什么都没有的情况下,初始化一个带头结点的链表并返回链表L
voidAddLinkList(LinkListp);//对带头结点的链表pl,添加一个节点为m的节点在表头
voidCreatFamilyTree(Tree&TR);//在什么都没有的情况下,创建一个家谱TR。
并返回TR
voidPrintPeople(PeoplePointp);//已知某节点的指针p,输出peoplep的相关信息
voidPrintLinkList(LinkListp);//已知链表p,输出链表p中的信息
intCompareNum(PeoplePointp,intnum);//已知某节点的指针p和一个编号num,比较p的num和num,如果相等返回1,否则返回0
intCompareName(PeoplePointp,chara[]);//已知某节点的指针p和一个姓名a,比较p的name,如果两者相等返回1,否则返回0
voidTraveTreePrint(TreeTR);//已知树TR,按规定输出节点信息,根据编号、姓名、孩子输出
voidAddPeople(Tree&TR);//已知树TR,当有人出生时,添加一个节点
voidMarryChange(TreeTR,charname[20]);//已知树TR和一个人的姓名name,因为结婚需要改变节点中的配偶一栏
voidOpen(Tree&TR);//打开保存家谱信息的文件
voidSave(TreeTR);//保存家谱信息到指定文件
voidPrintTree(TreeTR);//输出家谱中所有成员的信息
3详细设计
3.1结构体定义
structPeople//定义结构体People
{
intnum;
charname[20];
charsex;
charborndate[15];
intgeneration;
charmatename[20];
intparent;
charinfor[100];
LinkListchild;
};
structNode//定义结构体Node
{
inta;
structNode*next;
};
structLinkList//定义链表
{
NodePointLa;
};
structTree//定义树
{
PeoplePointTr;
intLength;
intTREE_INIT_SIZE;
};
3.2初始化
voidInitTree(Tree&TR)//在树已定义的情况下,初始化树TR
{
Peoplepeop[INIT_SIZE];
TR.Tr=peop;
TR.Length=0;
TR.TREE_INIT_SIZE=INIT_SIZE;
}
LinkListInitLinkList(void)//在什么都没有的情况下,初始化一个带头结点的链表并返回链表L
{
LinkListL;
NodePointHead;
Head=(NodePoint)malloc(sizeof(Node));
Head->a=0;
Head->next=NULL;
L.La=Head;
return(L);
}
voidCreatFamilyTree(Tree&TR)//在什么都没有的情况下,创建一个家谱TR。
并返回TR
{
LinkListlp;
TR.Tr=peop;
TR.Length=0;
TR.TREE_INIT_SIZE=INIT_SIZE;
inti=0,n,j,k,c;
cout<<"请输入家谱中一共有多少人\n";
cin>>n;
TR.Length=n;
for(i=0;i{
(peop[i].num)=i+1;
cout<<"请输入该人的姓名:
\n";
cin>>peop[i].name;
cout<<"请输入该人的性别:
\n";
cin>>peop[i].sex;
cout<<"请输入该人的出生日期:
\n";
cin>>peop[i].borndate;
cout<<"请输入该人是第几代人:
\n";
cin>>peop[i].generation;
cout<<"请输入其配偶的姓名,如无则输入Nomarry\n";
cin>>peop[i].matename;
cout<<"请输入其双亲的编号:
\n";
cin>>peop[i].parent;
cout<<"请输入该人相关的备注信息:
\n";
cin>>peop[i].infor;
LinkListL;
NodePointHead;
Head=(NodePoint)malloc(sizeof(Node));
Head->a=0;
Head->next=NULL;
L.La=Head;
peop[i].child=L;
lp=peop[i].child;
cout<<"请输入其孩子的个数:
\n";
cin>>k;
for(j=0;j{
cout<<"请输入孩子的编号:
\n";
cin>>c;
AddLinkList(lp,c);
}
}
}
3.3插入操作
voidAddPeople(Tree&TR)
//已知树TR,当有人出生时,添加一个节点
{
intk,c,j,m;
LinkListL,L1,L2;
NodePointHead;
PeoplePointp1,p2,p3;
if(TR.Length>=TR.TREE_INIT_SIZE)
{TR.Tr=(PeoplePoint)realloc(TR.Tr,(TR.TREE_INIT_SIZE+TREEINCREMENT)*LEN);
if(!
TR.Tr)exit(OVERFLOW);}
p1=peop;
p2=p1+(TR.Length);
p2->num=TR.Length+1;
cout<<"请输入该人的姓名:
\n";
gets(p2->name);
cout<<"请输入该人的性别:
\n";
cin>>p2->sex;
cout<<"请输入该人的出生日期:
\n";
cin>>p2->borndate;
cout<<"请输入该人是第几代人:
\n";
cin>>p2->generation;
cout<<"请输入其配偶的姓名,如无则输入Nomarry\n";
gets(p2->matename);
cout<<"请输入其双亲的编号:
\n";
cin>>p2->parent;
cout<<"请输入该人相关的备注信息:
\n";
gets(p2->infor);
gets(p2->infor);
Head=(NodePoint)malloc(sizeof(Node));
Head->a=0;
Head->next=NULL;
L.La=Head;
p2->child=L;
L1=p2->child;
cout<<"请输入其孩子的个数:
\n";
cin>>k;
for(j=0;j{
cout<<"请输入孩子的编号:
\n";
cin>>c;
AddLinkList(L1,c);
}
m=p2->parent-1;
p3=p1+m;
L2=p3->child;
AddLinkList(L2,p2->num);
TR.Length=TR.Length+1;
cout<<"添加成功\n";
}
3.4查询操作
voidTraveTreePrint(TreeTR)
//已知树TR,按规定输出节点信息,根据编号、姓名、孩子输出
{
PeoplePointp;
inti,j,k,Flag;
charname1[15],name2[15];
p=TR.Tr;
printf("根据编号查找请输入1,根据姓名查找请输入2,根据孩子查找请输入3:
\n");
scanf("%d",&i);
if(i==1)
{
printf("请输入该节点的编号:
\n");
scanf("%d",&k);
for(j=0;j
{
Flag=CompareNum((p+j),k);
if(Flag)
PrintPeople((p+j));
}
}
if(i==2)
{
printf("请输入该人的姓名:
\n");
gets(name1);
gets(name1);
for(j=0;j
{
Flag=CompareName((p+j),name1);
if(Flag)
PrintPeople((p+j));
}
}
if(i==3)
{
printf("请输入其孩子的姓名:
\n");
gets(name2);
gets(name2);
for(j=0;j
{
if(strcmp(peop[j].name,name2)==0)
PrintPeople((p+(peop[j].parent-1)));
}
}
}
4调试分析
在调试时,遇到的几个问题如下:
1)建立树时,由于新申请结点的孩子指针、兄弟指针、及双亲指针均未赋空值。
而在以后的函数中对树迚行递归操作时均以这些指针值中的一个或几个是否为空作为递归结束条件。
从而导致调用这些函数时出现系统保护异常(使用了不安全的指针)。
2)刚开始初除结点时,只考虑到初除其本身结点的情况,而初除其孩子结点的情况未考虑到,故在初除某些结点时使树出现了“断链”现象。
故在程序代码中对初除某一结点迚行操作时,首先要刞断此结点是否有孩子及兄弟,然后迚行相应操作。
本程序的编译环境为MicrosoftVisualC++6.0,在Windows8下编译通过。
5用户使用说明
用户在打开软件后即可使用本软件,傻瓜式操作,界面简单易懂,用户在使用本软件过程中若出现隐私泄露或受到任何损失,与作者无关。
6测试结果
部分测试结果:
图1:
初始状态
图2:
创建家谱
图3:
添加成员
图4:
添加一个孩子
图5:
修改成员的婚姻状态
图6:
输出所有家谱中的成员
图7:
从文件读取并输出
结论
通过一个学期以来的数据结构的学习,加深了我对C++程序设计语言的认识,使得我对程序的开发过程有了更深的认识,这一次的数据结构课程设计是对我学习的检验,在这次实验中,我利用了各种开发工具以及建模工具,还在图书馆查过不少资料,最终解决了一个个难题。
通过这次的实验,我得出了一个结论,任何一门语言的学习都是空洞的,只有在自己实验验证后才能让自己学到真正的知识。
以上便是我对《数据结构课程设计》这门课的总结,我会抓紧时间将没有吃透的知识点补齐。
今后我仍然会继续学习,克服学习中遇到的难关,在打牢基础的前提下向更深入的层面迈进!
附录
源码文件如下:
参考文献
[1]杨宝刚.开展企业管理信息化工作的步骤[J].企业管理.2002.(11).12~15
[2]Islamabad.Softwaretoolsforforgerydetection[J].Businessline.2001.(5).29~32
[3]《数据结构(C语言版)》——清华大学出版社——严蔚敏、吴伟民编著
[4]《C至VisualC++程序设计语言》——科学出版社——蔡常丰、林小苹编著[5]《MicrosoftVisualC++6.0高手速成》——兵器工业出版社——步行者工作室编著
[6]《C++程序设计》——清华大学出版社——谭浩强编著