《數(shù)據(jù)結(jié)構(gòu)題集》答案 第9章 查找
《《數(shù)據(jù)結(jié)構(gòu)題集》答案 第9章 查找》由會員分享,可在線閱讀,更多相關(guān)《《數(shù)據(jù)結(jié)構(gòu)題集》答案 第9章 查找(21頁珍藏版)》請?jiān)谘b配圖網(wǎng)上搜索。
1、第九章查找
9.25
int Search_Sq(SSTable ST,int key)//在有序表上順序查找的算法,監(jiān)視哨設(shè)在高下
標(biāo)端
{
ST.elem[ST.length+1].key=key;
for(i=1;ST.elem[i].key>key;i++);
if(i>ST.lengthllST.elem[i].key 2、e(SSTable ST,int key,int low,int high)//折 半查找的遞歸算 法
{
if(low>high) return 0; 〃查找不到時返回 0
mid=(low+high)/2;
if(ST.elem[mid].key==key) return mid;
else if(ST.elem[mid].key>key)
return Search_Bin_Recursive(ST,key,low,mid-1);
else return Search_Bin_Recursive(ST,key,mid+1,high);
}
}//Search_Bin_R 3、ecursive
9.27 int Locate_Bin(SSTable ST,int key)//折半查找,返回小于或等于待查元素的最后一
個結(jié)點(diǎn)號
{
int *r;
r=ST.elem;
if(keyvrA.key) return 0;
else if(key>=r[ST.length].key) return ST.length;
low=1;high=ST.length;
while(lowv=high) {
mid=(low+high)/2;
if(key>=r[mid].key&&keyvr[mid+1].key) 〃查找結(jié)束的條件 return mid;
4、
else if(key 5、t; //索引順序表類型
int Search_IdxSeq(IdxSqList L,int key)//分塊查找,用折半查找法確定記錄所在塊, 塊內(nèi)采用順序查找法
{
if(key>L.idx[L.blknum].maxkey) return ERROR; //超 過最大元素
low=1;high=L.blknum;
found=0;
while(low<=high&&!found) //折半查找記錄所在塊號mid
{
mid=(low+high)/2;
if(key<=L.idx[mid].maxkey&&key>L.idx[mid-1].maxkey)
found=1 6、;
else if(key>L.idx[mid].maxkey)
low=mid+1;
else high=mid-1;
}
i=L.idx[mid].firstloc; //塊的下界
j=i+blksize-1; //塊的上界
temp=L.elem[i-1]; //保存相鄰元素
L.elem[i-1]=key; //設(shè)置監(jiān)視哨
for(k=j;L.elem[k]!=key;k--); //順序查找
L.elem[i-1]=temp; //恢復(fù)元素
if(k
7、在塊內(nèi)進(jìn)行順序查找時,如果需要設(shè)置監(jiān)視哨,則必須先保存相鄰塊的相鄰 元素,以免數(shù)據(jù)丟失.
9.29
typedef struct {
LNode *h; //h指向最小元素
LNode *t; //t指向上次查找的結(jié)點(diǎn)
} CSList;
LNode *Search_CSList(CSList &L,int key)//在有序單循環(huán)鏈表存儲結(jié)構(gòu)上的查找 算法,假定每次查找都成功
{
if(L.t->data==key) return L.t;
else if(L.t->data>key)
for(p=L.h,i=1;p->data!=key;p=p->next,i++);
8、
else
for(p=L.t,i=L.tpos;p->data!=key;p=p->next,i++);
L.t=p;//更新t指針
return p;
}//Search_CSList
分析:由于題目中假定每次查找都是成功的,所以本算法中沒有關(guān)于查找失敗的處 理.由微積分可得,在等概率情況下,平均查找長度約為n/3.
9.30
typedef struct {
DLNode *pre;
int data;
DLNode *next;
} DLNode;
typedef struct {
DLNode *sp;
int length;
} DSList; //供 9、查找的雙向循環(huán)鏈表類型
DLNode *Search_DSList(DSList &L,int key)//在有序雙向循環(huán)鏈表存儲結(jié)構(gòu)上的
查找算法,假定每次查找都成功
{
p=L.sp;
if(p->data>key)
{
while(p->data>key) p=p->pre;
L.sp=p;
}
else if(p->data 10、=0,flag=1;
int Is_BSTree(Bitree T)//判斷二叉樹T是否二叉排序樹,是則返回1,否則返回0
{
if(T->lchild&&flag) Is_BSTree(T->lchild);
if(T->data 11、的最大元素和大
于x的最小元素
{
if(T->lchild) MaxLT_MinGT(T->lchild,x); 〃本算法仍是借助中序遍歷來實(shí)現(xiàn)
if(last 12、Tree T,int x)//從大到小輸出二叉排序樹T中所有不小于x的元
素
{
if(T->rchild) Print_NLT(T->rchild,x);
if(T->data 13、Delete_NLT(T->rchild,x);
if(T->data 14、d; //找到最小元素
while(p&&p->datadata>a) printf("%d\n",p->data); //輸出符合條件的元素
if(p->rtag) p=p->rtag;
else
{
p=p->rchild;
while(!p->ltag) p=p->lchild;
} 〃轉(zhuǎn)到中序后繼
}//while
}//Print_Between
9.36
void BSTree_Insert_Key(BiThrTree &T,int x)//在后繼線索二叉排序樹 T 中插入元 素x
{
if(T->data 15、
{
if(T->rtag) //T沒有右子樹時,作為右孩子插入
{
p=T->rchild;
q=(BiThrNode*)malloc(sizeof(BiThrNode));
q->data=x;
T->rchild=q;T->rtag=0;
q->rtag=1;q->rchild=p; //修改原線索
}
else BSTree_Insert_Key(T->rchild,x);//T 有右子樹時,插入右子樹中
}//if
else if(T->data>x) //插入到左子樹中
{
if(!T->lchild) //T沒有左子樹時,作為左孩子插入
{
q=( 16、BiThrNode*)malloc(sizeof(BiThrNode));
q->data=x;
T->lchild=q;
q->rtag=1;q->rchild=T; //修改自身的線索
}
else BSTree_Insert_Key(T->lchild,x);//T 有左子樹時,插入左子樹中
}//if
}//BSTree_Insert_Key
9.37
Status BSTree_Delete_key(BiThrTree &T,int x)//在后繼線索二叉排序樹 T 中刪除 元素x
{
BTNode *pre,*ptr,*suc;//ptr為x所在結(jié)點(diǎn),pre和 17、suc分別指向ptr的前驅(qū)和后繼
p=T;last=NULL; //last始終指向當(dāng)前結(jié)點(diǎn)p的前一個(前驅(qū))
while(!p->ltag) p=p->lchild; //找到中序起始元素
while(p)
{
if(p->data==x) //找到了元素x結(jié)點(diǎn)
{
pre=last;
ptr=p;
}
else if(last&&last->data==x) suc=p; //找到了 x 的后繼
if(p->rtag) p=p->rtag;
else
{
p=p->rchild;
while(!p->ltag) p=p->lchild;
} 〃轉(zhuǎn)到中序后繼
18、
last=p;
}//while //借助中序遍歷找到元素x及其前驅(qū)和后繼結(jié)點(diǎn)
if(!ptr) return ERROR; //未找到待刪結(jié)點(diǎn)
Delete_BSTree(ptr); //刪除 x 結(jié)點(diǎn)
if(pre&&pre->rtag)
pre->rchild=suc; //修改線索
return OK;
}//BSTree_Delete_key
void Delete_BSTree(BiThrTree &T)//課本上給出的刪除二叉排序樹的子樹T的算 法,按照線索二叉樹的結(jié)構(gòu)作了一些改動
{
q=T;
if(!T->ltag&&T->rtag) //結(jié)點(diǎn)無右子樹 19、,此時只需重接其左子樹
T=T->lchild;
else if(T->ltag&&!T->rtag) 〃結(jié)點(diǎn)無左子樹,此時只需重接其右子樹
T=T->rchild;
else if(!T->ltag&&!T->rtag) 〃結(jié)點(diǎn)既有左子樹又有右子樹
{
p=T;r=T->lchild;
while(!r->rtag)
{
s=r;
r=r->rchild; //找到結(jié)點(diǎn)的前驅(qū)r和r的雙親s
}
T->data=r->data; //用 r 代替 T 結(jié)點(diǎn)
if(s!=T)
s->rchild=r->lchild;
else s->lchild=r->lchild 20、; //重接r的左子樹到其雙親結(jié)點(diǎn)上
q=r;
}//else
free(q); //刪除結(jié)點(diǎn)
}//Delete_BSTree
分析:本算法采用了先求出x結(jié)點(diǎn)的前驅(qū)和后繼,再刪除x結(jié)點(diǎn)的辦法,這樣修改線 索時會比較簡單,直接讓前驅(qū)的線索指向后繼就行了 .如果試圖在刪除x結(jié)點(diǎn)的同 時修改線索,則問題反而復(fù)雜化了.
9.38
void BSTree_Merge(BiTree &T,BiTree &S)//把二叉排序樹 S 合并到 T 中
{
if(S->lchild) BSTree_Merge(T,S->lchild);
if(S->rchild) BSTree_Merge( 21、T,S->rchild); //合并子樹
Insert_Key(T,S); //插入元素
}//BSTree_Merge
void Insert_Node(Bitree &T,BTNode *S)//把樹結(jié)點(diǎn)S插入到T的合適位置上
{
if(S->data>T->data)
{
if(!T->rchild) T->rchild=S;
else Insert_Node(T->rchild,S);
}
else if(S->data 22、
}
S->lchild=NULL; //插入的新結(jié)點(diǎn)必須和原來的左右子樹斷絕關(guān)系
S->rchild=NULL; //否則會導(dǎo)致樹結(jié)構(gòu)的混亂
}//Insert_Node
分析:這是一個與課本上不同的插入算法.在合并過程中,并不釋放或新建任何結(jié) 點(diǎn),而是采取修改指針的方式來完成合并.這樣,就必須按照后序序列把一棵樹中 的元素逐個連接到另一棵樹上,否則將會導(dǎo)致樹的結(jié)構(gòu)的混亂.
9.39
void BSTree_Split(BiTree &T,BiTree &A,BiTree &B,int x)//把 二叉排序樹 T 分裂為 兩棵二叉排序樹A和B,其中A的元素全部小于等于x,B的元素 23、全部大于x
{
if(T->lchild) BSTree_Split(T->lchild,A,B,x);
if(T->rchild) BSTree_Split(T->rchild,A,B,x); //分裂左右子樹
if(T->data<=x) Insert_Node(A,T);
else Insert_Node(B,T); //將元素結(jié)點(diǎn)插入合適的樹中
}//BSTree_Split
void Insert_Node(Bitree &T,BTNode *S)//把樹結(jié)點(diǎn)S插入到T的合適位置上
{
if(!T) T=S; //考慮到剛開始分裂時樹A和樹B為空的情況
else 24、if(S->data>T->data) //其余部分與上一題同
{
if(!T->rchild) T->rchild=S;
else Insert_Node(T->rchild,S);
}
else if(S->data 25、ize域表示該結(jié)點(diǎn)的左子樹的結(jié)點(diǎn)總數(shù)加1
BlcNode *lchild,*rchild;
} BlcNode,*BlcTree; //含lsize域的平衡二叉排序樹類型
BTNode *Locate_BlcTree(BlcTree T,int k)//在含 lsize 域的平衡二叉排序樹 T 中確 定第k小的結(jié)點(diǎn)孑指針
{
if(!T) return NULL; //k小于1或大于樹結(jié)點(diǎn)總數(shù)
if(T->lsize==k) return T; //就是這個結(jié)點(diǎn)
else if(T->lsize>k)
return Locate_BlcTree(T->lchild,k); // 26、在左子樹中尋找
else return Locate_BlcTree(T->rchild,k-T->lsize); //在右子樹中尋找,注意要修改 k 的值
}//Locate_BlcTree
9.41
typedef struct {
enum {LEAF,BRANCH} tag; // 結(jié)點(diǎn)類型標(biāo)識
int keynum;
BPLink parent; //雙親指針
int key[MAXCHILD]; //關(guān)鍵字
union {
BPLink child[MAXCHILD];//非 葉結(jié)點(diǎn)的孩子指針 struct {
rectype *info[MAXCHILD]; 27、//葉子結(jié)點(diǎn)的信息指針
BPNode *next; //指向下一個葉子結(jié)點(diǎn)的鏈接
} leaf;
}
} BPNode,*BPLink,*BPTree;//B+樹及其結(jié)點(diǎn)類型
Status BPTree_Search(BPTree T,int key,BPNode *ptr,int pos)//B+樹中按關(guān)鍵字隨 機(jī)查找的算法,返回包含關(guān)鍵字的葉子結(jié)點(diǎn)的指針ptr以及關(guān)鍵字在葉子結(jié)點(diǎn)中 的位置pos
{
p=T;
while(p.tag==BRANCH) //沿分支向下查找
{
for(i=0;i 28、所在子樹
if(i==p->keynum) return ERROR; 〃關(guān)鍵字太大 p=p->child[i];
}
for(i=0;i 29、四章
{
q=(TrieNode*)malloc(sizeof(TrieNode));
q->kind=LEAF;
q->lf.k=key; //建葉子結(jié)點(diǎn)
klen=key[0];
p=T;i=1;
while(p&&i<=klen&&p->bh.ptr[ord(key[i])])
{
last=p;
p=p->bh.ptr[ord(key[i])];
i++;
}//自上而下查找
if(p->kind==BRANCH) //如果最后落到分支結(jié)點(diǎn)(無同義詞):
{
p->bh.ptr[ord(key[i])]=q; //直接連上葉子 p->bh.num++;
30、}
else //如果最后落到葉子結(jié)點(diǎn)(有同義詞):
{
r=(TrieNode*)malloc(sizeof(TrieNode)); //建立新的分支結(jié)點(diǎn)
last->bh.ptr[ord(key[i-1])]=r; //用新分支結(jié)點(diǎn)取代老葉子結(jié)點(diǎn)和上一層的聯(lián)系
r->kind=BRANCH;r->bh.num=2;
r->bh.ptr[ord(key[i])]=q;
r->bh.ptr[ord(p->lf.k[i])]=p; //新分支結(jié)點(diǎn)與新老兩個葉子結(jié)點(diǎn)相連
}
}//TrieTree_Insert_Key
分析:當(dāng)自上而下的查找結(jié)束時,存在兩種情況.一種情況,樹中 31、沒有待插入關(guān)鍵字
的同義詞,此時只要新建一個葉子結(jié)點(diǎn)并連到分支結(jié)點(diǎn)上即可.另一種情況,有同 義詞,此時要把同義詞的葉子結(jié)點(diǎn)與樹斷開,在斷開的部位新建一個下一層的分支 結(jié)點(diǎn),再把同義詞和新關(guān)鍵字的葉子結(jié)點(diǎn)連到新分支結(jié)點(diǎn)的下一層.
9.43
Status TrieTree_Delete_Key(TrieTree &T,StringType key)//在 Trie 樹 T 中刪除字符 串key
{
p=T;i=1;
while(p&&p->kind=BRANCH&&iv=key[0]) 〃查找待刪除元素
{
last=p;
p=p->bh.ptr[ord(key[i])];
i 32、++;
}
if(p&&p->kind==LEAF&&p->lf.k=key) //找到了待刪除元素
{
last->bh.ptr[ord(key[i-1])]=NULL;
free(p);
return OK;
}
else return ERROR; //沒找到待刪除元素
}//TrieTree_Delete_Key
9.44
void Print_Hash(HashTable印//按第一個字母順序輸出Hash表中的所有關(guān)鍵字,
其中處理沖突采用線性探測開放定址法
{
for(i=1;iv=26;i++)
for(j=i;H.elem[j].key;j=(j+ 33、1)%hashsize[sizeindex]) 〃線性探測 if(H(H.elem[j].key)==i) printf("%s\n",H.elem[j]);
}//Print_Hash
int H(char *s)//求 Hash 函數(shù)
{
if(s) return s[0]-96; //求關(guān)鍵字第一個字母的字母序號(小寫)
else return 0;
}//H
9.45
typedef *LNode[MAXSIZE] CHashTable; 〃鏈地址 Hash 表類型
Status Build_Hash(CHashTable &T,int m/輸入一組關(guān)鍵字,建立 Ha 34、sh 表,表長為 m用鏈地址法處理沖突.
{
if(m<1) return ERROR;
T=malloc(m*sizeof(WORD)); // 建立表頭指針向量
for(i=0;i 35、->next;p=p->next);
p->next=q; //插入鏈表尾部.本算法不考慮排序問題.
}
}//while
return OK;
}//Build_Hash
9.46
Status Locate_Hash(HashTable H,int row,int col,KeyType key,int &k)//根 據(jù)行列值
在Hash表表示的稀疏矩陣中確定元素key的位置k
{
h=2*(100*(row/10)+col/10); //作者設(shè)計的 Hash 函數(shù)
while(H.elem[h].key&&!EQ(H.elem[h].key,key))
h=(h+ 36、1)%20000;
if(EQ(H.elem[h].key,key)) k=h;
else k=NULL;
}//Locate_Hash
分析:本算法所使用的Hash表長20000,裝填因子為50%,Hash函數(shù)為行數(shù)前兩位 和列數(shù)前兩位所組成的四位數(shù)再乘以二,用線性探測法處理沖突.當(dāng)矩陣的元素是 隨機(jī)分布時,查找的時間復(fù)雜度為0(1).
另解:
第九章查找
習(xí)題及答案
題號:1 2 3 4 5 6 7 8 9 10 11 12 13 14
19 20 21 22 23 一、基礎(chǔ)知識題
1. 對含有n個互不相同元素的集合,同時找最大元和最小元至少需進(jìn)行多少次比較
答:我們 37、可以設(shè)立兩個變量max和min用于存放最大元和最小元的位置,第一次取兩個元素進(jìn)行比較,大的放而ax,小的放入min,從第2次 開始,每次取一個元素先和max比較,如果大于max則以它替換max,并結(jié)束本次比較;若小于nax則再與min相比較,在最好的情況下,一路比 較下去都不用和min相比較,所以這種情況下,至少要進(jìn)行V1次比較就能找到最大元和最小元。(順便說一下,最壞情況下,要進(jìn)行!n-3次比較
才能得到結(jié)果)
2. 若對具有n個元素的有序的順序表和無序的順序表分別進(jìn)行順序查找,試在下述兩種情況下分別討論兩者在等概率時的平均查找長度)查找
不成功,即表中無關(guān)鍵字等于給定值:的記錄;(2 38、)查找成功,即表中有關(guān)鍵字等于給定值的記錄。
答:查找不成功時,需進(jìn)行n+1次比較才能確定查找失敗。因此平均查找長度為+1,這時有序表和無序表是一樣的。
查找成功時,平均查找長度為n+1)/2,有序表和無序表也是一樣的。因?yàn)轫樞虿檎覍Ρ淼脑夹蛄械挠行蛐圆桓信d趣。
3. 畫出對長度為18的有序的順序表進(jìn)行二分查找的判定樹,并指出在等概率時查找成功的平均查找長度,以及查找失敗時所需的最多的關(guān)鍵字比
較次數(shù)。
答:請看題圖。
等概率情況下,查找成功的平均查找長度為:
ASL=(1+2*2+3*4+4*8+5*3)/18=3.556
也可以用公式代,大約為:ASL=(18+1)lg( 39、18+1)/18-1=3.346
查找失敗時,最多的關(guān)鍵字比較次樹不超過判定樹的深度,此處為■如圖:
4. 為什么有序的單鏈表不能進(jìn)行折半查找
答:因?yàn)殒湵頍o法進(jìn)行隨機(jī)訪問,如果要訪問鏈表的中間結(jié)點(diǎn)就必須先從頭結(jié)點(diǎn)開始進(jìn)行依次訪問,這就要浪費(fèi)很多時間還不如進(jìn)行順序查找,
而且,用鏈存儲結(jié)構(gòu)將無法判定二分的過程是否結(jié)束,因此無法用鏈表實(shí)現(xiàn)二分查找。
5. 設(shè)有序表為(a,b,c,e,f,g,i,j,k,p,q),請分別畫出對給定值b,g和n進(jìn)行折半查找的過程。
解:b的查找過程如下 (其中括號表示當(dāng)前查找區(qū)間,圓括號表示當(dāng)前比較的關(guān)鍵字
下標(biāo): 1 2 3 4 5 6 7 8 9 40、10 11 12 13
第一次比較:[a b c d e f (g) h i j k p q]
第二次比較:[a b (c)d e f] g h i j k p q
第三次比較:[a(b)]c d e f g h i j k p q
經(jīng)過三次比較,查找成功。
g的查找過程如下:
[a b c d e f (g) h i j k p q]
一次比較成功。
n的查找過程如下:
下標(biāo): 1 2 3 4 5 6 7 8 9 10 11 12 13
第一次比較: [a b c d e f (g) h i j k p q]
第二次比較: a b c d e f g [h i (j) 41、k p q]
第三次比較:a b c d e f g h i j [k (p) q]
第四次比較:a b c d e f g h i j [k] p q]
經(jīng)過四次比較,查找失敗。
6. 將(for, case, while, class, protected, virtual, public,
private, do, template, const ,if,
int)中的關(guān)鍵字依次插入初態(tài)為空的二叉排序樹中,請畫出所得到的楸然后畫出刪去for之后的二叉排序樹T',若再將for
插入T'中得到的二叉排序樹T''是否與T相同?最后給出T”的先序、中序和后序序列。
答:見題圖:
42、
T”的先序序列是:do case class const while protected private if
for int virtual public template
T”的中序序列是: case class const do for if int private
protected public template virtual while
T”的后序序列是:const class case for int if private template
public virtual protected while do
二叉排序樹T如下圖:
刪去for后的二叉排序樹如下圖: 43、圈內(nèi)的for表示再插入后的結(jié)點(diǎn):
7. 對給定的關(guān)鍵字集合,以不同的次序插入初始為空的樹中,是否有可能得到同一棵二叉排序■樹
答:有可能。如有兩個序列:3, 1,2, 4和3, 4, 1,2,它們插入空樹所得的二叉排序樹是相同的。
8. 將二叉排序樹T的先序序列中的關(guān)鍵字依次插入一空樹中,所得和二叉排序樹與T"是否相同?為什么?
答:這兩棵二叉樹完全相同。
9. 設(shè)二叉排序樹中關(guān)鍵字由1至1000的整數(shù)構(gòu)成,現(xiàn)要查找關(guān)鍵字為63的結(jié)點(diǎn),下述關(guān)鍵字序列哪一個不可能是在二叉排序樹上查找到的序列
(a) 2,252, 401,398,330, 344, 397,363;
(b) 924 44、, 220, 911, 244, 898, 258, 362, 363;
(c) 925, 202, 911, 240, 912, 245, 363;
(d) 2, 399, 387, 219, 266, 382, 381, 278, 363.
答:(c)是不可能查找到的序列。我們可以把這四個序列各插入到一個初始為空的二叉排序樹中,結(jié)果可以發(fā)現(xiàn)c)序列所形成的不是一條路徑,
而是有分支的,可見它是不可能在查找過程中訪問到的序列。
10. 設(shè)二叉排序樹中關(guān)鍵字互不相同,則其中最小元必?zé)o左孩子,最大元必?zé)o右孩子。此命題是否正最小元和最大元一定是葉子嗎一個新結(jié)點(diǎn)
總是插在二叉排序樹的某葉 45、子上嗎
答:此命題正確。假設(shè)最小元有左孩子,則根據(jù)二叉排序樹性質(zhì),此左孩子應(yīng)比最小元更小,如此一來就產(chǎn)生矛盾了此最小元不可能有左孩子, 對于最大元也是這個道理。
但最大元和最小元不一定是葉子,它也可以是根、內(nèi)部結(jié)點(diǎn)分支結(jié)點(diǎn))等,這得根據(jù)插入結(jié)點(diǎn)時的次序而定。如,1,2, 4
這個集合,根據(jù)不同的插入次序可以得到不同的二叉排序樹:
/ \
O1 04
\
02
02
/ \
O1 03
\
04
04
\
03
\
02
\
01
02
/ \
01 04
/
03
新結(jié)點(diǎn)總是插入在二叉排序樹的某個葉子上的。
11. 在一棵m階的B-樹中,當(dāng)將 46、一關(guān)鍵字插入某結(jié)點(diǎn)而引起該結(jié)點(diǎn)的分裂時此結(jié)點(diǎn)原有多少個關(guān)鍵字若刪去某結(jié)點(diǎn)中的一個關(guān)鍵字,而導(dǎo)致結(jié)點(diǎn)
合并時,該結(jié)點(diǎn)中原有幾個關(guān)鍵字
答:在此樹中,若由于一關(guān)鍵字的插入某結(jié)點(diǎn)而引起該結(jié)點(diǎn)的分裂時,則該結(jié)點(diǎn)原有1個關(guān)鍵字。
若刪去某結(jié)點(diǎn)中一個關(guān)鍵字而導(dǎo)致結(jié)點(diǎn)合并時,該結(jié)點(diǎn)中原有rm/2-il個關(guān)鍵字。
12. 在一棵B-樹中,空指針數(shù)總是比關(guān)鍵字?jǐn)?shù)多一個,此說法是否正礴問包含8個關(guān)鍵字的3階B-樹(即2-3樹)最多有幾個結(jié)點(diǎn)?最少有幾個結(jié)
點(diǎn)?畫出這兩種情況的B-樹。
答:這個說法是正確的。
包含8個關(guān)鍵字的3階B-樹最多有7個結(jié)點(diǎn),最少有4個結(jié)點(diǎn)。
見題圖。:圖如下:
13. 47、從空樹開始,依次輸入20,30,50,52,60,68, 70,畫出建立2-3樹的過程。并畫出刪除50和68后的B-樹狀態(tài)。
答:過程如下:
(1) 插入20,30: (2)插入50:
(3)插入52: (4)插入60:
(5)插入68: (6)插入70:
(7)刪去50: (8)刪去68
14。畫出依次插入z,v,o,p,w,y到圖9.12(h)所示的5階B-樹的過程。
答:如圖:第一步,插入z:
第二、三步,插入v,o:
第四五六步,插入p,w,y:
15. 在含有n個關(guān)鍵字的m階B-樹中進(jìn)行查找,至多讀盤多少次完全平衡的二叉排序樹的讀盤次數(shù)大約比它大多少倍
答:在含 48、有n個關(guān)鍵字的m階B-樹中進(jìn)行查找至多讀盤次數(shù)不超過5-樹高h(yuǎn),即logt((n+1)/2)+1
,(注,此處t為底,值是除根外的每個內(nèi)部結(jié)點(diǎn)的最小度數(shù)「m/2r).
完全平衡的二叉樹高為lgn,所以它的讀盤次數(shù)至多也是lgn,它與上述B-樹的讀盤次數(shù)的比值約為lgt倍(此處底是2).
16. 為什么在內(nèi)存中使用的3-樹通常是3階的,而不使用更高階的3-樹?
答:因?yàn)椴檎业炔僮鞯腸pu時間在B-樹上是O(lgn?(m/lgt)),而m/lgt>1,所以m較大時它所費(fèi)時間比平衡的二叉排序樹上相應(yīng)操作時間大得多因
此,僅在內(nèi)存中使用的B-樹通常取最小值3.
17. 為什么二叉排序樹長高 49、時,新結(jié)點(diǎn)總是一個葉子,而-樹長高時,新結(jié)點(diǎn)總是根哪一種長高能保證樹平衡
答:因?yàn)樵诙媾判驑渲?,關(guān)鍵字總是作為一個葉子結(jié)點(diǎn)插入以原來的樹中,所以當(dāng)樹增高時新結(jié)點(diǎn)總是一個葉子;而B-樹中關(guān)鍵字插入總是插
入到葉子結(jié)點(diǎn)內(nèi)部,在葉結(jié)點(diǎn)中的關(guān)鍵字?jǐn)?shù)目尚未超過它能夠容納的數(shù)目之前是不會增加結(jié)點(diǎn)的,當(dāng)關(guān)鍵字?jǐn)?shù)超過結(jié)點(diǎn)可容納的數(shù)目時,葉結(jié)點(diǎn)就
會發(fā)生分裂,產(chǎn)生一個新結(jié)點(diǎn)但不一定引起樹增高,并且將其中的中間結(jié)點(diǎn)傳至上一層,只有當(dāng)這種分裂操作傳遞至根結(jié)點(diǎn)并引起根結(jié)點(diǎn)的分裂
時,才能引起樹高增加,此時產(chǎn)生一個新的根結(jié)點(diǎn)。所以說樹長高時,新結(jié)點(diǎn)總是根。
顯然,后一種長高總能保證樹的平衡。
18. 已知 50、關(guān)鍵字序列為(PAL,LAP,PAM,MAP,PAT,PET,SET,SAT,TAT,BATM為它們設(shè)計一個散列函數(shù),將其映射到區(qū)畫..n-1]上,要求碰撞盡可能的
少。這里 n=11,13,17,19.
解:我的設(shè)計的散列函數(shù)是這樣的,把關(guān)鍵字串中的每一個字符按其所在位置分別將其CII值乘以一個不同的數(shù),然后把這些值相加的和去對
求余,余數(shù)即為散列表中的位置。函數(shù)如下:
int Hash (char key[])
{
return (int)(key[0]+key[1]*0.618+key[2]*10)%n;
我們可以設(shè)計一個程序來看看用這個散列函數(shù)得到的所有關(guān)鍵字映射到區(qū)間的 51、位置:
#include 52、
//以上用一個二維數(shù)組來存放關(guān)鍵字序列
int i;
for(i=0; i<10;i++)
{
printf('%d ”,Hash(3);
}
}
19. 對于一組給定的、固定不變的關(guān)鍵字序列,有可能設(shè)計出無沖突的散列,函數(shù)時稱H為完備的散列函數(shù)perfect
hashing function,)若H能無沖突地將關(guān)鍵字完全填滿散列表,貝H是最小完備minimal
perfect)的散列函數(shù)。通常找完備的散列函數(shù)非常困難,找最小完備的散列函數(shù)就更困難。請問:
(1)若h是已知關(guān)鍵字集合的完備的散列函數(shù),若要增加一個新的關(guān)鍵字到集合一般情況下!還是完備的嗎
(2) 已知關(guān)鍵 53、字集合為81,129, 301,38, 434, 216, 412, 487, 234),散列函數(shù)為i(x) = (x+18)/63請問H是完備的嗎它是最小完備的嗎
(3) 考慮由字符串構(gòu)成的關(guān)鍵字集合ret,Jane,Shirley,Bryce,Michelle,Heather試為散列表0..6]設(shè)計一個完備的散列函數(shù)。提示:考慮每
個字符串的第3個字符,即s[2])
答:⑴
一般情況下H不是完備的,如果說插入一個新的關(guān)鍵字它還是完備的,那么再插入一個不是永遠(yuǎn)是完備的散列函數(shù)了
所以一般情況下它不能總是完備的,只有一些很少的情況下它還可能是完備的。
⑵這個H是完備的,其函數(shù)值依次 54、為:2, 5, 0, 7, 3, 6, 8, 4。如果散列表詢=9時,它就是最小完備的。
(3)這個函數(shù)如下:
int Hash (char key[])
{ return key[2]%7;}
20. 設(shè)散列函數(shù)為i(key)=key%101解決沖突的方法為線性探查,表中用”表示空單元。若刪去散列度中的304即令HT[1]=-1)之后,在表1T 中查找707將會發(fā)生什么若將刪去的表項(xiàng)標(biāo)記為2”,查找時探查到2繼續(xù)向前搜索,探查到時終止搜索。請問用這種方法刪4后能否正確 地查找到707?
0123 100
HT |202 |304 |507 |707 | ... ... |
答: 55、查找707時,首先根據(jù)散列函數(shù)計算得出該元素應(yīng)在散列表中單元,但是在)單元沒有找到,因此將向下一單元探查,結(jié)果發(fā)現(xiàn)該單元是 -1(為空單元,所以結(jié)束查找,這將導(dǎo)致07無法找到。
如果改用'-2"作為刪除標(biāo)記,則可以正確找到7所在的結(jié)點(diǎn)。
21. 設(shè)散列表長度為1,散列函數(shù)!(x)=x%11,給定的關(guān)鍵字序列為1,13, 13, 34, 38, 33, 27, 22,試畫出分別用拉鏈法和線性探查法解決沖突 時所構(gòu)造的散列表,并求出在等概率情況下,這兩咱方法查找成功和失敗時的平均查找長度。請問裝填因子的值是什么
答:拉鏈法如下圖:(后面的框框就不畫了
T[0..10]
0| — 33 — 56、 22 A
1| |— 1 — 12 —34 A
2| |— 13 A
3| A |
4| A |
5| |— 38 — 27 A
6| A |
7| A |
8| A |
10| A I
線性探查法如下圖:
下標(biāo) 0 1 2 3 4 5 6 7 8 9 10
T[0..10]|33|1 |13|12|34|38|27|22 || | |
探查次數(shù)1 1 1 3 4 1 7 8
用拉鏈法的查找成功平均查找長度為:
ASLscuu=(1*4+2*3+3*1)/8=1.625
查找失敗時平均查找長度為:
ASLunsucc=(2+3+1+0+0+0+2+0+0+0 57、+0)/11=0.73
用線性探查法查找成功時平均查找長度為:
ASLsucc=(1+1+1+3+4+1+7+8)/8=3.25
查找失敗時平均查找長度為:
ASLunsucc=(9+8+7+6+5+4+3+2+1+1+1)/11=4.3
裝填因子a拉鏈=4/11=0.36 a線性探查=8/11=0.73
22 .假定有k個關(guān)鍵字互為同義詞,若用線性探查法把這些同義詞存入散列表中,至少要進(jìn)行多少次探查
答:至少要進(jìn)行1+2+3...+k-1+次探查。
也就是說,在散列表的一連串連續(xù)空間內(nèi),第一個關(guān)鍵字只需探查一次,第二個就2要探查如此這般,第個關(guān)鍵字就要探查次才能找到位
置存放。所以至少要把它們?nèi)悠饋聿艍颉?
23.為什么說當(dāng)裝填因子非常接近時,線性探查類似于順序查?為什么說當(dāng)裝填因子比較小比如a =0.7左右)時,散列查找的平均查找時間為
。⑴?
答:當(dāng)a非常接近1時,整個散列表幾乎被裝滿。由于線性探查法在關(guān)鍵字同義時解決沖突的辦法是線性地向后查找,當(dāng)整個表幾乎裝滿時,它 就很類似于順序查找了。
當(dāng)a比較小時,關(guān)鍵字碰撞的幾率比較小,一般情況下只要按照散列函數(shù)計算出的結(jié)果能性就找到相應(yīng)結(jié)點(diǎn),因此它的平均查找時間接近 于1.
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024《增值稅法》全文學(xué)習(xí)解讀(規(guī)范增值稅的征收和繳納保護(hù)納稅人的合法權(quán)益)
- 2024《文物保護(hù)法》全文解讀學(xué)習(xí)(加強(qiáng)對文物的保護(hù)促進(jìn)科學(xué)研究工作)
- 銷售技巧培訓(xùn)課件:接近客戶的套路總結(jié)
- 20種成交的銷售話術(shù)和技巧
- 銷售技巧:接近客戶的8種套路
- 銷售套路總結(jié)
- 房產(chǎn)銷售中的常見問題及解決方法
- 銷售技巧:值得默念的成交話術(shù)
- 銷售資料:讓人舒服的35種說話方式
- 汽車銷售績效管理規(guī)范
- 銷售技巧培訓(xùn)課件:絕對成交的銷售話術(shù)
- 頂尖銷售技巧總結(jié)
- 銷售技巧:電話營銷十大定律
- 銷售逼單最好的二十三種技巧
- 銷售最常遇到的10大麻煩