版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、<p><b> 需求分析</b></p><p> 1. 圖書管理系統(tǒng)中圖書管理模塊包括圖書類型定義:書號(hào)、現(xiàn)存量、總存量,出版時(shí)間為整型,定價(jià)為浮點(diǎn)型,書名、著者名為字符型,借閱指針、預(yù)約指針為讀者類型;讀者類型定義:證號(hào)為整型、姓名為字符型,另外借閱類型和預(yù)約類型組合成其中的共用體類型。</p><p> B樹(2-3樹)類型定義:關(guān)鍵字個(gè)數(shù)和關(guān)
2、鍵字?jǐn)?shù)組為整型、另外還有指向雙親的指針、指向子樹的指針、記錄單元指針;B樹查找結(jié)果類型定義: 節(jié)點(diǎn)指針、關(guān)鍵字序號(hào)和查找標(biāo)志變量為整型。</p><p> 2. 演示程序以用戶和計(jì)算機(jī)的對(duì)話方式進(jìn)行,在計(jì)算機(jī)終端上顯示“提示信息”之后,由用戶在鍵盤上輸入演示程序中規(guī)定的運(yùn)算命令,相應(yīng)的輸入數(shù)據(jù)和運(yùn)算結(jié)果顯示在后面。該演示系統(tǒng),沒有使用文件,全部數(shù)據(jù)放在內(nèi)存存放。四項(xiàng)基本業(yè)務(wù)都以書號(hào)為關(guān)鍵字進(jìn)行的,采用了B樹(2
3、-3樹)對(duì)書號(hào)建立索引,以提高效率。</p><p> 圖書管理系統(tǒng)實(shí)現(xiàn)功能:</p><p> ?、俨删幦霂欤盒聲徣?,將書號(hào)、書名、著者、冊(cè)數(shù)、出版時(shí)間添加入圖書賬目中去,如果這種書在帳中已有,則只將總庫存量增加,每新增一個(gè)書號(hào)則以凹入表的形式顯示B樹現(xiàn)狀。</p><p> ?、谇宄龓齑妫?實(shí)現(xiàn)某本書的全部信息刪除操作 ,每清除一個(gè)書號(hào)則已以凹入表的形式顯示
4、B樹現(xiàn)狀。③圖書借閱: 如果書的庫存量大于零時(shí)則執(zhí)行出借,登記借閱者的圖書證號(hào)和姓名,系統(tǒng)自動(dòng)抓取當(dāng)前借閱時(shí)間和計(jì)算歸還時(shí)間。④圖書預(yù)約:如果某書庫存為零,則記錄預(yù)約者姓名和證號(hào),系統(tǒng)自動(dòng)抓取當(dāng)前預(yù)約時(shí)間和取書時(shí)間。</p><p> ?、輬D書歸還:注銷借閱者信息,并改變?cè)摃默F(xiàn)存量。⑥作者專區(qū):輸入作者名字,系統(tǒng)將查找相應(yīng)作者全部著作并顯示出來。</p><p> ?、邎D書信息:可
5、以根據(jù)書號(hào)查閱此書基本信息、借閱信息和預(yù)約信息,亦可以查找全部圖書基本信息。</p><p><b> 概要設(shè)計(jì)</b></p><p> 1.抽象數(shù)據(jù)類型B樹定義:</p><p> ADTBTree{</p><p> 數(shù)據(jù)對(duì)象:D是具有相同特性的數(shù)據(jù)元素的集合。各個(gè)數(shù)據(jù)元素均含有類型相同,可惟一標(biāo)識(shí)數(shù)據(jù)元
6、素的關(guān)鍵字。</p><p> 數(shù)據(jù)關(guān)系:數(shù)據(jù)元素同屬于一個(gè)集合并且:</p><p> 一棵m階的B樹,或?yàn)榭?,或?yàn)闈M足下列特性的m叉樹:</p><p> 樹中每個(gè)結(jié)點(diǎn)至多有m棵子樹;</p><p> 若根結(jié)點(diǎn)不是葉子結(jié)點(diǎn),則至少有兩棵子樹;</p><p> 除根之外的所有非終端結(jié)點(diǎn)至少有m/2(取上
7、限)棵子樹;</p><p> 所有的非終端結(jié)點(diǎn)包含下列信息數(shù)據(jù):</p><p> (n,A0,K1,A1,K2,A2,K3,……,Kn,An)</p><p> 其中:Ki(i=1,2,……n)為關(guān)鍵字,且Ki<Ki+1(i=1,2,……n-1);Ai(i=0,……n)為指向子樹根結(jié)點(diǎn)的指針,且指針Ai-1所指子樹中所有結(jié)點(diǎn)的關(guān)鍵字均小于Ki(i=1
8、,2,……n),An所指子樹中所有結(jié)點(diǎn)的關(guān)鍵字均大于Kn,n(m/2(取上限)-1<=n<=m-1)為關(guān)鍵字的個(gè)數(shù)</p><p><b> 基本操作:</b></p><p> SearchBTree(T ,key);</p><p> 初始條件:B樹T存在,key為和關(guān)鍵字類型相同的給定值。</p><
9、p> 操作結(jié)果:若T中存在關(guān)鍵字等于key的數(shù)據(jù)元素,則返回該元素的值或在表中的位置,否則返回“空”。</p><p> Insert(T, i, k, P, recptr)</p><p> 初始條件:B樹q和p存在,i、k是指定變量,recptr指針有效</p><p> 操作結(jié)果:將k和ap分別插入到q->key[i+1]和q->pt
10、r[i+1],并插入關(guān)鍵字為k的記錄recptr </p><p> InsertBTree(&T ,e);</p><p> 初始條件:B樹T存在,e為待插入的數(shù)據(jù)元素。</p><p> 操作結(jié)果:若T中步存在關(guān)鍵字等于e.key的數(shù)據(jù)元素,則插入e到T中。</p><p> DeleteBTree(&T ,key
11、);</p><p> 初始條件:B樹T存在,key為和關(guān)鍵字類型相同的給定值。</p><p> 操作結(jié)果:若T中存在其關(guān)鍵字等于key的數(shù)據(jù)元素,則刪除之</p><p> BTreeTraverse(BTree T,Visit)</p><p> 初始條件:B樹T存在,Visit是對(duì)T結(jié)點(diǎn)的函數(shù)</p><p
12、> 操作結(jié)果:遍歷B樹T,對(duì)每個(gè)結(jié)點(diǎn)調(diào)用Visit函數(shù)</p><p> ShowBTree( T );</p><p> 初始條件:B樹T存在。</p><p> 操作結(jié)果:以凹入表形式顯示B樹T。</p><p> }ADTBTree</p><p> 2 .系統(tǒng)時(shí)間類型定義:</p>
13、;<p><b> ADTTime{</b></p><p> 數(shù)據(jù)對(duì)象:D={TM 是各種整型類型的系統(tǒng)時(shí)間格式定義}</p><p> 數(shù)據(jù)關(guān)系:數(shù)據(jù)元素同屬一個(gè)集合</p><p><b> 基本操作:</b></p><p> GetDate(tm &tim
14、)</p><p> 初始條件:系統(tǒng)時(shí)間運(yùn)行</p><p> 操作結(jié)果:獲取系統(tǒng)時(shí)間,賦予tm變量tim</p><p> AddDate(tm &date2,tm date1, intday)</p><p> 初始條件:系統(tǒng)時(shí)間date2、date1、day存在</p><p> 操作結(jié)果:把
15、date1的日期加day天后賦給date2</p><p> Earlier(tm date1,tm date2)</p><p> 初始條件:系統(tǒng)時(shí)間date2、date1存在</p><p> 操作結(jié)果:比較data1與date2日期的遲與早,如果date1早于或等于date2則返回TRUE,否則返回FALSE。</p><p>
16、 }ADT Time</p><p> 3. 圖書管理類型定義:</p><p> ADTBTree{</p><p> 數(shù)據(jù)對(duì)象:D={ai | ai∈BookType,i=1,2,3,……n,n>=0,其中</p><p> 每個(gè)數(shù)據(jù)元素ai含有類型相同,可惟一標(biāo)識(shí)數(shù)據(jù)元素的關(guān)鍵字}</p><p&g
17、t; 數(shù)據(jù)關(guān)系:數(shù)據(jù)元素同屬一個(gè)集合</p><p><b> 基本操作:</b></p><p> InitLibrary(&L );</p><p> 操作結(jié)果:初始化書庫L為空書庫。</p><p> InsertBook(&L ,B ,result);</p><p&
18、gt; 初始條件:書庫L和B已存在,result包含B書在書庫中的位置或應(yīng)該插入的位置。</p><p> 操作結(jié)果:如果書庫中已存在B書,則只將B書的庫存量增加,否則插入B書到書庫L中。</p><p> DeleteBook(&L ,&B);</p><p> 初始條件:書庫L和B存在。</p><p> 操作結(jié)
19、果:如果書庫中存在B書,則從書庫中刪除B書的信息,并返回OK,否則返回ERROR</p><p> BorrowBook(L ,&B ,R);</p><p> 初始條件:書庫L存在,B書是書庫中的書并且可被讀者R借閱。</p><p> 操作結(jié)果:借出一本B書,記錄信息。</p><p> ReturnBook(L ,&am
20、p;B ,R);</p><p> 初始條件:書庫L存在。</p><p> 操作結(jié)果:若書庫L中有讀者R借閱B書的記錄,則注銷該記錄,改變B書現(xiàn)存量,并返回OK,書不存在或無該讀者記錄則返回ERROR。</p><p> BespeakBook(L ,&B ,R);</p><p> 初始條件:書庫L存在,B書是書庫中的書,
21、R為借閱者。</p><p> 操作結(jié)果:為讀者R預(yù)約B書。</p><p> ListAuthor(L ,author);</p><p> 初始條件:書庫L存在,author為指定作者姓名</p><p> 操作結(jié)果:顯示author的所有著作。</p><p> ShowBookinfo(L ,B );
22、</p><p> 初始條件:書L存在。</p><p> 操作結(jié)果:若書庫L中存在書B,則顯示B書基本信息并返回OK,否則返回ERROR。</p><p> PrintAllBooks(L );</p><p> 初始條件:書庫L存在。</p><p> 操作結(jié)果:顯示所有圖書基本信息。</p>
23、<p> }ADT BTree</p><p><b> 3. 主程序</b></p><p> int main()</p><p><b> {</b></p><p><b> 系統(tǒng)界面; </b></p><p>&l
24、t;b> 初始化;</b></p><p> for( ; ; )</p><p><b> {</b></p><p><b> 顯示菜單信息;</b></p><p><b> 接受命令;</b></p><p><
25、b> 處理命令;</b></p><p><b> 輸出結(jié)果;</b></p><p><b> }</b></p><p><b> }|</b></p><p> 本程序有四個(gè)調(diào)用模塊</p><p><b>
26、 主程序模塊</b></p><p><b> ↓</b></p><p><b> 圖書管理模塊</b></p><p><b> ↓ ↓</b></p><p> B樹單元模塊 系統(tǒng)時(shí)間模塊</p><p><b&
27、gt; 詳細(xì)設(shè)計(jì)</b></p><p> 《抽象數(shù)據(jù)類型B樹算法詳解》</p><p> /**************************抽象數(shù)據(jù)類型 B- 樹存儲(chǔ)定義*************************/</p><p> typedef BookNode Record;
28、 //記錄指針為圖書結(jié)點(diǎn)類型</p><p> typedef struct BTNode{</p><p> int keynum; //結(jié)點(diǎn)關(guān)鍵字個(gè)數(shù)</p><p> struct BTNode *parent; //指
29、向雙親指針</p><p> int key[m+1]; //關(guān)鍵字?jǐn)?shù)組,0號(hào)單元未用</p><p> struct BTNode *ptr[m+1]; //指向子樹指針</p><p> Record *recptr[m+1];
30、 //記錄指針,0號(hào)單元未用</p><p> }BTNode, *BTree; // B樹節(jié)點(diǎn)類型和B樹類型</p><p> typedef struct{</p><p> BTNode *pt;
31、 //指向找到的結(jié)點(diǎn)或應(yīng)該插入的結(jié)點(diǎn)</p><p> int i; //1...m,在結(jié)點(diǎn)中關(guān)鍵字序號(hào)</p><p> int tag; // 1表示查找成功,0表示查找失敗</p><p>
32、 }Result; // B樹查找結(jié)果類型</p><p> /****************************************************************************/</p><p> /**************************B- 樹操作定義*
33、***********************************/</p><p> int Search(BTree p, int k)</p><p> /* 在B樹p中查找關(guān)鍵字k的位置i,使得p->node[i].key≤K<p->node[i+1].key*/</p><p><b> {</b></p&
34、gt;<p><b> int i;</b></p><p> for(i=0;i<p->keynum && p->key[i+1]<=k;i++);</p><p><b> return i;</b></p><p><b> }</b>
35、;</p><p> ResultSearchBTree(BTree T, int k)</p><p> // 在m階B樹T上查找關(guān)鍵字K,返回結(jié)果(pt,i,tag)。若查找成功,則特征值</p><p> // tag=1,指針pt所指結(jié)點(diǎn)中第i個(gè)關(guān)鍵字等于K;否則特征值tag=0,等于K的</p><p> // 關(guān)鍵字應(yīng)插
36、入在指針Pt所指結(jié)點(diǎn)中第i和第i+1個(gè)關(guān)鍵字之間。</p><p><b> {</b></p><p><b> Result r;</b></p><p><b> int i=1;</b></p><p> BTree p=T,q=NULL;
37、 // 初始化,p指向待查結(jié)點(diǎn),q指向p的雙親</p><p> int found=FALSE;</p><p> while(p && !found){</p><p> i=Search( p, k); //在p->key[1...keynum]中查找</p>
38、<p> if(i && p->key[i]==k) found=TRUE; //找到待查關(guān)鍵字</p><p><b> else</b></p><p><b> {</b></p><p><b> q=p;</b></p>
39、<p> p=p->ptr[i];</p><p><b> }</b></p><p><b> }</b></p><p> if(found) </p><p><b> {</b></p><p><b>
40、; r.pt=p;</b></p><p><b> r.i=i;</b></p><p><b> r.tag=1;</b></p><p><b> }</b></p><p><b> else</b></p>&
41、lt;p><b> {</b></p><p><b> r.pt=q;</b></p><p><b> r.i=i;</b></p><p> r.tag=0; </p><p><b> }</b></p>&l
42、t;p> return r; </p><p><b> }</b></p><p> voidInsert(BTree &q, inti, int k, BTree ap, Record *recptr)</p><p> // 將k和ap分別插入到q->key[i+1]和q->ptr[i+1],并插入關(guān)
43、鍵字為k的記錄recprt</p><p><b> {</b></p><p> for(int j=q->keynum;j>i;--j)</p><p> { // 記錄、關(guān)鍵字、子樹指針后移</p><p> q-&
44、gt;key[j+1]=q->key[j];</p><p> q->ptr[j+1]=q->ptr[j];</p><p> q->recptr[j+1]=q->recptr[j];</p><p><b> }</b></p><p> q->key[i+1]=k;
45、 //插入記錄、關(guān)鍵字、子樹指針,關(guān)鍵字個(gè)數(shù)加1</p><p> q->ptr[i+1]=ap;</p><p> q->recptr[i+1]=recptr;</p><p> q->keynum++;</p><p> if(ap) ap->parent = q;
46、 //子樹ap的父親指針</p><p><b> }</b></p><p> voidSplit(BTree&q, int n, BTree &ap)</p><p> // 以n為分界將結(jié)點(diǎn)q分裂為兩個(gè)結(jié)點(diǎn),前一半保留,后一半移入新生結(jié)點(diǎn)ap</p><p
47、><b> {</b></p><p><b> inti;</b></p><p> ap = (BTree)malloc(sizeof(BTNode)); // 申請(qǐng)新結(jié)點(diǎn)ap</p><p> ap->ptr[0]=q->ptr[n]; </p>
48、<p> for(i = n+1;i <= m; i++) // n后的關(guān)鍵字、子樹指針、記錄轉(zhuǎn)移到ap</p><p><b> {</b></p><p> ap->key[i-n] = q->key[i];</p><p> ap->ptr[i-n] = q->ptr[i];&
49、lt;/p><p> ap->recptr[i-n] = q->recptr[i];</p><p><b> }</b></p><p> ap->keynum = q->keynum - n; // 計(jì)算ap的關(guān)鍵字個(gè)數(shù)</p><p> q->keynum = n-1
50、; // q的關(guān)鍵字個(gè)數(shù)減少</p><p> ap->parent = q->parent;</p><p> for (i=0; i<=m-n; i++) </p><p> if(ap->ptr[i]) ap->ptr[i]->parent = ap; /
51、/ ap的子樹的父親指針</p><p><b> }</b></p><p> void NewRoot(BTree &T, BTree p, int k, BTree ap,Record *recptr)</p><p> // 當(dāng)插入B樹時(shí)T為空或根結(jié)點(diǎn)分裂為p和ap兩個(gè)節(jié)點(diǎn),需建立一個(gè)根節(jié)點(diǎn)空間</p>&l
52、t;p> // 本函數(shù)為T申請(qǐng)一塊空間,插入p,k,ap和記錄rec</p><p><b> {</b></p><p> T = (BTree)malloc(sizeof(BTNode));</p><p> T->keynum = 1;</p><p> T->ptr[0]
53、= p; // 插入</p><p> T->ptr[1] = ap; </p><p> T->key[1] = k;</p><p> T->recptr[1] = recptr;</p><p> if (p) p->parent= T; // T
54、的子樹ap的父親指針</p><p> if (ap) ap->parent = T;</p><p> T->parent = NULL; // 根節(jié)點(diǎn)雙親為NULL</p><p><b> }</b></p><p> int InsertBTree(BTree &T,
55、 int k, BTree q, int i,Record *recptr) </p><p> // 在m階B樹T上結(jié)點(diǎn)*q的key[i]與key[i+1]之間插入關(guān)鍵字K和記錄rec。</p><p> // 若引起結(jié)點(diǎn)過大,則沿雙親鏈進(jìn)行必要的結(jié)點(diǎn)分裂調(diào)整,使T仍是m階B樹。</p><p><b> {</b></p&g
56、t;<p> BTree ap = NULL;</p><p> int finished = FALSE; // T是空樹,生成僅含關(guān)鍵字K的根結(jié)點(diǎn)*T</p><p> if (!q) NewRoot(T, NULL, k, NULL,recptr);</p><p><b> else{&l
57、t;/b></p><p> while (!finished) </p><p><b> {</b></p><p> Insert(q, i, k, ap,recptr);/將k和ap插入到q->key[i+1]和q->ptr[i+1]</p><p> if (q->keyn
58、um < m) finished = TRUE; // 插入完成</p><p><b> else{</b></p><p> Split(q, (m+1)/2, ap); // 分裂結(jié)點(diǎn)q</p><p> k = q->key[(m+1)/2];</p&
59、gt;<p> recptr = q->recptr[(m+1)/2];</p><p> if (q->parent) </p><p> { // 在雙親結(jié)點(diǎn)*q中查找k的插入位置</p><p> q = q->parent; </p><p> i = Search(q, k);
60、 </p><p><b> } </b></p><p> else finished = OVERFLOW; // 根節(jié)點(diǎn)已分裂為*q和*ap兩個(gè)結(jié)點(diǎn)</p><p><b> } </b></p><p><b> } </b></p>&
61、lt;p> if (finished == OVERFLOW)// 根結(jié)點(diǎn)已分裂為結(jié)點(diǎn)*q和*ap</p><p> NewRoot(T, q, k, ap,recptr);// 需生成新根結(jié)點(diǎn)*T,q和ap為子樹指針</p><p><b> }</b></p><p> return OK;</p>
62、<p><b> }</b></p><p> voidTakePlace(BTree &q, int &i)</p><p> // *q結(jié)點(diǎn)的第i個(gè)關(guān)鍵字為k,用q的后繼關(guān)鍵字替代q,且令q指向后繼所在結(jié)點(diǎn)</p><p><b> {</b></p><p&g
63、t; BTree p = q;</p><p> q = q->ptr[i];</p><p> while(q->ptr[0]) q = q->ptr[0]; // 查找p的后繼</p><p> p->key[i] = q->key[1]; // 關(guān)鍵字代替</p>
64、<p> p->recptr[i] = q->recptr[1]; // 記錄代替</p><p> i = 1;// 代替后應(yīng)該刪除q所指結(jié)點(diǎn)的第1個(gè)關(guān)鍵字</p><p><b> }</b></p><p> voidDel(BTree q, int i)</p
65、><p> // 刪除q所指結(jié)點(diǎn)第i個(gè)關(guān)鍵字及其記錄</p><p><b> {</b></p><p> for(;i < q->keynum ;i++)// 關(guān)鍵字和記錄指針前移</p><p><b> {</b></p><p> q-&
66、gt;key[i] = q->key[i+1];</p><p> q->recptr[i] = q->recptr[i+1];</p><p><b> }</b></p><p> q->keynum --;// 關(guān)鍵字?jǐn)?shù)目減1</p><p><b> }&
67、lt;/b></p><p> intBorrow(BTree q)</p><p> // 若q的兄弟結(jié)點(diǎn)關(guān)鍵字大于(m-1)/2,則從兄弟結(jié)點(diǎn)上移最?。ɑ蜃畲螅┑年P(guān)鍵字到雙親結(jié)點(diǎn),</p><p> // 而將雙親結(jié)點(diǎn)中小于(或大于)且緊靠該關(guān)鍵字的關(guān)鍵字下移至q中,并返回OK,否則返回EREOR。</p><p><
68、b> {</b></p><p><b> inti;</b></p><p> BTreep = q->parent, b;// p指向q的雙親結(jié)點(diǎn)</p><p> for(i = 0 ; p->ptr[i] != q;i++) ; // 查找q在雙親p的子樹位置</p&g
69、t;<p> if(i >= 0 && i+1 <= p->keynum && p->ptr[i+1]->keynum > (m-1)/2)</p><p> {// 若q的右兄弟關(guān)鍵字個(gè)數(shù)大于(m-1)/2</p><p> b = p->ptr[i+1];// b
70、指向右兄弟結(jié)點(diǎn)</p><p> q->ptr[1] = b->ptr[0];// 子樹指針也要同步移動(dòng)</p><p> q->key[1] = p->key[i+1];// 從父節(jié)點(diǎn)借第i+1個(gè)關(guān)鍵字</p><p> q->recptr[1] = p->recptr[i+1];</p>
71、<p> p->key[i+1] = b->key[1];// b第一個(gè)關(guān)鍵字上移到父節(jié)點(diǎn)</p><p> p->recptr[i+1] = b->recptr[1];</p><p> for(i =1 ;i <= b->keynum;i++)// b第一個(gè)關(guān)鍵字上移,需把剩余記錄前移一位</p><p&
72、gt;<b> {</b></p><p> b->key[i] = b->key[i+1];</p><p> b->recptr[i] = b->recptr[i+1];</p><p> b->ptr[i-1] = b->ptr[i];</p><p><b>
73、 }</b></p><p><b> }</b></p><p> else if(i > 0 && p->ptr[i-1]->keynum > (m-1)/2)</p><p> {// 若q的左兄弟關(guān)鍵字個(gè)數(shù)大約(m-1)/2</p><p
74、> b = p->ptr[i-1];// b指向左兄弟結(jié)點(diǎn)</p><p> q->ptr[1] = q->ptr[0];</p><p> q->ptr[0] = b->ptr[b->keynum];</p><p> q->key[1] = p->key[i];// 從父節(jié)
75、點(diǎn)借第i個(gè)關(guān)鍵字</p><p> q->recptr[1] = p->recptr[i];</p><p> p->key[i] = b->key[b->keynum];// 將b最后一個(gè)關(guān)鍵字上移到父節(jié)點(diǎn)</p><p> p->recptr[i] = b->recptr[b->keynum];<
76、/p><p><b> }</b></p><p> else return ERROR;// 無關(guān)鍵字大于(m-1)/2的兄弟</p><p> q->keynum ++;</p><p> b->keynum --;</p><p> for(i = 0 ;i
77、<=q->keynum; i++)</p><p> if(q->ptr[i]) q->ptr[i]->parent = q; // 刷新q的子結(jié)點(diǎn)的雙親指針</p><p> return OK;</p><p><b> }</b></p><p> void
78、Combine(BTree &q)</p><p> // 將q剩余部分和q的父結(jié)點(diǎn)的相關(guān)關(guān)鍵字合并到q兄弟中,然后釋放q,令q指向修改的兄弟</p><p><b> {</b></p><p> inti, j ;</p><p> BTree p = q->parent, b;
79、// p指向q的父親</p><p> for(i = 0; p->ptr[i] != q; i++) ;// 插好q在父親p中的子樹位置</p><p> if(i == 0)// 如為0,則需合并為兄弟的第一個(gè)關(guān)鍵字</p><p><b> {</b></p><p> b =
80、p->ptr[i+1];</p><p> for(j = b->keynum ; j >= 0 ;j--)// 將b的關(guān)鍵字和記錄后移一位</p><p><b> {</b></p><p> b->key[j+1] = b->key[j];</p><p> b->r
81、ecptr[j+1] = b->recptr[j];</p><p> b->ptr[j+1] = b->ptr[j];</p><p><b> }</b></p><p> b->ptr[0] = q->ptr[0]; // 合并</p><p>
82、b->key[1] = p->key[1];</p><p> b->recptr[1] = p->recptr[1];</p><p><b> }</b></p><p> else if(i > 0)// 若q在父親的子樹位置大約0</p><p> {
83、// 需合并為兄弟b的最后一個(gè)關(guān)鍵字</p><p> b = p->ptr[i-1];</p><p> b->key[b->keynum+1] = p->key[i]; // 合并</p><p> b->recptr[b->keynum+1] = p->recptr[i];&l
84、t;/p><p> b->ptr[b->keynum+1] = q->ptr[0];</p><p><b> }</b></p><p> if(i == 0 || i == 1)// 若i為0或1,需將父節(jié)點(diǎn)p關(guān)鍵字前移一位</p><p> for( ; i < p->k
85、eynum; i++)</p><p><b> {</b></p><p> p->key[i] = p->key[i+1];</p><p> p->ptr[i] = p->ptr[i+1];</p><p> p->recptr[i] = p->recptr[i+1];&
86、lt;/p><p><b> }</b></p><p> p->keynum --;</p><p> b->keynum ++;</p><p><b> free(q);</b></p><p> q = b;// q指向修改的兄弟
87、結(jié)點(diǎn)</p><p> for(i = 0;i <= b->keynum; i++)</p><p> if(b->ptr[i]) b->ptr[i]->parent = b; // 刷新b的子結(jié)點(diǎn)的雙親指針</p><p><b> }</b></p><p> i
88、ntDeleteBTree(BTree &T,int k)</p><p> // 在m階B樹T上刪除關(guān)鍵字k及其對(duì)應(yīng)記錄,并返回OK。</p><p> // 如T上不存在關(guān)鍵字k,則返回ERROR。</p><p><b> {</b></p><p><b> intx=k;</
89、b></p><p> BTreeq,b = NULL;</p><p> intfinished = FALSE,i = 1;</p><p> Result res = SearchBTree(T,k);// 在T中查找關(guān)鍵字k</p><p> if(res.tag == 0 ) return ERROR;
90、// 未搜索到</p><p><b> else</b></p><p><b> {</b></p><p> q = res.pt;// q指向待刪結(jié)點(diǎn)</p><p> i = res.i;</p><p> if(q->pt
91、r[0]) TakePlace(q, i); // 若q的子樹不空,(非底層結(jié)點(diǎn))</p><p> // 則以其后繼代之,且令q指向后繼所在結(jié)點(diǎn)</p><p> Del(q,i);// 刪除q所指向結(jié)點(diǎn)中第i個(gè)關(guān)鍵字及記錄</p><p> if(q->keynum>=(m-1)/2||!q->parent)//
92、 若刪除后關(guān)鍵字個(gè)數(shù)不小于(m-1)/2或q是根 </p><p><b> {</b></p><p> finished = TRUE;// 刪除完成</p><p> if(q->keynum == 0 ) T = NULL;// 若q的關(guān)鍵字個(gè)數(shù)為0
93、 ,則為空樹</p><p><b> }</b></p><p> while(!finished)</p><p><b> {</b></p><p> if(Borrow(q))finished = TRUE;// 若q的相鄰兄弟結(jié)點(diǎn)關(guān)鍵字大于(m-1)/2,則
94、 </p><p> //從該兄弟結(jié)點(diǎn)上移一個(gè)最大(或最?。╆P(guān)鍵字到</p><p> // 父節(jié)點(diǎn),從父節(jié)點(diǎn)借一關(guān)鍵字到q</p><p> else{// 若q相鄰兄弟關(guān)鍵字個(gè)數(shù)均等于┌m /2┑-1</p><p> Combine(q);// 將q中的剩余部分和雙親中的相關(guān)關(guān)鍵字合并至q的一個(gè)兄弟中<
95、/p><p> q = q->parent;// 檢查雙親</p><p> if(q == T && T->keynum ==0 )// 若被刪結(jié)點(diǎn)的父節(jié)點(diǎn)是根T且T的關(guān)鍵字個(gè)數(shù)為0</p><p><b> {</b></p><p> T = T->ptr[0];
96、// 新根</p><p> T->parent = NULL;</p><p> free(q);// 刪除原雙親結(jié)點(diǎn)</p><p> finished = TRUE;</p><p><b> }</b></p><p> else if(q-&g
97、t;keynum >= m/2) finished = TRUE;</p><p> }// 合并后雙親關(guān)鍵字個(gè)數(shù)不少于(m-1)/2,完成</p><p><b> }</b></p><p><b> }</b></p><p> return OK ;</p>
98、;<p><b> }</b></p><p> voidBTreeTraverse(BTree T,void ( *Visit)(BTree p))</p><p> // 遍歷B樹T,對(duì)每個(gè)結(jié)點(diǎn)調(diào)用Visit函數(shù)</p><p><b> {</b></p><p>
99、if(!T) return;</p><p><b> Visit(T);</b></p><p> for(int i=0;i<=T->keynum;++i)</p><p> if(T->ptr[i])BTreeTraverse(T->ptr[i],Visit);</p><p><
100、;b> }</b></p><p> voidShowBTree(BTree T,short x = 8)</p><p> // 遞歸以凹入表形式顯示B樹T,每層的縮進(jìn)量為x,初始縮進(jìn)量為8</p><p><b> {</b></p><p> if(!T)return ;</
101、p><p><b> inti;</b></p><p> printf("\n");</p><p> for(i = 0;i<=x;i++) putchar(' '); // 縮進(jìn)x</p><p> for(i = 1 ;i <= T->
102、keynum;i++)</p><p> printf("%d,",T->key[i]);</p><p> for(i = 0 ;i <= T->keynum;i++)// 遞歸顯示子樹結(jié)點(diǎn)關(guān)鍵字</p><p> ShowBTree(T->ptr[i],x+7);</p><p&
103、gt;<b> } </b></p><p> /****************************圖書管理存儲(chǔ)定義*******************************/</p><p> typedefstructReaderNode // 借閱者</p><p><b> {
104、 </b></p><p> intcardnum; // 證號(hào)</p><p> charrname[MAX_NAME_LEN]; // 姓名</p><p><b> union{</b></p><p> struct{
105、</p><p> tmbordate; // 借書日期</p><p> tmretdate; // 還書日期</p><p><b> };</b></p><p><b> };</b></p><p>
106、 }ReaderNode,*ReaderType; // 讀者類型</p><p> typedefstructBookNode// 圖書結(jié)點(diǎn)</p><p><b> {</b></p><p> intbooknum;// 書號(hào)</p><p>
107、 charbookname[MAX_BKNAME_LEN];// 書名</p><p> charwriter[MAX_NAME_LEN]; // 作者名</p><p> intcurrent; // 現(xiàn)存量</p><p> int total;
108、 // 總庫存</p><p> ReaderTypereader;// 借閱者鏈表指針</p><p> } BookNode,*BookType;// 圖書類型</p><p> /*************************************************************
109、****************/</p><p> /*****************************圖書管理函數(shù)定義********************************/ </p><p> voidInitLibrary(BTree &L )</p><p> // 初始化書庫L為空書庫。</p><p
110、><b> {</b></p><p><b> L = NULL;</b></p><p><b> }</b></p><p> voidInsertBook(BTree &L ,BookType B , Result res)</p><p>
111、// 書庫L已存在,res包含B書在書庫L中的位置或應(yīng)該插入的位置</p><p> // 如果書庫中已存在B書,則只將B書的庫存量增加,否則插入B書到書庫L中。</p><p><b> {</b></p><p> if(res.tag==0) InsertBTree(L, B->booknum, res.pt, res.i,
112、B); // 書庫中不存在該書,則插入</p><p><b> else</b></p><p><b> {</b></p><p> BookType b=res.pt->recptr[res.i];</p><p> b->current=b->current+B-
113、>total; //現(xiàn)存量增加</p><p> b->total=b->total+B->total; //總庫存增加</p><p><b> }</b></p><p><b> }</b&g
114、t;</p><p> intDeleteBook(BTree &L ,BookType B)</p><p> // 如果書庫中存在B書,則從書庫中刪除B書的信息,并返回OK,否則返回ERROR</p><p><b> {</b></p><p> if(DeleteBTree(L,B->bo
115、oknum)) return OK; //刪除成功</p><p> else return ERROR; //刪除失敗 </p><p><b> }</b></p><p> intCanBorrow(BTree L,BookType B
116、 ,ReaderType R)</p><p> // 書庫L中存在B書。若B書現(xiàn)存量大于0,則可出借返回TRUE</p><p> // 不能出借返回FALSE。</p><p><b> {</b></p><p> if(B->current>0) return TRUE;
117、 //現(xiàn)存量大于零 else return FALSE; //其他情況均不允許出借</p><p><b> }</b></p><p> voidBorrowBook(BTree L ,BookType B ,
118、ReaderType R)</p><p> // 書庫L存在,B書是書庫中的書并且可被讀者借閱</p><p> // 借出一本B書,登記借閱者基本信息。</p><p><b> {</b></p><p> ReaderType r,pre;</p><p> GetDate(R
119、->bordate); // 獲取系統(tǒng)當(dāng)前時(shí)間為借書時(shí)間日期</p><p> AddDate(R->retdate,R->bordate,KEEP_DAYS); //當(dāng)前時(shí)間加上90天為還書日期</p><p> if(!B->reader)B->reader=R; //暫無借
120、閱者,直接登記</p><p><b> else</b></p><p><b> {</b></p><p> for(pre=r=B->reader;r;pre=r,r=r->nextr);</p><p> pre->nextr=R;
121、 //登記至借閱者表尾</p><p><b> }</b></p><p> B->current--;</p><p><b> }</b></p><p> int ReturnBook(BTree L ,int booknum ,int
122、cardnum,BookType &B ,ReaderType &R)</p><p> // booknum為還書書號(hào),cardnum為還書者借閱證號(hào),</p><p> // 若書庫中不存在書號(hào)為booknum的書,則搜索出錯(cuò),返回-1</p><p> // 若有借閱記錄,則注銷該記錄,并用B和R返回圖書信息和借閱者信息并返回1,<
123、/p><p> // 若沒有r、借閱的記錄,則用B返回圖書信息,并返回0</p><p><b> {</b></p><p> Result res=SearchBTree(L,booknum); //在B樹按書號(hào)搜索</p><p> if(res.tag==0) return -1;
124、 </p><p> B = res.pt->recptr[res.i];// 用B記錄圖書信息</p><p> ReaderTypep=res.pt->recptr[res.i]->reader,pre=p;</p><p> while(p){ // 搜索借書者鏈
125、表</p><p> if(pre==p&&p->cardnum == cardnum)//只有一個(gè)借書者</p><p><b> {</b></p><p><b> R = p;</b></p><p> B->current++;
126、 // 現(xiàn)存量增1</p><p><b> return 1;</b></p><p><b> }</b></p><p> if(p->cardnum==cardnum) //多個(gè)借書者</p><p><b> { &l
127、t;/b></p><p><b> R = p;</b></p><p> pre ->nextr = p->nextr;</p><p> B->current++; // 現(xiàn)存量增1</p><p><b> return 1;</b><
128、;/p><p><b> }</b></p><p><b> pre=p;</b></p><p> p=p->nextr;</p><p><b> }</b></p><p><b> return 0;</b>&
129、lt;/p><p><b> }</b></p><p> void PrintH() //表格頭部格式</p><p><b> {</b></p><p> printf("\n"
130、;);</p><p> printf("║********************圖書基本信息****************************║\n");</p><p> printf("║ 書號(hào) │ 書名 │ 著者 │現(xiàn)存│總庫存│出版年份│定價(jià) ║\n"); </p><p><b>
131、 }</b></p><p> void PrintD(BookType B) //顯示B書基本信息</p><p><b> {</b></p><p> printf("║───┼────┼────┼──┼───┼────┼───║\n&q
132、uot;);</p><p> printf("║ %-4d │ %-20s│ %-11s│%-4d│ %-4d │%-6d │%-6.1f║",B->booknum,B->bookname,B->writer,B->current,B->total,B->publishyear,B->price);</p><p>&l
133、t;b> }</b></p><p> void PrintT() //表格底部格式</p><p><b> {</b></p><p> printf("\n║───┼─────┼───┼──┼───┼───
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 《數(shù)據(jù)結(jié)構(gòu)》課程設(shè)計(jì)---圖書管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)--圖書管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)---圖書管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)-圖書管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)-圖書管理
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)--圖書管理
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告——圖書管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)圖書管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告圖書管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)圖書管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告--學(xué)院圖書管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)——圖書管理信息系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)圖書管理系統(tǒng)實(shí)驗(yàn)報(bào)告
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告---- 圖書管理系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
- 數(shù)據(jù)結(jié)構(gòu)-圖書管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)--圖書借閱管理系統(tǒng)
- 圖書管理系統(tǒng)(含源代碼)c語言_數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)----用c++語言實(shí)現(xiàn)圖書管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)--圖書館管理系統(tǒng)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)--小型圖書購銷管理系統(tǒng)
評(píng)論
0/150
提交評(píng)論