数据结构课程设计图书管理系统Word文档格式.docx
《数据结构课程设计图书管理系统Word文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计图书管理系统Word文档格式.docx(32页珍藏版)》请在冰豆网上搜索。
![数据结构课程设计图书管理系统Word文档格式.docx](https://file1.bdocx.com/fileroot1/2022-11/23/d6be8d40-8a62-49f9-bc60-b9419f3bc38e/d6be8d40-8a62-49f9-bc60-b9419f3bc38e1.gif)
初始条件:
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);
若T中存在其关键字等于key的数据元素,则删除之
BTreeTraverse(BTreeT,Visit)
B树T存在,Visit是对T结点的函数
遍历B树T,对每个结点调用Visit函数
ShowBTree(T);
B树T存在。
以凹入表形式显示B树T。
}ADTBTree
2.系统时间类型定义:
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
3.图书管理类型定义:
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,&
书库L存在。
若书库L中有读者R借阅B书的记录,则注销该记录,改变B书现存量,并返回OK,书不存在或无该读者记录则返回ERROR。
BespeakBook(L,&
书库L存在,B书是书库中的书,R为借阅者。
为读者R预约B书。
ListAuthor(L,author);
书库L存在,author为指定作者姓名
显示author的所有著作。
ShowBookinfo(L,B);
书L存在。
若书库L中存在书B,则显示B书基本信息并返回OK,否则返回ERROR。
PrintAllBooks(L);
显示所有图书基本信息。
}ADTBTree
3.主程序
intmain()
{
系统界面;
初始化;
for(;
;
)
{
显示菜单信息;
接受命令;
处理命令;
输出结果;
}
}|
4.本程序有四个调用模块
主程序模块
↓
图书管理模块
↓↓
B树单元模块系统时间模块
三、详细设计
《抽象数据类型B树算法详解》
/**************************抽象数据类型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*/
for(i=0;
i<
p->
keynum&
&
p->
key[i+1]<
=k;
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&
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.tag=0;
}
returnr;
voidInsert(BTree&
q,inti,intk,BTreeap,Record*recptr)
//将k和ap分别插入到q->
ptr[i+1],并插入关键字为k的记录recprt
for(intj=q->
keynum;
j>
i;
--j)
{//记录、关键字、子树指针后移
q->
key[j+1]=q->
key[j];
ptr[j+1]=q->
ptr[j];
recptr[j+1]=q->
recptr[j];
q->
key[i+1]=k;
//插入记录、关键字、子树指针,关键字个数加1
ptr[i+1]=ap;
recptr[i+1]=recptr;
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];
ptr[i-n]=q->
recptr[i-n]=q->
recptr[i];
keynum=q->
keynum-n;
//计算ap的关键字个数
keynum=n-1;
//q的关键字个数减少
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;
ptr[0]=p;
//插入
ptr[1]=ap;
key[1]=k;
recptr[1]=recptr;
if(p)p->
parent=T;
//T的子树ap的父亲指针
if(ap)ap->
parent=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->
ptr[i+1]
if(q->
keynum<
m)finished=TRUE;
//插入完成
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->
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->
while(q->
ptr[0])q=q->
ptr[0];
//查找p的后继
key[i]=q->
key[1];
//关键字代替
recptr[i]=q->
recptr[1];
//记录代替
i=1;
//代替后应该删除q所指结点的第1个关键字
voidDel(BTreeq,inti)
//删除q所指结点第i个关键字及其记录
for(;
keynum;
i++)//关键字和记录指针前移
key[i+1];
recptr[i+1];
keynum--;
//关键字数目减1
intBorrow(BTreeq)
//若q的兄弟结点关键字大于(m-1)/2,则从兄弟结点上移最小(或最大)的关键字到双亲结点,
//而将双亲结点中小于(或大于)且紧靠该关键字的关键字下移至q中,并返回OK,否则返回EREOR。
BTreep=q->
parent,b;
//p指向q的双亲结点
for(i=0;
ptr[i]!
=q;
i++);
//查找q在双亲p的子树位置
if(i>
=0&
i+1<
=p->
ptr[i+1]->
keynum>
(m-1)/2)
{//若q的右兄弟关键字个数大于(m-1)/2
b=p->
ptr[i+1];
//b指向右兄弟结点
ptr[1]=b->
//子树指针也要同步移动
key[1]=p->
//从父节点借第i+1个关键字
recptr[1]=p->
p->
key[i+1]=b->
//b第一个关键字上移到父节点
recptr[i+1]=b->
for(i=1;
=b->
i++)//b第一个关键字上移,需把剩余记录前移一位
b->
key[i]=b->
recptr[i]=b->
ptr[i-1]=b->
elseif(i>
0&
ptr[i-1]->
{//若q的左兄弟关键字个数大约(m-1)/2
ptr[i-1];
//b指向左兄弟结点
ptr[1]=q->
ptr[0]=b->
ptr[b->
keynum];
//从父节点借第i个关键字
key[b->
//将b最后一个关键字上移到父节点
recptr[b->
elsereturnERROR;
//无关键字大于(m-1)/2的兄弟
keynum++;
b->
=q->
i++)
if(q->
ptr[i])q->
//刷新q的子结点的双亲指针
voidCombine(BTree&
q)
//将q剩余部分和q的父结点的相关关键字合并到q兄弟中,然后释放q,令q指向修改的兄弟
inti,j;
//p指向q的父亲
for(i=0;
i++);
//插好q在父亲p中的子树位置
if(i==0)//如为0,则需合并为兄弟的第一个关键字
for(j=b->
j>
=0;
j--)//将b的关键字和记录后移一位
key[j+1]=b->
recptr[j+1]=b->
ptr[j+1]=b->
}
b->
ptr[0]=q->
//合并
0)//若q在父亲的子树位置大约0
{//需合并为兄弟b的最后一个关键字
keynum+1]=p->
//合并
keynum+1]=q->
if(i==0||i==1)//若i为0或1,需将父节点p关键字前移一位
i<
key[i]=p->
ptr[i]=p->
recptr[i]=p->
free(q);
q=b;
//q指向修改的兄弟结点
if(b->
ptr[i])b->
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)returnERROR;
//未搜索到
q=res.pt;
//q指向待删结点
i=res.i;
ptr[0])TakePlace(q,i);
//若q的子树不空,(非底层结点)
//则以其后继代之,且令q指向后继所在结点
Del(q,i);
//删除q所指向结点中第i个关键字及记录
keynum>
=(m-1)/2||!
q->
parent)//若删除后关键字个数不小于(m-1)/2或q是根
finished=TRUE;
//删除完成
if(q->
keynum==0)