《数据结构》课程设计报告
题 目
文章编辑、纸牌游戏、猴子选大王
专 业: 计 算 机 应 用 技 术
班 级: 计 应 0 7 0 1
学 号: 3 0 1 0 7 0 1 3 0
姓 名: 梁 光 贵
指导教师: 陈 香 兰
二00八 年 10 月 25日
目录
一. 课程设计目的~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~第3页
二. 课程设计目标~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~第3页
三. 需求分析~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~第4页
四. 程序实现思想~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~第5页
五. 设计说明~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~第5页
六. 源代码~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~第7页
七. 运行后的菜单展示~~~~~~~~~~~~~~~~~~~~~~~~~~~~第13页
八. 调试分析~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~第15页
九. 心得体会~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~第16页
一.课程设计目的:
熟练掌握数据结构这门课程,掌握经性表、栈、队列、串、数组、广义表、树和二叉树以及图等基本类型的数据结构及其应用。
进一步熟悉抽象数据类型的定义和实现、如何利用数组的动态分酚实现顺序结构、继承的实现方式。
学会分析研究计算机加工的数据结构的特性,以便为应用涉及的数据选择适当的逻辑结构、想念结构及基相应的算法并初步掌握算法的时间分析和空间分析的技术。
基本掌握程序设计的基本思路和方法。
利用所学的基本知识和技能,解决简单的程序设计问题各算法描述
培养我们的数据抽象能力。
二.设计目标:
题目1:文章编辑
功能:输入一页文字,程序可以统计出文字、数字、空格的个数。
静态存储一页文章,每行最多不超过80个字符,共N行;要求(1)分别统计出其中英文字母数和空 格数及整篇文章总字数;(2)统计某一字符串在文章中出现的次数,并输出该次数;(3)删除某一子串,并将后面的字符前移。
存储结构使用线性表,分别用几个子函数实现相应的功能;
输入数据的形式和范围:可以输入大写、小写的英文字母、任何数字及标点符号。
输出形式:(1)分行输出用户输入的各行字符;(2)分4行输出"全部字母数"、"数字个数"、"空格个数"、"文章总字数"(3)输出删除某一字符串后的文章;
题目2:纸牌游戏
任务:编号为1-52张牌,正面向上,从第2张开始,以2为基数,是2的倍数的牌翻一次,直到最后一张牌;然后,从第3张开始,以3为基数,是3的倍数的牌翻一次,直到最后一张牌;然后…从第4张开始,以4为基数,是4的倍数的牌翻一次, 直到最后一张牌;...再依次5的倍数的牌翻一次,6的,7的直到 以52为基数的 翻过,输出:这时正面向上的牌有哪些?
题目3:猴子选大王
任务:一堆猴子都有编号,编号是1,2,3 ...m ,这群猴子(m个)按照1-m的顺序围坐一圈,从第1开始数,每数到第N个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,则该猴子为大王。
要求:
输入数据:输入m,n m,n 为整数,n
三.需求分析:
文章编辑:
1.文章录入:包含中英文,空格和各种字符;用函数shuchu()来实现.
2.文章的统计: 包含中英文字母.空格数和文章总字数的统计,用函数Tongjiwz()来实现.
3.字符统计:根据客户的需要,统计在文章任一字符出现的次数,用函数GetTime()来实现.
4.字符的删除: 根据客户的需要,把文章中出现的符合客户要求的全部删除,用shanchu()来实现.
纸牌游戏:
用函数node()按照题目要求的规则,用几个循环体来实现.
猴子选大王:
首先用一个数组来存放猴子的编号,从1到m,然后用hzxdw()按题目要求,用两个双重循环来实现猴子大王的选举.
四.程序实现思想:
首先必须确定实现这个课程设计的主算法是使用链式存储结构还是栈又或是数组和广义表。
根据题目要求需要实现的功能有:
1、 数据录入:输入各种数据;
此处即创建链表的过程,调用一个成员函数负值。在此处还有一个方法实现,即先输入数据,然后再调用构造实现。
2、数据统计:
存储方式的选择,是使用链式存储结构还是栈又或是数组和广义表;遵守先定义后调用的原则;数组定义时注意下标的起始值和上限;链表定义时注意结点中的项;准确运用结点。
3、 数据输出:按要求的格式打印
调用do循环和for循环,通过遍历链表实现输出,用cout函数出。
4、 查找,修改,删除:
这三个功能的核心是寻找成员,先遍历链表,然后寻找对应的ID号来找到结点,然后再对结点实行删除,修改操作。
五.设计说明:
题目1:文章编辑
一 .算法思想
用顺序表来存放一篇文章,用指针*wz来录入文章,文章以#作为结束,然后统计文章各种数据,直到#号为止,查找用户要统计的和删除的字符都是一样的思想,删除某一子串,并将后面的字符前移。
题目2:猴子选大王
一、算法思想
将表中最后一个结点的指针域指向头结点,整个链表形成一个环,构造循环链表 ‘*L’。由此,从表中任意一个结点开始,都可以遍历全表。再用一个for循环来实现从第1开始数,第数到第N个,该猴子就要离开此圈。如果链表不空的话,用’a’指向开始结点,往后数到第N个结点,就把第N-1个结点与第N+1个结点链在一起,即实现了删除第N个结点。如此反复,直到L的后继结点是它自己,即圈中只剩最后一只猴子,那么这只猴子就是大王。
二、概要设计
1)、猴子的存放采用链式存储结构,利用循环链表来实现建立的,其表示方法是递归定义的:
typedef struct Mnode
{ int data;
struct Mnode *next;
}Mnode;
根据题目要求,要让这M只猴子顺序围坐一圈,那就得用循环链表,只须将单循环链表的尾指针的NEXT域指向头指针。它的判空条件是L=L->next =NULL;
(非空表) (空表)
单循环链表
2)、函数status Electe_King()读取数据M、N后,然后就根据N的值,用for循环数猴子结点用’a’指向开始结点,往后数到第N个结点,就把第N-1个结点与第N+1个结点链在一起,即实现了删除第N个结点。如此反复,直到L的后继结点是它自己,即圈中只剩最后一只猴王。其源代码如下:
for(int j=1;j<=N;j++)
{ L=L->next;
if(L->data!=L->next->data)
{ a=L->next;
L->next=L->next->next;
L=L->next->next;
delete a;
}
}
本算法只用了两个简单的for循环,所以时间复杂度为O(m2 )。其中难点是如何实现数到第N就删除它。
题目3:纸牌游戏的算法思想与猴子选大王的大体上相似。
六.源代码:
#define chuqi 1000
#define zengjia 100
#include
#include
typedef struct{
char *wz;
int length;
int listsize;
}sqlise;
void Tongjiwz(char *wz,int zy,int kg,int zs)
{//统计文章各种数据的函数,wz代表文章,zy代表中英文字母数,kg代表空格数,zs代表文章总字数
char *p=wz;
zy=kg=zs=0;
while(*p!='@')
{
if((*p>0x40&&*p<0x5B)||(*p>0x60&&*p<0x7B)) zy++;
if(*p==0x20) kg++;
zs++;
p++;
}
cout<<"统计完成!结果如下:"<
cout<<"中英文字母数:"<
}
void GetTime(char* wz,char* p)
{//统计某一字符串在文章中出现的次数
char *a=wz,*temp=a,*b=p;
int num=0,zj;
while(*a!='@')
{
temp=a;
b=p;
while(*b!='#')
{
if(*(temp++)==*(b++))
zj=1;
else
zj=0;
}
if(zj)num++;
a++;
}
cout<
cout<
}
void shanchu(char *wz,char *p)
{//删除某一字符串
char *a=wz,*temp=a,*b=p;
int zj=0;
while(*a!='@')
{
temp=a;
b=p;
while(*b!='#')
{
if(*(temp++)==*(b++))
zj=1;
else
zj=0;;
}
if(zj)
{
while(*temp!='@'&&(*(a++)=*(temp++)))
*a='@';
cout<<"删除字符串成功!"<
}
a++;
}
cout<<"删除后的文章如下:"<
while(*wz!='@')cout<<*(wz++);
cout<
}
void shuchu(sqlise &L){//输入文章后输出文章
char n;
int i=0;
int m;
L.wz=(char *)malloc(chuqi*sizeof(char));
if(!L.wz)cout<<"存储分配失败!"<
else
{
cout<<"ok!"<
L.length=0;
L.listsize=chuqi;
}
cout<<"请输入文章:"<
cin>>n;
while(n!='#')
{
L.wz[i]=n;
i++;
cin>>n;
m=i;
}
cout<<"你刚才输入的文章如下:"<
for(i=0;i
cout<
cout<
}
typedef struct need{//纸牌游戏
int data;
int tag;
}need;
void node(){
need park[52];
int i,j;
for(i=1;i<=52;i++){
park[i-1].data=i;
park[i-1].tag=1;
}
for(i=2;i<=52;i++){
for(j=i;j<=52;j++){
if(park[j-1].data%i==0)
park[j-1].tag=park[j-1].tag*(-1);
}
}
cout<<"※※※※※※※※※※※※纸牌游戏结束时正面向上的牌有※※※※※※※※※※※※";
cout<
for(i=0;i<52;i++){
if(park[i].tag==1){
cout<<"※※※※※※※※※※※※※※※※※第";
cout<
}
}
}
void hzxdw(int m,int n)//猴子选大王
{
int a[100];
int s=0,bj=m; //s作为n的标志
for(int i=0;i
a[i]=i+1; //为猴子编号
while(bj>1)//当bj=1时表明猴子大王已选到
{
bj=0;
for(i=0;i
{
if(a[i])
s++;//记数;
if(s==n)
s=a[i]=0; //猴子离开此圈;
if(a[i])
bj++;
}
}
for(i=0;i
if(a[i]!=0)
cout<<"猴子大王为:"<<(i+1)<
}
void main()
{
zcd:
cout<<"**********************************************"<
cout<<"* 想进入文章编辑系统,请按1 *"<
cout<<"* 想进行纸牌游戏, 请按2 *"<
cout<<"* 想进行猴子选大王, 请按3 *"<
cout<<"**********************************************"<
int m;
cin>>m;
if(m==1)
{
sqlise T;
char *n,*m,c[100],b[100];
int z,k,s,l,i;
shuchu(T);
pp:
cout<<"**********************************************"<
cout<<"*你要统计文章各种数据, 请按11 *"<
cout<<"*统计某一字符串在文章中出现的次数,请按12 *"<
cout<<"*你要删除某一字符串, 请按13 *"<
cout<<"*提醒:想返回主菜单请按4 *"<
cout<<"**********************************************"<
cout<<" 欢迎进入文章编辑系统,你想做什么,请选择: "<
cin>>l;
switch(l)
{
case 11:Tongjiwz(T.wz,z,k,s);goto pp;break;
case 12:cout<<"输入你要统计的字符串:";
for(i=0;i<100;i++)
{
cin>>c[i];
if(c[i]=='#')break;
}
m=c;
GetTime(T.wz,m);goto pp;break;
case 13:cout<<"输入你要删除的字符串:";
for(i=0;i<100;i++)
{
cin>>b[i];
if(b[i]=='#')break;
}
n=b;
shanchu(T.wz,n);goto pp;break;
case 4: goto zcd;break;
}
}
else if(m==2)node();
else if(m==3)
{
int zs,n1;
cout<<"请输入猴子总数和规则中规定n的值:";
cin>>zs>>n1;
hzxdw(zs,n1);
}
cout<<"提醒:想返回主菜单请按4"<
int k;
cin>>k;
while(k==4) goto zcd;
}
七.运行后的菜单展示
八、调试分析
(1)、语法错误:
语法错误相对来说要好调试一些的,但有两点需要特别指出:一是应该用规范化的格式输入源程序,我推荐的格式是:函数体内、循环体内等都应该缩进一个TAB位,相应的块语句的两个大括号都应保持在同一列上,函数体之间、模块之间都应用空行隔开,这就解决了各种匹配的问题,更重要的是它极大的增强的程序的可读性。二是应该注意函数的实参与形参的传递问题,要尽量保持两者类型的匹配,(当不匹配又可通过编译时会发生数据类型的隐式转换,这样会产生很多不安全且又很难找到的错误)当不需要改变形参时,只需传入变量,如果你想在函数体内改变函数的外部变量,则传入指针:
(2)指针问题:
如:char *name;再将name做为一个指针传到函数中,你的本意可能是想通过函数改变你的字符串,但这里你忽略了一个问题,你没有初始化你的指针却用了它,这样很不安全,虽然你有时可以运行,却有了不安定的因素。你可以这样定义:char name[20];这里的name是一个常量地址,也是一个数组名,因此不用担心它没有被初始化。字符数组与字符串的区别是前者不用在最末位加一个’/0’,但你如果把它当做字符串用时系统会自动给你加上的,因此在定义字符数组时尽量多定义一位)
(3)注意中英文符号
如:中文的分号和英文的分号是不一样的,这是我在调试中最大的体会,害的我用了半个多小时呢!
八.心得体会:
真正可称得上“好程序”是要满足一大堆的条件的。可读性、健壮性、可维护性、高效性等条件。其实大部分功能我早就已经实现了,(只用了三天),但其后的测试、修改、完善、注释、润色和现在的编写系统文档也用了不少的时间。
成功的感觉真好!当你看着自己把功能一个个实现,把错误一个调试出来,那种感觉给了自己某种安慰,还有自信!
要提高自己的编程能力,你必须亲自去体验、去设计、编辑、编译、调试、运行。在此之前,我也以为自己对C语言已经比较懂了,可还是遇到了一系列问题,也学到很多东西。每一个程序员都是在失败、尝试、失败、尝试与收获中成长起来的。我本学识尚浅,无权谈论这些,只是希望能对大家有所警醒,编程之道漫漫无边,吾将上下而求索.最后以林锐先生的话来作为自己的追求目标和最后的结束语:以振兴民族软件产业为己任,作真实、正值、优秀的科技人员!