17统计问题.docx
《17统计问题.docx》由会员分享,可在线阅读,更多相关《17统计问题.docx(21页珍藏版)》请在冰豆网上搜索。
17统计问题
湖南人文科技学院计算机科学技系
课程设计说明书
课程名称:
数据结构
课程代码:
408024
题目:
统计问题
年级/专业/班:
08级计算机科学与技术二班
学生姓名:
罗维马红操任萍
苏明张小龙
学号:
0840822508408226
0840822808408229
指导教师:
袁辉勇
开题时间:
2009年12月日
完成时间:
2010年1月日
目录
摘要2
一、引言4
二、设计目的与任务0
1、课程设计目的0
2、课程设计的任务0
三、设计方案0
1、需求分析0
2、概要设计1
3、详细设计3
4、程序清单5
四、调试分析与体会5
五、运行结果5
六、结论5
七、致谢5
八、参考文献5
摘要
本课程设计选取了统计问题进行制作,利用二叉排序树实现从文件中读出整数并统计其出现的次数,然后按整数由小到大的次序及其出现的次数写入文件;利用文件的输入输出函数实现对文件数据的读写。
其具体是利用二叉排序树对整数排序,其中在建立二叉树的过程中运用了平衡二叉树的相关函数对二叉树进行平衡处理,并在这个过程中统计不同整数出现的次数。
在开始阶段首先根据题目的要求,要从文件中读取整数,为了读取到文件中所有有效的数据,就需要利用循环控制语句逐个读取文件中的数据。
考虑到要对不同的整数进行排序,并且统计出不同数据出现的次数,所以在建立二叉树的结构类型时,就必须添加一个成员变量,用来在建立二叉排序树的过程中统计不同整出现的次数。
关键词:
二叉排序树;平衡二叉树;文件;整数;
Abstract
Thiscourseisdesignedtoproduceselectedstatisticalissues,usingthebinarysorttreereadfromafile,aninteger,andthenumberofstatisticsinwhichwhichtheyappear,andthenclicktheorderfromsmalltolargeintegersandthenumberofoccurrencesincludedinthedocument;theuseofdocumentsinputandoutputfunctionstorealizereadingandwritingfiledata.Thespecificistousebinarysorttreeforintegersorting,inwhichtheprocessoftheestablishmentofabinarytreeusingabalancedbinarytreebalancedbinarycorrelationfunctionoftheprocessingandstatisticsintheprocessthenumberofoccurrencesofdifferentintegers.
First,accordingtothesubjectatthebeginningoftherequest,toreadintegersfromafile,inordertoreadthefileofallvaliddata,weneedtousetheloopcontrolstatementsonebyonetoreadthefiledata.Takingintoaccountthedifferentpairsofintegerstobesorted,andthestatisticsofthenumberofoccurrencesofdifferentdata,sointheestablishmentofthestructureofbinarytype,youmustaddamembervariablecounttimesusedintheestablishmentoftwobinarysorttreeintheprocessStatisticsofdifferentwholenumberofoccurrences.
Keywords:
BinarySortTree;BalancedBinaryTree;Documents;Integer;
《数据结构》课程设计
----统计问题
一、引言
“数据结构”是计算机类各专业的核心课程,也是其他诸多类专业的重要选修课。
开设这门课可以为理解、应用和开发程序提供技术和方法支持,为后续课程的学习提供重要思想和方法基础。
同时对于我们逻辑思维培养和程序设计思想体系的建立有着重要的影响。
学好“数据结构”仅仅通过课堂教学或自学获取理论知识是远远不够的,还必须加强实践,亲自上机输入、编辑、检查、修改、调试和运行各种典型算法。
为了加强实践,我们就统计问题做了一个课程设计。
问题要求从文件中读取整数,利用二叉树实现对文件中整数进行排序,并统计不同整数出现的次数。
为了解决这个问题,我们用运到了文件的输入输出函数来读写文件,利用建立二叉树排序树对文件中的数据进行排序,其中在建立二叉树的同时借助了平衡二叉树的相关,然后利用中序遍历输出即可得到有序的序列,而对文件中不同整数出现的次数的统计,则在树的结构体中添加一个计次成员变量。
整个程序是用C语言编写的,在VisualC++6.0中编译完成的。
在拿到问题之后,因为对二叉排序树的算法,掌握的不是很好,开始编写函数时出现过不少问题,就如在编写插入函数时,因为在建树的过程中没有利用平衡二叉树的原理对二叉树进行平衡处理,所以在编写这个函数的过程,出现了大量的问题,后来有同学建意利用平衡二叉树来解决,加上借助书上已有的算法,得已顺利解决。
整个程序最重要的函数完成之后,因为对以前C语言中的文件输入输出函数掌握不够,接着又参考了C语言的输入输出函数,完成了对文件数据的读写操作。
程序完成之后,接着是编写文档,其中编写文档的过程中,值得一提的是,流程图的绘制和运行结果图的颜色控制;其次是各种文字格式的统一性问题。
分配的任务大家也都能顺利的完成,最后修改阶段,主要完成了对目录的更新,对格式的统一,和整体编排的美观。
因为我们做课程设计的水平相对有限,加上经验不足,在完成程序的编写过程中,也出现过不少问题,经过组员们不断努力,不断修改,最终得以解决。
由于时间仓促,设计的文档做的可能不是很完美,有错误和不足之处还请老师批评和指正。
二、设计目的与任务
1、课程设计目的
通过课程设计,使我们巩固所学知识、培养我们动手能力。
我们用数据结构设计一个完整的应用程序,综合应用所学知识完成软件的分析、设计、调试和总结,提高我们对数据结构综合应用能力和解决问题的能力。
灵活应用所学数据结构知识,独立完成问题分析。
初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等方法。
训练用系统的观点和软件开发一般规范进行软件开发。
提高综合运用所学的理论知识和方法独立分析和解决问题的能力。
同时增加了同学之间的团队合作精神!
更加也体会到以后在工作中团队合作的重要性和必要性!
2、课程设计的任务
问题描述:
使用二叉排序树实现:
从文件中读出整数,统计不同整数出现的次数,输出不同整数及其出现的次数,按整数由小到大的次序将整数及其出现的次数写入文件。
三、设计方案
1、需求分析
1)由问题要求,用二叉排序树实现,从文件中读取整数,统计不同整数出现的次数,并顺序的输出到文件,可以想到肯定输出肯定要以中序遍历输出。
2)要求统计不同整数出现的次数,并且要建立一棵二叉排序树以达到顺序输出的目的,则树的结构肯定要加入一个计次成员变量,在建树的过程中要借助平衡二叉树。
3)要求从文件读取数据,并输出数据到文件,则必须调用到文件操作的函数,如打开文件fopen(),读取文件数据fscanf(),输出数据到文件fprintf(),最后关闭文件fclose()。
2、概要设计
1)二叉树数据类型(ADT)如下:
ADTBinaryTree
{数据对象D:
D是具有相同特性的数据元素的集合。
数据关系R:
若D=,则R=Φ称BinaryTree为二叉树;
若D≠,则R={H},H是如下二元关系:
⑴在D中存在惟一的称为根的数据元素root,它在关系H下无前驱;
⑵若D-{root}≠Φ,则存在D-{root}={
},且
=Φ;
⑶若
≠Φ,则
中存在惟一的元素
,>
H,且存在
上的关系
H,若
≠Φ,则
中存在惟一的元素
,>
H,且存在
上的关系
H;H={>,>,
};
⑷(
{
})是一棵符合本定义的二叉树,称为根的左子树,(
{
})是一棵符合本定义的二叉树,称为根的右子树。
基本操作:
(1)EQ(s,w)
函数功能:
相等返回1,不相等返回2。
(2)LQ(s,w)
函数功能:
前一个大于后一个返回1,否则返回零。
(3)R_Rotate(&T)
函数功能:
对二叉树作一次右旋处理。
(4)L_Rotate(&T)
函数功能函数功能对此二叉树作一次左旋处理。
(5)LeftBalance(&T)
函数功能:
对此二叉树作左旋平衡处理。
(6)RightBalance(&T)
函数功能:
对此二叉树作右旋平衡处理。
(7)InsertAVL(&T,s,&taller)
函数功能:
在此二叉树中顺序的插入原来不存在的结点s。
(8)in_order(root)
函数功能:
将排序二叉树的数据元素顺序的输出到文件。
}
2)存储结构
typedefstructBiTNode
//定义树结构
{
ElemTypedata;
intnum;//计次成员变量
intbf;//结点的平衡因子
structBiTNode*lchild,*rchild;
}BiTNode,*BiTree;
3)流程图
是
否
否
是
3、详细设计
在本程序中,重要的程序段有InsertAVL(BiTree&T,ElemTypes,bool&taller){},其主要作用是往二叉树中插入数据元素,并进行平衡处理;在这个函数的内部另外还调用了两个重要的函数LeftBalance(BiTree&T),RightBalance(BiTree&T),用来在建树过程中作平衡处理;在平衡处理的过程中,还有调用了R_Rotate()和L_Rotate()两个单旋处理函数。
1)插入函数
这个程序段是本程序的中心,它的作用是在查找的过程中建立一棵二叉排序树,并调用相应的平衡处理函数作平衡处理。
intInsertAVL(BiTree&T,ElemTypes,bool&taller)
//若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个数据//元素为e的新结点,并返回1,否则返回0,若因插入而合二叉排序树失去平衡,
//则作平衡旋转处理,布尔变量taller反映T长高与否。
{if(!
T)
{//插入新结点,树“长高”,置taller为TRUE
T=(BiTree)malloc(sizeof(BiTNode));T->data=s;
T->lchild=T->rchild=NULL;T->bf=EH;taller=true;T->num=1;
}
else
{if(EQ(s,T->data))
{taller=false;T->num++;return0;}
if(LQ(s,T->data))
{if(!
InsertAVL(T->lchild,s,taller))return0;
if(taller)
switch(T->bf)
{caseLH:
LeftBalance(T);taller=false;break;
caseEH:
T->bf=LH;taller=true;break;
caseRH:
T->bf=EH;taller=false;break;
}
}
else
{if(!
InsertAVL(T->rchild,s,taller))return0;
if(taller)
switch(T->bf)
{caseLH:
T->bf=EH;taller=false;break;
caseEH:
T->bf=RH;taller=true;break;
caseRH:
RightBalance(T);taller=false;break;
}
}
}
return1;
}
2)平衡函数
这个程序段也是本程序中的一个重要程序段,它的作用是对二叉树作左平衡处理,包含了双向旋转平衡处理的过程,调用了两个单向旋转平衡处理函数。
voidLeftBalance(BiTree&T)
//对以指针T所指结点为根的二叉树作左平衡旋转处理,结束时,指针T指向新
//的根结点。
{BiTreelc,rd;
lc=T->lchild;
switch(lc->bf)//检查*T的左子树的平衡度,并作相应的平衡处理
{caseLH:
T->bf=lc->bf=EH;R_Rotate(T);break;
caseRH:
rd=lc->rchild;
switch(rd->bf)//修改*T及其左孩子的平衡因子
{caseLH:
T->bf=RH;lc->bf=EH;break;
caseEH:
T->bf=lc->bf=EH;break;
caseRH:
T->bf=EH;lc->bf=LH;break;
}
rd->bf=EH;
L_Rotate(T->lchild);
R_Rotate(T);
}
}
由于右平衡处理函数RightBalance(BiTree&T)与左平衡理函数对称,作用也相似,下面就不列出了。
3)单向平衡函数
这个程序段是作单向平衡处理的,在对结点为根的二叉树作平衡处理的平衡处理函数(LeftBalance()和RightBalance())中都被调用到。
而与之对称的voidR_Rotate(BiTree)的功能与这个函数的功能相似,下面就不一一列出了。
voidL_Rotate(BiTree&T)
//对以*p为根的二叉排序树作左旋处理,处理之后p指向新的
//树根结点,即旋转处理之前的右子树的根结点
{BiTreelc;
lc=T->rchild;
T->rchild=lc->lchild;lc->lchild=T;T=lc;
}
4)中序遍历
这个程序段的主要作用是中序遍历建好的排序二叉树,并输出排序后的结果到文件中去!
voidin_order(BiTreeroot)//中序遍历,输出并打印排序后的结果
{if(root)
{in_order(root->lchild);
printf("%d\t\t\tnum=%d\n",root->data,root->num);//输出到屏幕
fprintf(fp,"%d\t\t\tnum=%d\n",root->data,root->num);//输出到文件
in_order(root->rchild);
}
}
5)打开文件、关闭文件
这个位于main()函数中,用来以读写方式打开文件,在统计、排序操作完成后,并关闭文件。
voidmain()
{
……
fp=fopen(nam,"r+");
……
fclose(fp);
……
}
6)主函数
这个位于主函数中的重要程序段,其主要作用是把文件中的整数逐个循环的输入到树中。
voidmain()
{
……
while(fscanf(fp,"%d",&x)!
=EOF)
InsertAVL(T,x,taller);
……
}
4、程序清单
/*
1、使用二叉排序树实现
2、功能实现
1)从文件中读出整数,统计不同整数出现的次数
2)输出不同整数及其出现的次数
3)按整数由小到大的次序将整数及其出现的次数写入文件
*/
#include
#include
#include
#defineLH+1//左高
#defineEH0//等高
#defineRH-1//右高
FILE*fp;//fp指向一个文件的结构体变量
booltaller;
typedefintElemType;
typedefstructBiTNode
//定义树结构
{ElemTypedata;
intnum;//计次成员变量
intbf;//结点的平衡因子
structBiTNode*lchild,*rchild;
}BiTNode,*BiTree;
intEQ(ElemTypes,ElemTypew)
//比较结点键值是否相等
{if(s==w)return1;
elsereturn0;
}
intLQ(ElemTypes,ElemTypew)
//比较结点键值大小
if(selsereturn0;
}
voidR_Rotate(BiTree&T)
//对以*p为根的二叉排序树作右旋处理,处理之后p指向新的
//树根结点,即旋转处理之前的左子树的根结点
{BiTreelc;lc=T->lchild;
T->lchild=lc->rchild;lc->rchild=T;T=lc;
}
voidL_Rotate(BiTree&T)
//对以*p为根的二叉排序树作左旋处理,处理之后p指向新的
//树根结点,即旋转处理之前的右子树的根结点
{BiTreelc;lc=T->rchild;
T->rchild=lc->lchild;lc->lchild=T;T=lc;
}
voidLeftBalance(BiTree&T)
//对以指针T所指结点为根的二叉树作左平衡旋转处理,结束时,
//指针T指向新的根结点
{BiTreelc,rd;lc=T->lchild;
switch(lc->bf)
//检查*T的左子树的平衡度,并作相应的平衡处理
{caseLH:
T->bf=lc->bf=EH;R_Rotate(T);break;
caseRH:
rd=lc->rchild;
switch(rd->bf)
//修改*T及其左孩子的平衡因子
{caseLH:
T->bf=RH;lc->bf=EH;break;
caseEH:
T->bf=lc->bf=EH;break;
caseRH:
T->bf=EH;lc->bf=LH;break;
}
rd->bf=EH;L_Rotate(T->lchild);R_Rotate(T);
}
}
voidRightBalance(BiTree&T)
//对以指针T所指结点为根的二叉树作右平衡旋转处理,结束时,
//指针T指向新的根结点
{BiTreelc,rd;lc=T->rchild;
switch(lc->bf)
//检查*T的右子树的平衡度,并作相应的平衡处理
{caseRH:
T->bf=lc->bf=EH;L_Rotate(T);break;
caseLH:
rd=lc->lchild;
switch(rd->bf)
//修改*T及其右孩子的平衡因子
{caseRH:
T->bf=LH;lc->bf=EH;break;
caseEH:
T->bf=lc->bf=EH;break;
caseLH:
T->bf=EH;lc->bf=RH;break;
}
rd->bf=EH;R_Rotate(T->rchild);L_Rotate(T);
}
}
intInsertAVL(BiTree&T,ElemTypes,bool&taller)
//若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个数据元素
//为e的新结点,并返回1,否则返回0,若因插入而合二叉排序树失去平衡,则作平
//衡旋转处理,布尔变量taller反映T长高与否。
P(237)
{if(!
T)
{//插入新结点,树“长高”,置taller为TRUE
T=(BiTree)malloc(sizeof(BiTNode));T->data=s;
T->lchild=T->rchild=NULL;T->bf=EH;taller=true;T->num=1;
}
else
{if(EQ(s,T->data)){taller=false;T->num++;return0;}
if(LQ(s,T->data))
{if(!
InsertAVL(T->lchild,s,taller))return0;
if(taller)
switch(T->bf)
{caseLH:
LeftBalance(T);taller=false;break;
caseEH:
T->bf=LH;taller=true;break;
caseRH:
T->bf=EH;taller=false;break;
}
}
else
{if(!
InsertAVL(T->rchild,s,taller))return0;
if(taller)
switch(T->bf)
{caseLH:
T->bf=EH;taller=false;break;
caseEH:
T->bf=RH;taller=true;break;
caseRH:
RightBalance(T);taller=false;break;
}
}
}