通过几天的努力,课设终于写完了!!!!
一. 需求分析
1. 本演示程序中由输入的实部和虚部生成一个复数.其中作为除数的复数不能为零.
2. 本演示程序由用户对话的方试进行,即在计算机终端上显示提示信息,由用户输入相应命令后执行相应的操作..
3. 程序执行的命令行包括
1)加; 2) 减; 3) 乘; 4) 除; 5) 求实部; 6) 求虚部; 7) 退出.
在执行每个操作前需要先构造相应个数的复数.
4. 测试数据
对下列各数据实现求和
(1)0,;0;应输出0
(2)3.1,0;4.22,8.9;应输出7.32+i8.9
(3)-1.33,2.34;0.1,-6.5;应输出-1.23 --i4.16
(4)0,9.7;-2.1,-9.7;应输出-2.1
(5)7.7,-8;-7.7,0;应输出-i8
二.概要设计
为实现以上功能,应用一个结构体表示一个复数,在定义若干操作.我们需要一个抽象数据类型:Complex.
1. 抽象数据类型可以表示为
ADT Complex{
数据对象:D={a[i]|a[i]∈CharSet,i=1,2}
数据关系:R={<a[i-1],a[i]>|a[i]∈D,i=1,2}
基本操作:
Add()
操作结果:实现求两个复数的和,并打印.
Sub()
操作结果:实现求两个复数的差,并打印.
Pgl()
操作结果:实现求两个复数的乘积,并打印.
Div()
操作结果:实现求两个复数的商,并打印.
GetR()
操作结果:实现求一个复数的实部,并打印.
GetI()
操作结果:实现求一个复数的虚部,并打印.
}ADT Complex
2. 本程序包含两个模块.
1)主程序模块:
Int main()
{
While(“命令”!=”退出”)
{
接受指令;
处理指令;
}
}
2)复数单元模块---实现复数的各种功能.
各模块之间的调用关系如下:
主程模块
↓
复数单元模块
三. 详细设计及编程实现
1)复数结构体定义如下:
/*复数构体
BY张林林*/
struct Complex
{
double real;
double imag;
};
2)对复数的各种操作定义如下:
/*功能:两复数相加
BY张林林*/
void add()
{
Complex r1;
Complex r2;
cout<<"请输入两个复数:"<<endl;
cout<<"第"<<1<<"个数的实部";
cin>>r1.real;
cout<<"第"<<1<<"个数的虚部";
cin>>r1.imag;
cout<<"第"<<2<<"个数的实部";
cin>>r2.real;
cout<<"第"<<2<<"个数的虚部";
cin>>r2.imag;
cout<<"相加的结果"<<endl;
if(r1.imag+r2.imag==0&&r1.real+r2.real==0)
{
cout<<"0"<<endl;
return ;
}
else if(r1.real+r2.real==0)
{
cout<<"i"<<r1.imag+r2.imag;
return;
}
else if(r1.imag+r2.imag==0)
{
cout<<r1.real+r2.real<<endl;;
return ;
}
cout<<(r1.real+r2.real)<<"+";
cout<<"i"<<(r1.imag+r2.imag)<<endl;
cout<<"********************"<<endl;
return ;
}
/*功能:求两复数之差
BY张林林*/
void sub()
{
Complex r1;
Complex r2;
cout<<"请输入两个复数:"<<endl;
cout<<"第"<<1<<"个数的实部";
cin>>r1.real;
cout<<"第"<<1<<"个数的虚部";
cin>>r1.imag;
cout<<"第"<<2<<"个数实部";
cin>>r2.real;
cout<<"第"<<2<<"个数的虚部";
cin>>r2.imag;
cout<<"相减的结果"<<endl;
if(r1.real!=r2.real)
{
if(r1.imag>r2.imag)
{
cout<<(r1.real-r2.real)<<"+";
cout<<"i"<<(r1.imag-r2.imag)<<endl;
}
else if(r1.imag<r2.imag)
{
cout<<(r1.real-r2.real)<<"-";
cout<<"i"<<(r2.imag-r1.imag)<<endl;
}
else
{
cout<<r1.real-r2.real<<endl;
}
}
else
{
if(r1.imag>r2.imag)
cout<<"i"<<r1.imag-r2.imag<<endl;
else if(r1.imag<r2.imag)
cout<<"-i"<<r2.imag-r1.imag<<endl;
else
{
cout<<"0"<<endl;
}
}
cout<<"********************"<<endl;
}
/*功能:求两复数之积
BY张林林*/
void pgl()
{
Complex r1;
Complex r2;
cout<<"请输入两个复数:"<<endl;
cout<<"第"<<1<<"个数的实部";
cin>>r1.real;
cout<<"第"<<1<<"个数的虚部";
cin>>r1.imag;
cout<<"第"<<2<<"个数的实部";
cin>>r2.real;
cout<<"第"<<2<<"个数的虚部";
cin>>r2.imag;
cout<<"相乘的结果"<<endl;
if(r1.real*r2.real-r1.imag*r2.imag==0&&r1.real*r1.imag+r1.imag+r2.real==0)
{
cout<<"0"<<endl;
return ;
}
if(r1.real*r2.real-r1.imag*r2.imag==0)
{
cout<<"i"<<r1.real*r1.imag+r1.imag+r2.real<<endl;
return ;
}
else if(r1.real*r1.imag+r1.imag*r2.real==0)
{
cout<<r1.real*r2.real-r1.imag*r2.imag<<endl;
return ;
}
else
{
cout<<(r1.real*r2.real-r1.imag*r2.imag)<<"+";
cout<<"i"<<(r1.real*r1.imag+r1.imag*r2.real)<<endl;
cout<<"********************"<<endl;
return ;
}
}
/*功能:求两两数之商
BY张林林*/
void div()
{
Complex r1;
Complex r2;
cout<<"请输入两个复数:"<<endl;
cout<<"第"<<1<<"个数的实部";
cin>>r1.real;
cout<<"第"<<1<<"个数的虚部";
cin>>r1.imag;
cout<<"第"<<2<<"个数的实部";
cin>>r2.real;
cout<<"第"<<2<<"个数的虚部";
cin>>r2.imag;
if(r2.real==0&&r2.imag==0)
{
cout<<"errorNumber"<<endl;
cout<<"********************"<<endl;
}
else
{
cout<<"相除的结果"<<endl;
if(r1.real*r2.real+r1.imag*r2.imag==0&&(-r1.real*r1.imag+r1.imag*r2.real)==0)
{
cout<<"0"<<endl;
return;
}
if(r1.real*r2.real+r1.imag*r2.imag==0)
{
cout<<"i"<<(-r1.real*r1.imag+r1.imag+r2.real)/(r2.real*r2.real+r2.imag*r2.imag)<<endl;
}
else if(-r1.real*r1.imag+r1.imag*r2.real==0)
{
cout<<(r1.real*r2.real+r1.imag*r2.imag)/(r2.real*r2.real+r2.imag*r2.imag)<<endl;
}
else
{
cout<<(r1.real*r2.real+r1.imag*r2.imag)/(r2.real*r2.real+r2.imag*r2.imag)<<"+"<<endl;
cout<<"i"<<(-r1.real*r1.imag+r1.imag*r2.real)/(r2.real*r2.real+r2.imag*r2.imag)<<endl;
cout<<"********************"<<endl;
}
}
}
/*功能:求一个数的实部
BY张林林*/
void GetR()
{
Complex r1;
cout<<"请输入一个复数:"<<endl;
cout<<"实部";
cin>>r1.real;
cout<<"虚部";
cin>>r1.imag;
cout<<r1.real<<endl;
cout<<"********************"<<endl;
}
/*功能:求一个数的虚部
BY张林林*/
void GetI()
{
Complex r1;
cout<<"请输入一个复数:"<<endl;
cout<<"实部";
cin>>r1.real;
cout<<"虚部";
cin>>r1.imag;
cout<<"i"<<r1.imag<<endl;
cout<<"********************"<<endl;
}
3)主程序模块定义如下:
/*功能:驱动函数
BY张林林*/
int main()
{
int i;
cout<<"请选择"<<endl;
cout<<"(1)加"<<"(2)减"<<"(3)乘"<<"(4)除"<<"(5)求实部"<<"(6)求虚部"<<"(7)退出"<<endl;
cin>>i;
while(i!=7)
{
switch(i)
{
case 1:
add();break;
case 2:
sub();break;
case 3:
pgl();break;
case 4:
div();break;
case 5:
GetR();break;
case 6:
GetI();break;
case 7:
exit(1);
default:
cout<<"error number";
}
cout<<"请选择"<<endl;
cout<<"(1)加"<<"(2)减"<<"(3)乘"<<"(4)除"<<"(5)求实部"<<"(6)求虚部"<<"(7)退出"<<endl;
cin>>i;
}
return 0;
}
5)函数的调用关系反应了演示程序的层次关系:
mian
--------------------------------------------------
↓ ↓ ↓ ↓ ↓ ↓
Add Sub Pgl Div GetR GetI
四.调试分析
本次作业比较简单,在调试的过中没有什么问题.就是要主意在打印的时候当结果为0是的情况.
程序中的每个算法的时间复杂度者是O(1).
五.测试结果.
1)执行命令1: 输入0 0 0 0,输出0.
2)执行命令2: 输入0 0 0 0,输出0.
3)执行命令3: 输入0 0 1 1,输出0
4)执行命令4: 输入0 0 1 1,输出0
5)执行命令5: 输入1,1 输出1
6)执行命令6: 输入1 1 输出1
7)执行命令7: 退出.
题目2:设计一个能进行有理数运算的演示程序
一. 需求分析
1) 本演示系统中,有理数有分数表示.
2) 本演示系统由用户分别输入分数的分子与分母.
3) 本演示系统以用户与计算机对话的方试进行,用户输入指令,计算机执行相应的操作,并把运算结果显示出来.
4) 程序执行的命令包括:
(1) 加 (2)减 (3)乘 (4)除 (5)求分子 (6)求分母
在执行相应的操作前要求有户输分相应分数.
5) 测试数据:
由用户自行输入相应数据测试.
二.概要设计
为实现上述功能,我们用一个结构体表示一个分数.为此,需要一个抽象数据类型Real.
1.Real抽象数据类型定义为:
ADT Real{
数据对象:D={a[i]|a[i]∈CharSet,i=1,2}
数据关系:R={<a[i-1],a[i]>|a[i]∈D,i=1,2}
huaJ()
操作结果:对一个有理数进行化简,并返回化简结果.
Add()
操作结果:求两个有理数的和,并打印.
Sub()
操作结果:求两个有理数的差,并打印.
Pgl()
操作结果:求两个有理数的乘积,并打印.
Div()
操作结果:求两个有理数的商,并打印.
GetZi()
操作结果:求一个有理数的分子,并的印.
GetMu()
操作结果:求一个有理数的分母,并打印.
}
2.本程序包含两个模块:
1)主程序模块
Int main()
{
While(“命令”!=”退出”)
{
接受命令;
处理命令;
}}
2)Real单元模块------实现Real抽象数据类型的定义.
各模块的调用关系如下:
主程序模块
↓
Real程序模块
三.详细设计及编程实现
1.Real结构体定义如下:
struct Real
{
int zi;
int mu;
};
2.各种操作定义如下:
/*功能:对分数进行化简
BY张林林*/
Real huaJ(int zi,int mu)
{
Real R;
int min;
if(zi>mu)
min=mu;
else min=zi;
for(int i=2;i<=(min);i++)
{
if(zi%i==0&&mu%i==0)
{
zi=zi/i;
mu=mu/i;
i=i-1;
}
}
R.zi=zi;
R.mu=mu;
return R;
}
/*功能:求两有理数(分数)之和
BY张林林*/
void add()
{
Real r1;
Real r2;
Real r3;
cout<<"请输入两个有理数:"<<endl;
cout<<"第"<<1<<"个数的分母";
cin>>r1.mu;
if(r1.mu==0)
{
cout<<"分母不能为!!"<<endl;
cout<<"******************************"<<endl;
return ;
}
cout<<"第"<<1<<"个数的分子";
cin>>r1.zi;
cout<<"第"<<2<<"个数的分母";
cin>>r2.mu;
if(r2.mu==0)
{
cout<<"分母不能为!!"<<endl;
cout<<"******************************"<<endl;
return ;
}
cout<<"第"<<2<<"个数的分子";
cin>>r2.zi;
cout<<"相加的结果"<<endl;
r3=huaJ(r1.zi*r2.mu+r2.zi*r1.mu,r1.mu*r2.mu);
cout<<"分子:"<<r3.zi<<endl;
cout<<"分母:"<<(r3.mu)<<endl;
cout<<"******************************"<<endl;
}
/*功能:求两有理数(分数)之差
BY张林林*/
void sub()
{
Real r1;
Real r2;
Real r3;
cout<<"请输入两个有理数:"<<endl;
cout<<"第"<<1<<"个数的分母";
cin>>r1.mu;
if(r1.mu==0)
{
cout<<"分母不能为!!"<<endl;
cout<<"******************************"<<endl;
return ;
}
cout<<"第"<<1<<"个数的分子";
cin>>r1.zi;
cout<<"弟"<<2<<"个数的分母";
cin>>r2.mu;
if(r2.mu==0)
{
cout<<"分母不能为!!"<<endl;
cout<<"******************************"<<endl;
return ;
}
cout<<"第"<<2<<"个数的分子";
cin>>r2.zi;
cout<<"相减的结果"<<endl;
r3=huaJ(r1.zi*r2.mu-r2.zi*r1.mu,r1.mu*r2.mu);
cout<<"分子:"<<(r3.zi)<<endl;
cout<<"分母:"<<(r3.mu)<<endl;
cout<<"******************************"<<endl;
}
/*功能:求两有理数(分数)之积
BY张林林*/
void pgl()
{
Real r1;
Real r2;
Real r3;
cout<<"请输入两个有理数:"<<endl;
cout<<"第"<<1<<"个数的分母";
cin>>r1.mu;
cout<<"弟"<<1<<"个数的分子";
cin>>r1.zi;
cout<<"第"<<2<<"个数的分母";
cin>>r2.mu;
cout<<"第"<<2<<"个数的分子";
cin>>r2.zi;
cout<<"相乘的结果"<<endl;
r3=huaJ(r1.zi*r2.zi,r1.mu*r2.mu);
cout<<"分子:"<<(r3.zi)<<endl;
cout<<"分母:"<<(r3.mu)<<endl;
cout<<"******************************"<<endl;
}
/*功能:求两有理数(分数)之商
BY张林林*/
void div()
{
Real r1;
Real r2;
Real r3;
cout<<"请输入两个有理数:"<<endl;
cout<<"第"<<1<<"个数的分母";
cin>>r1.mu;
if(r1.mu==0)
{
cout<<"分母不能为!!"<<endl;
cout<<"******************************"<<endl;
return ;
}
cout<<"第"<<1<<"个数的分子";
cin>>r1.zi;
cout<<"第"<<2<<"个数的分母";
cin>>r2.mu;
if(r2.mu==0)
{
cout<<"分母不能为!!"<<endl;
cout<<"******************************"<<endl;
return ;
}
cout<<"第"<<2<<"个数的分子";
cin>>r2.zi;
if(r2.zi==0)
{
cout<<"分母不能为!!"<<endl;
cout<<"******************************"<<endl;
}
else
{
cout<<"相除的结果"<<endl;
r3=huaJ(r1.zi*r2.mu,r1.mu*r2.zi);
cout<<"分子:"<<(r3.zi)<<endl;
cout<<"分母:"<<(r3.mu)<<endl;
cout<<"******************************"<<endl;
}
}
/*功能:求一个有理数的分子
BY张林林*/
void GetZi()
{
Real r1;
Real r3;
cout<<"请输入一个有理数:"<<endl;
cout<<"分母";
cin>>r1.mu;
if(r1.mu==0)
{
cout<<"分母不能为!!"<<endl;
cout<<"******************************"<<endl;
return ;
}
cout<<"分子";
cin>>r1.zi;
r3=huaJ(r1.zi,r1.mu);
cout<<"分子是"<<r3.zi<<endl;
cout<<"******************************"<<endl;
}
/*功能:求一有理数的分母
BY张林林*/
void GetMu()
{
Real r1;
Real r3;
cout<<"请输入一个有理数:"<<endl;
cout<<"分母";
cin>>r1.mu;
if(r1.mu==0)
{
cout<<"分母不能为!!"<<endl;
cout<<"******************************"<<endl;
return ;
}
cout<<"分子";
cin>>r1.zi;
r3=huaJ(r1.zi,r1.mu);
cout<<"分母"<<r3.mu<<endl;
cout<<"******************************"<<endl;
}
3.主程序模块定义如下:
/*测试函数
BY张林林*/
int main()
{
int i;
cout<<"请选择"<<endl;
cout<<"(1)加"<<"(2)减"<<"(3)乘"<<"(4)除"<<"(5)求分子"<<"(6)求分母"<<"(7)退出"<<endl;
cin>>i;
while(i!=7)
{
switch(i)
{
case 1:
add();break;
case 2:
sub();break;
case 3:
pgl();break;
case 4:
div();break;
case 5:
GetZi();break;
case 6:
GetMu();break;
default:
cout<<"errorNumber";
}
cout<<"请选择"<<endl;
cout<<"(1)加"<<"(2)减"<<"(3)乘"<<"(4)除"<<"(5)求分子"<<"(6)求分母"<<endl;
cout<<"请选择"<<endl;
cin>>i;
}
return 0;
}
4.各函数的调用关系图反应了程序的结构层次结构
Mian
-----------------------------------------
↓ ↓ ↓ ↓ ↓ ↓
Add sub pgl div GetZi GetMu
↓ ↓ ↓ ↓ ↓ ↓
huaJ huaJ huaJ hauJ huaJ huaJ
5.调试分析
1)程序比较简单,就是实现一些基本运算.
2)化简的算法还值得在推敲.
3)各函数的时间复杂度都是O(1).
六.测试结果
1) 执行命令” 1” ,输入1,1,1,1输出1,2
2)其它操作类似.
题目3:图书管理系统
一.需求分析
1) 每种书的登记内容包括:书号.书名.作者.现存量和总存量.
2) 本演示程序不使用文件,基本业务活动是通过书号(关键字)进行的.
3) 末演示系统实现的功能如下:
1)采编入库 2)清除库存 3)借阅 4)归还 5)显示
4) 测试数据
入库书号:35,16,18,70,5,50,22,60,13,17,12,45,25,42,15,90,30,7
然后清除库存:45,90,50,22,42
其余数据由用户输入
二.概要设计
本程序用到两个抽象数据类型:library抽象数据类型,lender抽象数据类型.
1) library抽象数据类型定义如下:
ADT library{
数据对象:D={a[i]|i=1,2,3….}
数据关系:R={a[i]∈D}
基本操作:
initLibrary(library &L)
操作结果:初始化图书管.
display(library L)
初始条件:L已存在.
操作结果:输出图书管中的所有书的信息
newBook(library &L)
初始条件:L已存在.
操作结果:新书入库(图书管中新增加一本书).
bClear(library &L)
初始条件:L已存在且L中有书存在.
操作结果:清除一本书.
}ADT library
2) lender抽象数据类型定义如下:
ADT lender{
数据对象:D={a[i]|i=1,2,3….}
数据关系:R={a[i]∈D}
基本操作:
initlend(lend &S)
操作结果:初始化一位借阅者
borrow(library &L,lend &S)
初始条件:L,S已存在.
操作结果: 借阅者S向图书管L借一本书.
bBook(library &L,lend &S)
初始条件:L,S已存在.
操作结果: 借阅者S向图书管L还一本书(此书是出自L)
}
3) 主程序
Int main()
{
初始化;
While(“命令”!=”退出”)
{
接受命令;
处理命令;
}
}
4) 本程序包含三个模块,调用关系如下:
主模块
↓
图书管模块
↓
借阅者模块
三.详细设计及编程实现
各结构体定义如下:
struct Book
{
int bNumber;//书号
char bName[20];//书名
char author[20];//作者
int nowNumber;//现存量
int total;//总存量
};
struct library
{
Book book[MAX];
int number;
};
struct lender
{
int id;
};
/*存放借阅者的
相关信息
BY林林*/
struct lend
{
lender len[MAX];
Book book[MAX];
int l;
};
各种操作定义如下:
int initLibrary(library &L)
{
L.number=0;
return 1;
}
int initlend(lend &S)
{
S.l=0;
return 1;
}
/*功能:显示图书管书
的信息
BY林林*/
int display(library L)
{
cout<<"存书情况如下"<<endl;
cout<<"书名"<<" "<<"书号"<<" "<<"作者"<<" "<<" "<<"现有量"<<" "<<"总库量"<<endl;
for(int i=0;i<L.number;i++)
{
cout<<L.book[i].bName<<" "<<L.book[i].bNumber<<" "<<L.book[i].author<<" "<<L.book[i].nowNumber<<" "<<L.book[i].total<<endl;
}
cout<<"*****************************************************"<<endl;
return 0;
}
/*功能:入库一本书
BY林林*/
int newBook(library &L)
{
Book b;
int i=0;
cout<<"输入你要入库书的信息"<<endl;
cout<<"书号:";
cin>>b.bNumber;
cout<<"书名:";
cin>>b.bName;
cout<<"作者:";
cin>>b.author;
while(i<L.number && L.book[i].bNumber!=b.bNumber)
i++;
if(i>=L.number)
{
strcpy(L.book[i].author,b.author);
strcpy(L.book[i].bName,b.bName);
L.book[i].bNumber=b.bNumber;
L.book[i].nowNumber=b.nowNumber=1;
L.book[i].total=b.total=1;
L.number++;
}
else
{
L.book[i].nowNumber++;
L.book[i].total++;
}
return 1;
}
/*功能:清除一本书
BY林林*/
int bClear(library &L)
{
Book b;
int i;
cout<<"请输入你要清除的书号"<<endl;
cin>>b.bNumber;
for(i=0;i<=L.number;i++)
if(L.book[i].bNumber==b.bNumber)break;
if(L.number==1)
{
L.number=0;
return 0;
}
for(int j=i;j<L.number;j++)
{
strcpy(L.book[j].author,L.book[j+1].author);
strcpy(L.book[j].bName,L.book[j+1].bName);
L.book[j].bNumber=L.book[j+1].bNumber;
L.book[j].nowNumber=L.book[j+1].nowNumber;
L.book[j].total=L.book[j+1].total;
}
L.number--;
return 0;
}
/*功能:借阅
BY林林*/
int borrow(library &L,lend &S)
{
Book b;
lender l;
int i;
int j=0;
cout<<"请输入你的图书证号"<<endl;
cin>>l.id;
cout<<"请输入你要借的书号"<<endl;
cin>>b.bNumber;
for(i=0;i<L.number;i++)
if(L.book[i].bNumber==b.bNumber)break;
if(i>=L.number)
cout<<"图书管没有这本书"<<endl;
else if(L.book[i].nowNumber==0)
cout<<"没有库存了"<<endl;
else
{
cout<<"借书已成功"<<endl;
L.book[i].nowNumber--;
while(j<=S.l)
{
j++;
}
S.book[j].bNumber=b.bNumber;
S.len[j].id=l.id;
S.l++;
}
return 0;
}
/*功能:归还
BY林林*/
int bBook(library &L,lend &S)
{
lender Lender;
Book b;
int i=0;
cout<<"请输入你的图书证号"<<endl;
cin>>Lender.id;
cout<<"请输入你要还的书号"<<endl;
cin>>b.bNumber;
while(i<=S.l)
{
i++;
if(Lender.id==S.len[i].id)break;
}
if(i>S.l)
{
cout<<"这本书不是本图书管的"<<endl;
return 0;
}
cout<<"还书成功"<<endl;
for(int j=i;j<=S.l;j++)
{
S.len[j+1].id=S.len[j].id;
S.book[j+1].bNumber=S.book[j].bNumber;
}
for(i=0;i<=L.number;i++)
if(L.book[i].bNumber==b.bNumber)break;
L.book[i].nowNumber++;
return 0;
}
主函数程序代码如下:
/*驱动函数
BY林林*/
int main()
{
int i;
lend S;
initlend(S);
library L;
initLibrary(L);
cout<<"你要做什么"<<endl;
cout<<"(1)采编入库(2)清除库存(3)借阅(4)归还(5)退出"<<endl;
cin>>i;
while(i!=5)
{
switch(i)
{
case 1:
newBook(L);
display(L);
break;
case 2:
bClear(L);
display(L);
break;
case 3:
borrow(L,S);
display(L);
break;
case 4:
bBook(L,S);
display(L);
break;
default:
cout<<"errorNumber"<<endl;
}
cout<<"你要做什么"<<endl;
cout<<"(1)采编入库(2)清除库存(3)借阅(4)归还(5)退出"<<endl;
cin>>i;
}
return 0;
}
四.设计和调试分析
1) 各个数据关系之间的关系不是很复杂,在写的时候采取了自上而下的调试方法,因此没有什么太大的问题.
2) 原来设计前还有一个续借的模块,因为某些原因没有完成,但是这个功能不是这次实验要求的.
3) 某些算法(比如查找)效率不是很高,还值得进一步的推敲.
4) 各算法的时间复杂度是O(n)n 为图书管中书的类型数.
五.测试结果
1)执行命令1,用户输入相应数据,则图书管保存一本书.
2)执行命令2,用户输入已存在的一本书的书号,则将从图书管中清除这全书.
3)执行命令3,用户可以向图书管借出一本书.(用户输入书号).
4)执行命令4:用户向图书管还一本书.
5)执行命令5:退出系统.
题目4:Joseph生死都问题.
一.问题描述.
每30个旅客同乘一条船,因为严重超载,加上风高浪大,危险万分;因此船长告诉乘客,只有将全船一半的旅客投入海中,其余人才能幸免遇难。
无奈,大家只得同意这种办法,并议定30个人围成一圈,由第一个人数起,依次报数,数到第9人,便把他投入大海中,然后再从他的下一个人数起,数到第9人,再将他扔进大海中,如此循环地进行,直到剩下15个乘客为止。问哪些位置是将被扔下大海的位置。
二.需求分析
1) 程序运行结果要求打印出”安全”的位置和”不安全”的位置.
2) 由于是循环计数,在程序中会用到一个单循环链表.
3) 程序更具有一般性,不只是适应30个人的要求.
三.概要设计
1)程序中会用到一个单循环链表的抽象数据类型.
ADT ClinkList{
数据对象:D={a[i]|i=1,2,3….}
数据关系:R={<a[i],a[i-1]>a[i]∈D}
基本操作:
initClist(ClinkList *&L)
操作结果:初始化单循环链表
creatList(ClinkList *&L)
操作结果:用尾插法建立单循环链表
初始条件:L已初始化
displayList(ClinkList *L)
操作结果:输出单循环链表中的数据域
初始条件:L已存在.
desideW(ClinkList *&L)
操作结果:决定哪个位置出列,并从循环链表中删除
初始条件:L已存在,且L中的实点个数大于要删除的个数
说明:此来体程序的核心算法.
}
2) 主程序
Int main()
{
While(“命令”!=”退出”)
{
接受命令;
处理命令;
}
}
3) 本程序只有现个模块,关系比较简单,其调用关系如下
主程序模块
↓
单循环链表模块
四.详细设计及编程实现
1.单循环链表结构体定义如下.
/*定义位置存结构
BY林林*/
struct ClinkList
{
int data;
ClinkList *next;
};
2.初始化程序如下
/*功能:初始化
BY林林*/
int initClist(ClinkList *&L)
{
L=(ClinkList*)malloc(sizeof(ClinkList));
if(!L)
{
cout<<”内存分配错误”<<endl;
return 0;
}
L->data=1;
L->next=NULL;
return 1;
}
3. 创建循环链表的代码如下
/*功能:采用头插法
创建循环链表(用循环
链表表示位置)
BY林林*/
int creatList(ClinkList *&L)
{
ClinkList *s=L;
ClinkList *r=NULL;
ClinkList *p=NULL;
int i=1;
while(i<=N-1)
{
p=(ClinkList*)malloc(sizeof(ClinkList));
s->next=p;
p->data=i+1;
s=s->next;
i++;
}
p->next=L;
return 0;
}
4.核心算法如下
/*核心算法:主要决定第几个位
置出列,然后从链表中删除
BY林林*/
int desideW(ClinkList *&L)
{
int i=1;
int num=0;
ClinkList *p=L;
ClinkList *s=p->next;
ClinkList *q=p->next->next;
cout<<”以下位置不安全”<<endl;
while(num!=K)
{
if(i==M-1)
{
if(s==L)
{
L=s->next;
}
cout<<s->data<<” “;
p->next=q;
free(s);
num++;
p=p->next;
s=p->next;
q=p->next->next;
i=1;
}
else
{
p=p->next;
s=s->next;
q=q->next;
i++;
}
}
cout<<endl;
return 0;
}
5.主程序如下
/*驱动主函数*/
int main()
{
ClinkList *L;
initClist(L);
creatList(L);
displayList(L);
desideW(L);
cout<<”以下位置是安全的”<<endl;
displayList(L);
return 0;
}
6.各函数的调用关系图反应了程序的结构层次结构
Main
↓ ↓ ↓ ↓
initClist creatList displayList disideW
五.设计和调试分析
1)因为是循环计数,故用单循环链表.
2)最初本来用的是带头结点的单循环链表,但是在调试是遇到很多问题.一个比较头疼的就是在计数是头结点也算在内了,和测试数据有差别.
3)在改用不带头点的循环链表后又遇到问题:假如在某次操作中要删去头结点怎么办?
4)其除算法比较简单.只是在2.3两个问题上浪费了一些时间.
六.测试结果
总结:
1) 通过这次课设,提升了自已的动手能力,加深了对各种存储结构的理解,熟悉了各种算法,也了解了一个高效算法的重要性.
2) 本次课设两个必做题比较简单,就是一个结构体,然后就是一些简单的运算.在有理数的运算中有一个化简的算法,这个算法是自已根据数论知识摸索出来的.
3) 两个选做题,图书管理是比较有成就感的一个,完全拼弃了B树的复杂算法.打印信息采用了”表”的形式打印.约瑟夫生死问题是用循环链表实现,只要注意对头结点的操作问题就变得比较简单了.