第八章2索引与散列.docx
《第八章2索引与散列.docx》由会员分享,可在线阅读,更多相关《第八章2索引与散列.docx(21页珍藏版)》请在冰豆网上搜索。
第八章2索引与散列
第8章索引与散列
10-1什么是静态索引结构?
什么是动态索引结构?
它们各有哪些优缺点?
【解答】
静态索引结构指这种索引结构在初始创建,数据装入时就已经定型,而且在整个系统运行期间,树的结构不发生转变,只是数据在更新。
动态索引结构是指在整个系统运行期间,树的结构随数据的增删及时调整,以维持最佳的搜索效率。
静态索引结构的长处是结构定型,成立方式简单,存取方便;缺点是无益于更新,插入或删除时效率低。
动态索引结构的长处是在插入或删除时能够自动调整索引树结构,以维持最佳的搜索效率;缺点是实现算法复杂。
10-2设有10000个记录对象,通过度块划分为若干子表并成立索引,那么为了提高搜索效率,每一个子表的大小应设计为多大?
【解答】
每一个子表的大小s=⎡n⎤=⎡10000⎤=100个记录对象。
10-3若是一个磁盘页块大小为1024(=1K)字节,存储的每一个记录对象需要占用16字节,其中关键码占4字节,其它数据占12字节。
所有记录均已按关键码有序地存储在磁盘文件中,每一个页块的第1个记录用于寄存线性索引。
另外在内存中开辟了256K字节的空间可用于寄存线性索引。
试问:
(1)若将线性索引常驻内存,文件中最多能够寄存多少个记录?
(每一个索引项8字节,其中关键码4字节,地址4字节)
(2)若是利用二级索引,第二级索引占用1024字节(有128个索引项),这时文件中最多能够寄存多少个记录?
【解答】
(1)因为一个磁盘页块大小为1024字节,每一个记录对象需要占用16字节,则每一个页块可寄存1024/16=64个记录,除第一个记录存储线性索引外,每一个页块可存储63个记录对象。
又因为在磁盘文件中所有记录对象按关键码有序存储,所以线性索引能够是稀疏索引,每一个索引项寄存一个页块的最大关键码及该页块的地址。
若线性索引常驻内存,那么它最多可寄存256*(1024/8)=256*128=32768个索引项,文件中可寄存32768*63=2064384个记录对象。
(2)由于第二级索引占用1024个字节,内存中还剩255K字节用于第一级索引。
第一级索引有255*128=32640个索引项,作为稀疏索引,每一个索引项索引一个页块,则索引文件中可寄存32640*63=2056320。
397
HelloWorld!
82
XYZ
1038
Thisstringisratherlong
1037
ThisisShorter
42
ABC
2222
HellonewWorld!
10-4假设在数据库文件中的每一个记录是由占2个字节的整型数关键码和一个变长的数据字段组成。
数据字段都是字符串。
为了寄存右面的那些记录,应如何组织线性索引?
【解答】
将所有字符串依加入的前后顺序寄存于一个持续的存储空间store中,那个空间也叫做“堆”,它是寄存所有字符串的顺序文件。
它有一个指针free,指示在堆store中当前可寄存数据的开始地址。
初始时free置为0,表示可从文件的0号位置开始寄存。
线性索引中每一个索引项给出记录关键码,字符串在store中的起始地址和字符串的长度:
索引表ID堆store
关键码
串长度
串起始地址
0
HelloWorld!
XYZThisstringisratherlongThis
42
3
56
82
3
12
isShorterABCHellonewWorld!
free
397
12
0
1037
15
41
1038
26
15
2222
16
59
10-5设有一个职工文件:
记录地址
职工号
姓名
性别
职业
年龄
籍贯
月工资(元)
10032
034
刘激扬
男
教师
29
山东
10068
064
蔡晓莉
女
教师
32
辽宁
10104
073
朱力
男
实验员
26
广东
10140
081
洪伟
男
教师
36
北京
10176
092
卢声凯
男
教师
28
湖北
10212
123
林德康
男
行政秘书
33
江西
10248
140
熊南燕
女
教师
27
上海
10284
175
吕颖
女
实验员
28
江苏
10320
209
袁秋慧
女
教师
24
广东
其中,关键码为职工号。
试按照此文件,对下列查询组织主索引和倒排索引,再写出搜索结果关键码。
(1)男性职工;
(2)月工资超过800元的职工;(3)月工资超过平均工资的职工;(4)职业为实验员和行政秘书的男性职工;(5)男性教师或年龄超过25岁且职业为实验员和教师的女性职工。
【解答】
主索引月工资倒排索引职务倒排索引
职工号
记录地址
月工资
长度
指针
职务
长度
指针
0
034
10032
480.
3
073
教师
6
034
1
064
10068
123
064
2
073
10104
175
081
3
081
10140
720.
3
034
092
4
092
10176
092
140
5
123
10212
209
209
6
140
10248
780.
1
140
实验员
2
073
7
175
10284
1200.
1
064
175
8
209
10320
1400.
1
081
行政秘书
1
123
性别倒排索引年龄倒排索引
性别
长度
指针
年龄
长度
指针
男
5
034
24
1
209
073
26
1
073
081
27
1
140
092
28
2
092
123
175
女
4
064
29
1
034
140
32
1
064
175
33
1
123
209
36
1
081
搜索结果:
(1)男性职工(搜索性别倒排索引):
{034,073,081,092,123}
(2)月工资超过800元的职工(搜索月工资倒排索引):
{064,081}
(3)月工资超过平均工资的职工(搜索月工资倒排索引){月平均工资776元}:
{064,081,140}
(4)职业为实验员和行政秘书的男性职工(搜索职务和性别倒排索引):
{073,123,175}&&{034,073,081,092,123}={073,123}
(5)男性教师(搜索性别与职务倒排索引):
{034,073,081,092,123}&&{034,064,081,092,140,209}={034,081,092}
年龄超过25岁且职业为实验员和教师的女性职工(搜索性别、职务和年龄倒排索引):
{064,140,175,209}&&{034,064,073,081,092,140,175,209}&&{034,064,073,081,092,123,140,175}={064,140,175}
10-6倒排索引中的记录地址能够是记录的实际寄存地址,也能够是记录的关键码。
试比较这两种方式的优缺点。
【解答】
在倒排索引中的记录地址用记录的实际寄存地址,搜索的速度快;但以后在文件中插入或删除记录对象时需要移动文件中的记录对象,从而改变记录的实际寄存地址,这将对所有的索引产生影响:
修改所有倒排索引的指针,不但工作量大而且容易引入新的错误或遗漏,使得系统不易保护。
记录地址采用记录的关键码,缺点是寻觅实际记录对象需要再通过主索引,降低了搜索速度;但以后在文件中插入或删除记录对象时,若是移动文件中的记录对象,致使许多记录对象的实际寄存地址发生转变,只需改变主索引中的相应记录地址,其他倒排索引中的指针一概不变,使得系统容易保护,且不易产生新的错误和遗漏。
10-7m=2的平衡m路搜索树是AVL树,m=3的平衡m路搜索树是2-3树。
它们的叶结点必需在同一层吗?
m阶B树是平衡m路搜索树,反过来,平衡m路搜索树必然是B树吗?
为何?
【解答】
m=3的平衡m路搜索树的叶结点不必然在同一层,而m阶B_树的叶结点必需在同一层,所以m阶B_树是平衡m路搜索树,反过来,平衡m路搜索树不必然是B_树。
10-8下图是一个3阶B树。
试别离画出在插入65、15、40、30以后B树的转变。
55
8090
45
95
85
6070
50
2535
【解答】
插入65后:
5580
90
65
45
2535
50
60
70
85
95
5580
插入15后:
90
65
2545
15
70
60
95
85
50
35
插入40后:
5580
90
65
2545
50
3540
15
70
60
95
85
插入30后:
55
80
35
45
25
90
65
30
15
40
70
60
95
85
50
10-9下图是一个3阶B树。
试别离画出在删除50、40以后B树的转变。
50
30
6080
55
20
95
70
40
【解答】
删除50后:
55
80
30
95
6070
40
20
删除40后:
5580
2030
6070
95
10-10对于一棵有1999999个关键码的199阶B树,试估量其最大层数(不包括失败结点)及最小层数(不包括失败结点)。
【解答】
设B树的阶数m=199,则⎡m/2⎤=100。
若不包括失败结点层,则其最大层数为
⎣log⎡m/2⎤((N+1)/2)⎦+1=⎣log1001000000⎦+1=4
若使得每一层关键码数达到最大,可使其层数达到最小。
第0层最多有(m-1)个关键码,第1层最多有(m-1)2个关键码,⋯,第h-1层最多有(m-1)h个关键码。
层数为h的B树最多有(m-1)+(m-1)2+…+(m-1)h-1=(m-1)((m-1)h–1)/(m-2)个关键码。
反之,如有n个关键码,n≤(m-1)((m-1)h–1)/(m-2),则h≥log(m-1)(n(m-2)/(m-1)+1),所以,有1999999个关键码的199阶B树的最小层数为
⎡log(m-1)(n*(m-2)/(m-1)+1)⎤=⎡log198(1999999*197/198+1)⎤=⎡log1981989899⎤
10-11给定一组记录,其关键码为字符。
记录的插入顺序为{C,S,D,T,A,M,P,I,B,W,N,G,U,R,K,E,H,O,L,J},给出插入这些记录后的4阶B+树。
假定叶结点最多可寄存3个记录。
【解答】
插入C,S,D插入T插入A插入M
DS
S
S
CDS
DM
ST
AC
ACD
ST
ST
CD
插入P插入I
DMS
DS
MP
DI
ST
AC
DMP
AC
ST
DMSU
插入B,W,N,G插入U
DMS
UW
ST
MNP
DGI
ABC
DGI
MNP
STW
ABC
插入R
P
SU
DM
MN
DGI
ABC
PR
ST
UW
插入K
P
SU
DIM
IK
DG
MN
PR
ST
UW
ABC
P
插入E
SU
DIM
DEG
IK
ST
PR
UW
MN
ABC
插入H
P
DGIM
SU
GH
IK
MN
ST
PR
UW
DE
ABC
插入O,L
P
DGIM
SU
MNO
ABC
IKL
ST
PR
GH
DE
UW
插入J
IP
DG
KM
SU
IJ
KL
PR
ST
MNO
UW
GH
DE
ABC
10-12设有一棵B+树,其内部结点最多可寄存100个子女,叶结点最多可存储15个记录。
对于1,2,3,4,5层的B+树,最多能存储多少记录,最少能存储多少记录。
【解答】
一层B+树:
按照B+树概念,一层B+树的结点只有一个,它既是根结点又是叶结点,最多可存储m1=15个记录,最少可存储⎡m1/2⎤=8个记录。
二层B+树:
第0层是根结点,它最多有m=100棵子树,最少有2个结点;第1层是叶结点,它最多有m个结点,最多可存储m*m1=100*15=1500个记录,最少有2个结点,最少可存储2*⎡m1/2⎤=16个记录。
三层B+树:
第2层是叶结点。
它最多有m2个结点,最多可存储m2*m1=150000个记录。
最少有2*⎡m/2⎤=100个结点,最少可存储2*⎡m/2⎤*⎡m1/2⎤=800个记录。
四层B+树:
第3层是叶结点。
它最多有m3个结点,可存储m3*m1=个记录。
最少有2*⎡m/2⎤2=2*502=5000个结点,存储2*⎡m/2⎤2*⎡m1/2⎤=40000个记录。
五层B+树:
第4层是叶结点。
它最多有m4个结点,可存储m4*m1=00个记录。
最少有2*⎡m/2⎤3=2*503=250000个结点,存储2*⎡m/2⎤3*⎡m1/2⎤=2000000个记录。
10-13设散列表为HT[13],散列函数为H(key)=key%13。
用闭散列法解决冲突,对下列关键码序列12,23,45,57,20,03,78,31,15,36造表。
(1)采用线性探查法寻觅下一个空位,画出相应的散列表,并计算等概率下搜索成功的平均搜索长度和搜索不成功的平均搜索长度。
(2)采用双散列法寻觅下一个空位,再散列函数为RH(key)=(7*key)%10+1,寻觅下一个空位的公式为Hi=(Hi-1+RH(key))%13,H1=H(key)。
画出相应的散列表,并计算等概率下搜索成功的平均搜索长度。
【解答】
利用散列函数H(key)=keymod13,有
H(12)=12,H(23)=10,H(45)=6,H(57)=5,
H(20)=7,H(03)=3,H(78)=0,H(31)=5,
H(15)=2,H(36)=10.
(1)利用线性探查法造表:
0
1
2
3
4
5
6
7
8
9
10
11
12
78
15
03
57
45
20
31
23
36
12
(1)
(1)
(1)
(1)
(1)
(1)
(4)
(1)
(2)
(1)
搜索成功的平均搜索长度为
ASLsucc=
(1+1+1+1+1+1+4+1+2+1)=
搜索不成功的平均搜索长度为
ASLunsucc=
(2+1+3+2+1+5+4+3+2+1+5+4+3)=
(2)利用双散列法造表:
Hi=(Hi-1+RH(key))%13,H1=H(key)
0
1
2
3
4
5
6
7
8
9
10
11
12
78
15
03
57
45
20
31
36
23
12
(1)
(1)
(1)
(1)
(1)
(1)
(3)
(5)
(1)
(1)
搜索成功的平均搜索长度为
ASLsucc=
(1+1+1+1+1+1+3+5+1+1)=
10-14设有150个记录要存储到散列表中,要求利用线性探查法解决冲突,同时要求找到所需记录的平均比较次数不超过2次。
试问散列表需要设计多大?
设α是散列表的装载因子,则有
【解答】
已知要存储的记录数为n=150,查找成功的平均查找长度为ASLsucc≤2,则有ASLsucc=
≤2,解得α≤
。
又有α=
≤
,则m≥225。
10-15若设散列表的大小为m,利用散列函数计算出的散列地址为h=hash(x)。
(1)试证明:
若是二次探查的顺序为(h+q2),(h+(q-1)2),…,(h+1),h,(h-1),…,(h-q2),其中,q=(m-1)/2。
因此在接踵被探查的两个桶之间地址相减所得的差取模(%m)的结果为
m-2,m-4,m-6,…,5,3,1,1,3,5,…,m-6,m-4,m-2
(2)编写一个算法,利用课文中讨论的散列函数h(x)和二次探查解决冲突的方式,按给定值x来搜索一个大小为m的散列表。
若是x不在表中,则将它插入到表中。
【解答】
(1)将探查序列分两部份讨论:
(h+q2),(h+(q-1)2),…,(h+1),h和(h-1),(h-22),…,(h-q2)。
对于前一部份,设其通项为h+(q–d)2,d=0,1,…,q,则相邻两个桶之间地址相减所得的差取模:
(h+(q–(d-1))2–(h+(q–d)2))%m=((q–(d-1))2–(q–d)2)%m
=(2*q-2*d+1)%m=(m–2*d)%m.(代换q=(m-1)/2)
代入d=1,2,…,q,则可取得探查序列如下:
m-2,m-4,m-6,…,5,3,1。
(m–2*q=m–2*(m-1)/2=1)
对于后一部份,其通项为h–(q–d)2,d=q,q+1,…,2q,则相邻两个桶之间地址相减所得的差取模:
(h–(q–d)2–(h–(q–(d+1))2))%m=((q–(d+1)2–(q–d)2)%m
=(2*d–2*q+1)%m=(2*d–m+2)%m(代换q=(m-1)/2)
代入d=q,q+1,…,2q-1,则可取得
2*d–m+2=2*q–m+2=m–1–m+2=1,
2*d–m+2=2*q+2–m+2=m–1+2–m+2=3,……,
2*d–m+2=2*(2*q-1)–m+2=2*(m–1–1)–m+2=2*m–4–m+2=m–2。
〖证毕〗
(2)编写算法
下面是利用二次探查法处置溢出时的散列表类的声明。
templateclassHashTable{nfo!
=Empty&&ht[CurrentPos].Element!
=x){
/搜索是不是要求表项
if(i<=q){nfo==Active&&ht[CurrentPos].Element==x)
returnCurrentPos;nfo=Active;ht[CurrentPos].Element=x;nfo==Active){
Find(Oldht[i].Element);lement==x)CurrentPos=i;
}
delete[]Oldht;
returnCurrentPos;
}
}
求下一个大于参数表中所给正整数N的质数的算法。
intNextPrime(intN){
nfo!
=Empty&&strcmp(ht[j].Element,id)!
=0){nfo!
=Active){lement=ht[k-1].Element;ht[k].info=ht[k-1].info;}
ht[i].Element=id;ht[i].info=Active;lement;=ht[TableSize-1].info;
while(intk=TableSize-1;k>i;k--)
{ht[k].Element=ht[k-1].Element;ht[k].info=ht[k-1].info;}
ht[i].Element=id;ht[i].info=Active;lement=ht[k-1].Element;ht[k].info=ht[k-1].info;}
ht[0].Element=;ht[0].info=;
}
returnj;
}
voidHashTable:
:
HashSort(){
intn,i;char*str;
cin>>