root->children[i]=NULL;
}
boolBTreeSearch(sBTree*T,intcount,sBTree*&x,int&index)
{//查找操作
inti=0;
while(i<(T->n)&&count>(T->keywords[i].count))
i++;
if(i<(T->n)&&count==(T->keywords[i].count)){
x=T;
index=i;
returntrue;
}
if(T->leaf)
returnfalse;
else
returnBTreeSearch(T->children[i],count,x,index);
}
voidBTreeInsert(sKeywordskeywords)
{//插入操作
sBTree*r=root;
if(r->n==MAX_KEYWORDS){//如果结点B树已满,那么分配新的结点
sBTree*newNode=(sBTree*)malloc(sizeof(sBTree));
root=newNode;
newNode->leaf=false;
newNode->n=0;
newNode->children[0]=r;
BTreeSplitChild(newNode,0);
BTreeInsertNonfull(newNode,keywords);
}
else
BTreeInsertNonfull(r,keywords);
}
voidBTreeInsertNonfull(sBTree*x,sKeywordskeywords)
{
inti=(x->n);
while(i>0&&keywordskeywords[i-1])
i--;
if(x->leaf)
AddKeywordsToLine(x,i,keywords,NULL,true);
else{
if(x->children[i]->n==MAX_KEYWORDS){
BTreeSplitChild(x,i);
if(keywords>x->keywords[i])
i++;
}
BTreeInsertNonfull(x->children[i],keywords);
}
}
voidBTreeDeleteKeywords(sBTree*x,intcount)
{//删除结点
sKeywordskeywords;
sBTree*newNode;
intindex=-1;
if(x->leaf){
BTreeDeleteLeafData(x,count);
}
elseif(DataInNode(x,count,index)){
if((x->children[index]->n)>MIN_KEYWORDS){
keywords=MaxKeywords(x->children[index]);
x->keywords[index]=keywords;
BTreeDeleteKeywords(x->children[index],keywords.count);
}
elseif((x->children[index+1]->n)>MIN_KEYWORDS){
keywords=MinKeywords(x->children[index+1]);
x->keywords[index]=keywords;
BTreeDeleteKeywords(x->children[index+1],keywords.count);
}
else{
newNode=RemoveKeywordsFromLine(x,index,keywords,false);
BTreebine(x->children[index],keywords,newNode);
BTreeDeleteKeywords(x->children[index],count);
}
}
else{
for(index=0;indexn;index++){
if(countkeywords[index].count)
break;
}
if(x->children[index]->n==MIN_KEYWORDS){
if(index>0&&(x->children[index-1]->n)>MIN_KEYWORDS){
newNode=RemoveKeywordsFromLine(x->children[index-1],x->children[index-1]->n-1,keywords,false);
AddKeywordsToLine(x->children[index],0,x->keywords[index-1],newNode,false);
x->keywords[index-1]=keywords;
BTreeDeleteKeywords(x->children[index],count);
}
elseif(index<(x->n)&&(x->children[index+1]->n>MIN_KEYWORDS))
{
newNode=RemoveKeywordsFromLine(x->children[index+1],0,keywords,true);
AddKeywordsToLine(x->children[index],x->children[index]->n,x->keywords[index],newNode,true);
x->keywords[index]=keywords;
BTreeDeleteKeywords(x->children[index],count);
}
else{
if(index==0){
newNode=RemoveKeywordsFromLine(x,index,keywords,false);
BTreebine(x->children[index],keywords,newNode);
BTreeDeleteKeywords(x->children[index],count);
}
else{
newNode=RemoveKeywordsFromLine(x,index-1,keywords,false);
BTreebine(x->children[index-1],keywords,newNode);
BTreeDeleteKeywords(x->children[index-1],count);
}
}
}
else{
BTreeDeleteKeywords(x->children[index],count);
}
}
newNode=root;
while(root->n==0){
newNode=root->children[0];
free(root);
root=newNode;
}
}
(3)图书管理存储定义
voidprintBTree(sBTree*T);//B树的形式显示当前所有的图书号
voidprintTab();
voidInsertBook(sBTree*T,sKeywordskeywords);//插入新书
sKeywordsMakeNewBook();//输入新书的信息
voidrent(intcount);//借书
voidget(intcount);//还书
〔4〕图书管理函数定义
sKeywordsMakeNewBook()//输入新书的信息
{
sKeywordskeywords;
printf("请输入新书编号:
\n");
scanf("%d",&(keywords.count));
printf("请输入新书名称:
\n");
scanf("%s",keywords.name);
printf("请输入新书\n");
scanf("%s",keywords.author);
printf("请输入新书数量:
\n");
scanf("%d",&(keywords.allReserves));
keywords.reserves=keywords.allReserves;//现有数量等于库存量
returnkeywords;
}
voidInsertBook(sBTree*T,sKeywordskeywords)//插入新书
{
intindex;
sBTree*x;
boolexist=BTreeSearch(T,keywords.count,x,index);
if(exist){
x->keywords[index].allReserves+=keywords.allReserves;//库存增加
x->keywords[index].reserves+=keywords.reserves;//现有量增加
}
else{
BTreeInsert(keywords);
}
}
voidrent(intcount)//借书,书库中有书号为count的书,借阅成功,否那么“查找
//失败
{
sBTree*x;
intindex;
if(BTreeSearch(root,count,x,index)&&(x->keywords[index].reserves>0))
x->keywords[index].reserves--;
else
printf("查找失败!
\n");
}
voidget(intcount)//还书,如果书库中有书号为count的书,那么可归还
{//假设无,那么输出“查无此书〞。
sBTree*x;
intindex;
if(BTreeSearch(root,count,x,index))
x->keywords[index].reserves++;
else
printf("查无此书!
\n");
}
voidprintBTree(sBTree*T)//B树的形式显示当前所有的图书号
{
if(T==NULL)
return;
if(T->leaf){
for(inti=0;in;i++){
printTab();
printf("%d\n",T->keywords[i].count);
}
}
else{
for(inti=0;in;i++){
deep++;
printBTree(T->children[i]);
deep--;
printTab();
printf("%d\n",T->keywords[i].count);
}
deep++;
printBTree(T->children[T->n]);
deep--;
}
}
voidprintTab()//按制表位输出书号
{
for(inti=0;iprintf("\t");
}
(5)主函数
voidmain()
{
sKeywordskeywords;
intcount;//书号
charchoice;
CreateBTree();//构建B树
printf("\n\n");
printf("图书管理系统主菜单\n");
printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
printf("☆1----采编入库☆\n\n");
printf("☆2----去除库存☆\n\n");
printf("☆3----借阅☆\n\n");
printf("☆4----归还☆\n\n");
printf("☆5----显示☆\n\n");
printf("☆6----退出☆\n\n");
printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
printf("请选择相应编码:
");
do{
scanf("%c",&choice);
switch(choice)
{
case'1':
//采编入库
keywords=MakeNewBook();
InsertBook(root,keywords);
break;
case'2':
//去除库存
printf("要删除的书编号为:
");
scanf("%d",&count);
BTreeDeleteKeywords(root,count);
break;
case'3':
//借书
printf("要借出的书编号为:
");
scanf("%d",&count);
rent(count);
break;
case'4':
//还书
printf("归还的树编号为:
");
scanf("%d",&count);
get(count);
break;
case'5':
//退出
printBTree(root);
default:
break;
}
}while(choice!
='6');
}
函数调用过程如以下图所示:
4.调试分析
⑴调试过程中遇到的问题以及对设计与实现的回忆讨论和分析:
对于本次设计个人感觉难度很大,因为图书管理系统涉及到的功能比拟多,采编入库、去除库存、借阅和和归还,其中最难的局部是B树定义和操作以及B树相关操作的调用,书上对于B树这一块的容比拟少,网上B树的根本操作和算法很少,因此在B树的插入和删除算法上花了很多时间,后来通过网上查找资料跟同学讨论得出。
此外,因为涉及的算法和代码比拟多,很容易出各种各样的错,在编译面也花了不少时间。
⑵算法的时空分析:
这个图书管理系统的存储时建立在存上的,故程序退出数据得不到保存,每个功能感觉比拟独立,相互间联系不算多,想要提高根本操作和算法的效率只能通过在算法的设计以及存储构造上下功夫。
⑶经历和体会:
?
数据构造?
这门课程考验的不仅仅是人的思维,更多的是考验人的耐心和洞察力,想要学好这一门课程,掌握根本要领,以及编写出执行能力各面都强的程序需要花更多的时间去钻研;在编写过程中,会出现各种各样细节上的问题,大到一条算法,小到一个“=〞与“==〞或者是“;〞与“;〞都可能成为你的障碍,细心和结实的根底知识很重要。
5.用户使用说明
1.本程序运行环境为VC6.0,执行文件为:
图书管理系统.exe;
2.程序界面与菜单信息
选择1:
采编入库,新书购入,将书号、书名、著者、册数、出版时间添参加图书账目中去,如果这种书在帐中已有,那么只将总库存量增加,每新增一个书号那么以凹入表的形式显示B树现状。
选择2:
去除库存,实现某本书的全部信息删除操作,没去除一个书号那么已以凹入表的形式显示B树现状。
选择3:
图书借阅,如果书的库存量大于零时那么执行出借,登记借阅者的图书证号和XX,系统自动抓取当前借阅时间和计算归还时间。
选择4:
图书归还,注销借阅者信息,并改变该书的现存量。
选择5:
显示输出。
选择6:
平安退出。
6.测试结果
测试数据:
入库书号:
35,16,18,70,5,50,22,60,13,17,12,45,25,42,15,90,30,7
分别删除书号:
45、90、50、22、42
(1)新书入库界面如下:
〔2〕所有的书号录入完毕后以B树形式显示:
〔3〕分别删除书号45、90、50、22、42
(4)删除后以B树形式显示剩下所有的书号
(5)当只向系统中录入书号为35的书时,以下为借书号为12和书号为35、还书号为12和还书号为35的运行情况〔成功和失败的测试结果〕
7.附录