7书馆管理系统实验报告.docx
- 文档编号:30692647
- 上传时间:2023-08-19
- 格式:DOCX
- 页数:45
- 大小:148.56KB
7书馆管理系统实验报告.docx
《7书馆管理系统实验报告.docx》由会员分享,可在线阅读,更多相关《7书馆管理系统实验报告.docx(45页珍藏版)》请在冰豆网上搜索。
7书馆管理系统实验报告
一、问题的描述………………………………………………………2
二、需求分析…………………………………………………………2
三、系统设计…………………………………………………………3
3.1概要设计…………………………………………………………3
3.2详细设计…………………………………………………………3
3.3函数说明…………………………………………………………7
四、系统实现……………………………………………………………9
4.1、程序界面…………………………………………………………9
4.2、菜单信息…………………………………………………………10
4.3、单个书号入库显示树状态………………………………………10
4.4、全部书号入库显示树状态………………………………………11
五、实验总结与展望……………………………………………………13
一、问题概述
二、需求分析
图书管理系统中图书管理模块包括图书类型定义:
书号、现存量、总存量,出版时间为整型,定价为浮点型,书名、著者名为字符型,借阅指针、预约指针为读者类型;读者类型定义:
证号为整型、姓名为字符型,另外借阅类型和预约类型组合成其中的共用体类型。
B树(2-3树)类型定义:
关键字个数和关键字数组为整型、另外还有指向双亲的指针、指向子树的指针、记录单元指针;B树查找结果类型定义:
节点指针、关键字序号和查找标志变量为整型。
演示程序以用户和计算机的对话方式进行,在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中规定的运算命令,相应的输入数据和运算结果显示在后面。
该演示系统,没有使用文件,全部数据放在内存存放。
四项基本业务都以书号为关键字进行的,采用了B树(2-3树)对书号建立索引,以提高效率。
图书管理系统实现功能:
①采编入库:
新书购入,将书号、书名、著者、册数、出版时间添加入图书账目中去,如果这种书在帐中已有,则只将总库存量增加,每新增一个书号则以凹入表的形式显示B树现状。
②清除库存:
实现某本书的全部信息删除操作,每清除一个书号则已以凹入表的形式显示B树现状。
③图书借阅:
如果书的库存量大于零时则执行出借,登记借阅者的图书证号和姓名,系统自动抓取当前借阅时间和计算归还时间。
④图书预约:
如果某书库存为零,则记录预约者姓名和证号,系统自动抓取当前预约时间和取书时间。
⑤图书归还:
注销借阅者信息,并改变该书的现存量。
⑥作者专区:
输入作者名字,系统将查找相应作者全部著作并显示出来。
⑦图书信息:
可以根据书号查阅此书基本信息、借阅信息和预约信息,亦可以查找全部图书基本信息。
三、系统设计
3.1、概要设计
抽象数据类型B树定义:
ADTBTree{
数据对象:
D是具有相同特性的数据元素的集合。
各个数据元素均含有类型相同,可惟一标识数据元素的关键字。
数据关系:
数据元素同属于一个集合并且:
一棵m阶的B树,或为空,或为满足下列特性的m叉树:
树中每个结点至多有m棵子树;
若根结点不是叶子结点,则至少有两棵子树;
除根之外的所有非终端结点至少有m/2(取上限)棵子树;
所有的非终端结点包含下列信息数据:
(n,A0,K1,A1,K2,A2,K3,……,Kn,An)
其中:
Ki(i=1,2,……n)为关键字,且Ki 基本操作: SearchBTree(T,key); 初始条件: B树T存在,key为和关键字类型相同的给定值。 操作结果: 若T中存在关键字等于key的数据元素,则返回该元素的值或在表中的位置,否则返回“空”。 Insert(T,i,k,P,recptr) 初始条件: B树q和p存在,i、k是指定变量,recptr指针有效 操作结果: 将k和ap分别插入到q->key[i+1]和q->ptr[i+1],并插入关键字为k的记录recptr InsertBTree(&T,e); 初始条件: B树T存在,e为待插入的数据元素。 操作结果: 若T中步存在关键字等于e.key的数据元素,则插入e到T中。 DeleteBTree(&T,key); 初始条件: B树T存在,key为和关键字类型相同的给定值。 操作结果: 若T中存在其关键字等于key的数据元素,则删除之 BTreeTraverse(BTreeT,Visit) 初始条件: B树T存在,Visit是对T结点的函数 操作结果: 遍历B树T,对每个结点调用Visit函数 ShowBTree(T); 初始条件: B树T存在。 操作结果: 以凹入表形式显示B树T。 }ADTBTree 系统时间类型定义: ADTTime{ 数据对象: D={TM是各种整型类型的系统时间格式定义} 数据关系: 数据元素同属一个集合 基本操作: GetDate(tm&tim) 初始条件: 系统时间运行 操作结果: 获取系统时间,赋予tm变量tim AddDate(tm&date2,tmdate1,intday) 初始条件: 系统时间date2、date1、day存在 操作结果: 把date1的日期加day天后赋给date2 Earlier(tmdate1,tmdate2) 初始条件: 系统时间date2、date1存在 操作结果: 比较data1与date2日期的迟与早,如果date1早于或等于date2则返回TRUE,否则返回FALSE。 }ADTTime 图书管理类型定义: ADTBTree{ 数据对象: D={ai|ai∈BookType,i=1,2,3,……n,n>=0,其中 每个数据元素ai含有类型相同,可惟一标识数据元素的关键字} 数据关系: 数据元素同属一个集合 基本操作: InitLibrary(&L); 操作结果: 初始化书库L为空书库。 InsertBook(&L,B,result); 初始条件: 书库L和B已存在,result包含B书在书库中的位置或应该插入的位置。 操作结果: 如果书库中已存在B书,则只将B书的库存量增加,否则插入B书到书库L中。 DeleteBook(&L,&B); 初始条件: 书库L和B存在。 操作结果: 如果书库中存在B书,则从书库中删除B书的信息,并返回OK,否则返回ERROR BorrowBook(L,&B,R); 初始条件: 书库L存在,B书是书库中的书并且可被读者R借阅。 操作结果: 借出一本B书,记录信息。 ReturnBook(L,&B,R); 初始条件: 书库L存在。 操作结果: 若书库L中有读者R借阅B书的记录,则注销该记录,改变B书现存量,并返回OK,书不存在或无该读者记录则返回ERROR。 BespeakBook(L,&B,R); 初始条件: 书库L存在,B书是书库中的书,R为借阅者。 操作结果: 为读者R预约B书。 ListAuthor(L,author); 初始条件: 书库L存在,author为指定作者姓名 操作结果: 显示author的所有著作。 ShowBookinfo(L,B); 初始条件: 书L存在。 操作结果: 若书库L中存在书B,则显示B书基本信息并返回OK,否则返回ERROR。 PrintAllBooks(L); 初始条件: 书库L存在。 操作结果: 显示所有图书基本信息。 }ADTBTree 3.主程序 intmain() { 系统界面; 初始化; for(;;) { 显示菜单信息; 接受命令; 处理命令; 输出结果; } }| 3.2、详细设计及各函数说明 /**************************抽象数据类型B-树存储定义*************************/ typedefBookNodeRecord;//记录指针为图书结点类型 typedefstructBTNode{ intkeynum;//结点关键字个数 structBTNode*parent;//指向双亲指针 intkey[m+1];//关键字数组,0号单元未用 structBTNode*ptr[m+1];//指向子树指针 Record*recptr[m+1];//记录指针,0号单元未用 }BTNode,*BTree;//B树节点类型和B树类型 typedefstruct{ BTNode*pt;//指向找到的结点或应该插入的结点 inti;//1...m,在结点中关键字序号 inttag;//1表示查找成功,0表示查找失败 }Result;//B树查找结果类型 /****************************************************************************/ /**************************B-树操作定义************************************/ intSearch(BTreep,intk) /*在B树p中查找关键字k的位置i,使得p->node[i].key≤K<p->node[i+1].key*/ { inti; for(i=0;i returni; } ResultSearchBTree(BTreeT,intk) //在m阶B树T上查找关键字K,返回结果(pt,i,tag)。 若查找成功,则特征值 //tag=1,指针pt所指结点中第i个关键字等于K;否则特征值tag=0,等于K的 //关键字应插入在指针Pt所指结点中第i和第i+1个关键字之间。 { Resultr; inti=1; BTreep=T,q=NULL;//初始化,p指向待查结点,q指向p的双亲 intfound=FALSE; while(p&&! found){ i=Search(p,k);//在p->key[1...keynum]中查找 if(i&&p->key[i]==k)found=TRUE;//找到待查关键字 else { q=p; p=p->ptr[i]; } } if(found) { r.pt=p; r.i=i; r.tag=1; } else { r.pt=q; r.i=i; r.tag=0; } returnr; } voidInsert(BTree&q,inti,intk,BTreeap,Record*recptr) //将k和ap分别插入到q->key[i+1]和q->ptr[i+1],并插入关键字为k的记录recprt { for(intj=q->keynum;j>i;--j) {//记录、关键字、子树指针后移 q->key[j+1]=q->key[j]; q->ptr[j+1]=q->ptr[j]; q->recptr[j+1]=q->recptr[j]; } q->key[i+1]=k;//插入记录、关键字、子树指针,关键字个数加1 q->ptr[i+1]=ap; q->recptr[i+1]=recptr; q->keynum++; if(ap)ap->parent=q;//子树ap的父亲指针 } voidSplit(BTree&q,intn,BTree&ap) //以n为分界将结点q分裂为两个结点,前一半保留,后一半移入新生结点ap { inti; ap=(BTree)malloc(sizeof(BTNode));//申请新结点ap ap->ptr[0]=q->ptr[n]; for(i=n+1;i<=m;i++)//n后的关键字、子树指针、记录转移到ap { ap->key[i-n]=q->key[i]; ap->ptr[i-n]=q->ptr[i]; ap->recptr[i-n]=q->recptr[i]; } ap->keynum=q->keynum-n;//计算ap的关键字个数 q->keynum=n-1;//q的关键字个数减少 ap->parent=q->parent; for(i=0;i<=m-n;i++) if(ap->ptr[i])ap->ptr[i]->parent=ap;//ap的子树的父亲指针 } voidNewRoot(BTree&T,BTreep,intk,BTreeap,Record*recptr) //当插入B树时T为空或根结点分裂为p和ap两个节点,需建立一个根节点空间 //本函数为T申请一块空间,插入p,k,ap和记录rec { T=(BTree)malloc(sizeof(BTNode)); T->keynum=1; T->ptr[0]=p;//插入 T->ptr[1]=ap; T->key[1]=k; T->recptr[1]=recptr; if(p)p->parent=T;//T的子树ap的父亲指针 if(ap)ap->parent=T; T->parent=NULL;//根节点双亲为NULL } intInsertBTree(BTree&T,intk,BTreeq,inti,Record*recptr) //在m阶B树T上结点*q的key[i]与key[i+1]之间插入关键字K和记录rec。 //若引起结点过大,则沿双亲链进行必要的结点分裂调整,使T仍是m阶B树。 { BTreeap=NULL; intfinished=FALSE;//T是空树,生成仅含关键字K的根结点*T if(! q)NewRoot(T,NULL,k,NULL,recptr); else{ while(! finished) { Insert(q,i,k,ap,recptr);/将k和ap插入到q->key[i+1]和q->ptr[i+1] if(q->keynum else{ Split(q,(m+1)/2,ap);//分裂结点q k=q->key[(m+1)/2]; recptr=q->recptr[(m+1)/2]; if(q->parent) {//在双亲结点*q中查找k的插入位置 q=q->parent; i=Search(q,k); } elsefinished=OVERFLOW;//根节点已分裂为*q和*ap两个结点 } } if(finished==OVERFLOW)//根结点已分裂为结点*q和*ap NewRoot(T,q,k,ap,recptr);//需生成新根结点*T,q和ap为子树指针 } returnOK; } voidTakePlace(BTree&q,int&i) //*q结点的第i个关键字为k,用q的后继关键字替代q,且令q指向后继所在结点 { BTreep=q; q=q->ptr[i]; while(q->ptr[0])q=q->ptr[0];//查找p的后继 p->key[i]=q->key[1];//关键字代替 p->recptr[i]=q->recptr[1];//记录代替 i=1;//代替后应该删除q所指结点的第1个关键字 } voidDel(BTreeq,inti) //删除q所指结点第i个关键字及其记录 { for(;i { q->key[i]=q->key[i+1]; q->recptr[i]=q->recptr[i+1]; } q->keynum--;//关键字数目减1 } intBorrow(BTreeq) //若q的兄弟结点关键字大于(m-1)/2,则从兄弟结点上移最小(或最大)的关键字到双亲结点, //而将双亲结点中小于(或大于)且紧靠该关键字的关键字下移至q中,并返回OK,否则返回EREOR。 { inti; BTreep=q->parent,b;//p指向q的双亲结点 for(i=0;p->ptr[i]! =q;i++);//查找q在双亲p的子树位置 if(i>=0&&i+1<=p->keynum&&p->ptr[i+1]->keynum>(m-1)/2) {//若q的右兄弟关键字个数大于(m-1)/2 b=p->ptr[i+1];//b指向右兄弟结点 q->ptr[1]=b->ptr[0];//子树指针也要同步移动 q->key[1]=p->key[i+1];//从父节点借第i+1个关键字 q->recptr[1]=p->recptr[i+1]; p->key[i+1]=b->key[1];//b第一个关键字上移到父节点 p->recptr[i+1]=b->recptr[1]; for(i=1;i<=b->keynum;i++)//b第一个关键字上移,需把剩余记录前移一位 { b->key[i]=b->key[i+1]; b->recptr[i]=b->recptr[i+1]; b->ptr[i-1]=b->ptr[i]; } } elseif(i>0&&p->ptr[i-1]->keynum>(m-1)/2) {//若q的左兄弟关键字个数大约(m-1)/2 b=p->ptr[i-1];//b指向左兄弟结点 q->ptr[1]=q->ptr[0]; q->ptr[0]=b->ptr[b->keynum]; q->key[1]=p->key[i];//从父节点借第i个关键字 q->recptr[1]=p->recptr[i]; p->key[i]=b->key[b->keynum];//将b最后一个关键字上移到父节点 p->recptr[i]=b->recptr[b->keynum]; } elsereturnERROR;//无关键字大于(m-1)/2的兄弟 q->keynum++; b->keynum--; for(i=0;i<=q->keynum;i++) if(q->ptr[i])q->ptr[i]->parent=q;//刷新q的子结点的双亲指针 returnOK; } voidCombine(BTree&q) //将q剩余部分和q的父结点的相关关键字合并到q兄弟中,然后释放q,令q指向修改的兄弟 { inti,j; BTreep=q->parent,b;//p指向q的父亲 for(i=0;p->ptr[i]! =q;i++);//插好q在父亲p中的子树位置 if(i==0)//如为0,则需合并为兄弟的第一个关键字 { b=p->ptr[i+1]; for(j=b->keynum;j>=0;j--)//将b的关键字和记录后移一位 { b->key[j+1]=b->key[j]; b->recptr[j+1]=b->recptr[j]; b->ptr[j+1]=b->ptr[j]; } b->ptr[0]=q->ptr[0];//合并 b->key[1]=p->key[1]; b->recptr[1]=p->recptr[1]; } elseif(i>0)//若q在父亲的子树位置大约0 {//需合并为兄弟b的最后一个关键字 b=p->ptr[i-1]; b->key[b->keynum+1]=p->key[i];//合并 b->recptr[b->keynum+1]=p->recptr[i]; b->ptr[b->keynum+1]=q->ptr[0]; } if(i==0||i==1)//若i为0或1,需将父节点p关键字前移一位 for(;i { p->key[i]=p->key[i+1]; p->ptr[i]=p->ptr[i+1]; p->recptr[i]=p->recptr[i+1]; } p->keynum--; b->keynum++; free(q); q=b;//q指向修改的兄弟结点 for(i=0;i<=b->keynum;i++) if(b->ptr[i])b->ptr[i]->parent=b;//刷新b的子结点的双亲指针 } intDeleteBTree(BTree&T,intk) //在m阶B树T上删除关键字k及其对应记录,并返回OK。 //如T上不存在关键字k,则返回ERROR。 { intx=k; BTreeq,b=NULL; intfinished=FALSE,i=1; Resultres=SearchBTree(T,k);//在T中查找关键字k if(res.tag==0)returnER
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 管理 系统 实验 报告