第八章查找

合集下载

数据结构习题及答案 (1)

数据结构习题及答案 (1)

第八章查找一、判断题1.用二分查找法对一个顺序表进行查找,这个顺序表可以是按各键值排好序的,也可以是没有按键值排好序的。

()2.哈希表的查找不用进行关键字的比较。

()3.哈希表的定义函数H(key)=key%p(p<=m)这种方法是直接定址法。

()4.装填因子α的值越大,就越不容易发生冲突。

( )5.选择hash函数的标准为:随机性好、均匀性好和尽量避免冲突。

( )参考答案:1、×2、×3、×4、×5、√二、填空题1.顺序查找法的平均查找长度为__________,二分查找法的平均查找长度为________,分块查找法(以顺序查找确定块)的平均查找长度为__________,分块查找法(以二分查找确定块〉的平均查找长度为_________,哈希表查找法采用链接法处理冲突时的平均查找长度为_________。

(n+1)/2;((n+1)*log2(n+1))/n-1;(s2+2s+n)/2s;log2(n/s+1)+s/2;1+α2.在各种查找方法中,平均查找长度与结点个数n无关的查法方法是_________哈希表查找3.二分查找的存储结构仅限于_________,且是__________。

顺序;有序的4.在分块查找方法中,首先查找__________,然后再查找相应的___________。

索引;块5.长度为255的表,采用分块查找法,每块的最佳长度是____________。

156.在散列函数H(key)=key%p中,p应取_______________。

小于表长的最大素数7.假设在有序线性表A[1..20]上进行二分查找,则比较一次查找成功的结点数为_________,则比较二次查找成功的结点数为__________,则比较三次查找成功的结点数为_________,则比较四次查找成功的结点数为________,则比较五次查找成功的结点数为_________,平均查找长度为_________。

数据结构(八)查找

数据结构(八)查找
122
99
250
110
300
280
类C程序实现: void InsertBST(*&t,key) //在二叉排序树中插入查找关键字key { if(t= = NULL){ t=new BiTree; t->lchild=t->rchild=NULL; t->data=key; return; } if(key<t->data ) InsertBST(t->lchild,key); else InsertBST (t->rchild, key ); } void CreateBiTree(tree,d[ ],n) //n个数据在数组d中,tree为二叉排序树根 { tree=NULL; for(i=0;i<n;i++) InsertBST(tree,d[i]); }
p q
void delete(*&p) { if(p->rchild = = NULL) { q=p; p=p->lchild; delete q; } else if(p->lchild= =NULL) { q=p; p=p->rchild; delete q; } else { q=p; s=p->lchild; while(s->rchild!=NULL) {q=s; s=s->rchild;} p->data=s->data; if(q!=p) q->rchild=s->lchild; else q->lchild=s->lchild; } delete s; }
在xL中选值最大的代替x,该数据按二叉排序树的性质应在 最右边。
f x f s c

查找也叫检索

查找也叫检索

3 19
4 21
5 37
mid 6 7 56 64 low
8 75
9 80
10 88
1 5
2 13
3 19
4 21
5 37
6 56
7 64
mid high 8 9 10 11 75 80 88 92
low mid high 1 5 2 13 3 19 4 21 5 37 6 56 7 64 8 75 9 80 10 88 11 92
索引表 关键码字段 指针字段 22 1 48 7 86 13 查38
查找表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 22 12 13 8 9 20 33 42 44 38 24 48 60 58 74 57 86 53
分块查找方法评价
ASL=ASL索引表+ASL子表
P C CL 中序遍历:CL C P PR F (8) PR CL
C PR
中序遍历:CL C PR F
例 50
80 80 120 60 110 150
删除50
60 55 53
120 70 110
80
删除60 150
55 53
120
55
53
70
70 110
150
10 4 8 13 7 25 删除10 5 4
查找失败情况下:ASL=n+1
8.2.3 折半查找
查找过程:每次将待查记录所在区间缩小一半 适用条件:采用顺序存储结构的有序表 算法实现
设表长为n,low、high和mid分别指向待查元素所在 区间的上界、下界和中点,kx为给定值 初始时,令low=1,high=n,mid=(low+high)/2 让kx与mid指向的记录比较

第8章_查找

第8章_查找

{
int low,mid,high;
low=0;
/*确定起始区间低下界位置*/
high=n-1;
/*确定起始区间高下界位置*/
while(low<=high)
{
mid=(low+high)/2;
/*求区间范围的中间位置*/
if(a[mid].key==k) return mid;
/*比较中间位置上的关键字与给定值*/ /*查找成功,返回查找到的记录的下标*/
精选2021版课件
6
8.2.2 折半查找
一、折半查找 又称为二分查找。使用该查找算法的前提条件是:查找表
中记录顺序存储且相应的关键字值有序。
例8-1 设顺序表中有8个记录,它们的关键字依次为{8,11,18,28, 45,55,63,80},用折半查找的方法在该顺序表中查找关键字为55 和20的记录。查找关键字为55的记录的过程见图:
8.2.3 分块查找
一、分块查找
分块查找(又称为索引顺序查找),是顺序查找的一种改进方法。
在分块查找时,把表内的记录按某种属性分成n(n>1)个块(子表),且 块间有序,块内无序。然后建立一个相应的“索引表”,索引表由若 干个索引记录组成,每个索引记录对应一个块。索引记录包含两个数 据项,即对应块内最大关键字值和块中第一个记录位置的地址指针。
个关键字能确定多个记录,称该关键字为次关键字。 查找(Searching):给定一个确定的值,在查找表中确定
一个记录,其相应的关键字等于给定值的操作。
精选2021版课件
2
根据对查找表进行的不同操作,把查找表分为静态 查找表和动态查找表两种。
• 静态查找表是指只查询给定的记录是否存在于查找 表中或检索某个特定记录的有关属性。

数据结构-查找分析

数据结构-查找分析

第八章查找一、填空题1.线性有序表(a1,a2,a3,…,a256)是从小到大排列的,对一个给定的值k,用二分法检索表中与k相等的元素,在查找不成功的情况下,最多需要检索次。

设有100个结点,用二分法查找时,最大比较次数是。

2.折半查找有序表(4,6,12,20,28,38,50,70,88,100),若查找表中元素20,它将依次与表中元素比较大小。

3. 在各种查找方法中,平均查找长度与结点个数n无关的查找方法是。

4、对线性表进行二分查找时,要求线性表必须以方式存储,且结点按关键字排列。

5.顺序查找n个元素的顺序表,若查找成功,则比较关键字的次数最多为_ __次;当使用监视哨时,若查找失败,则比较关键字的次数为__ 。

6.在有序表A[1..12]中,采用二分查找算法查等于A[12]的元素,所比较的元素下标依次为____ _____。

7. 在有序表A[1..20]中,按二分查找方法进行查找,查找长度为5的元素个数是_8. 已知二叉排序树的左右子树均不为空,则_______上所有结点的值均小于它的根结点值,________上所有结点的值均大于它的根结点的值。

9、中序遍历二叉排序树得到的序列是序列(填有序或无序)。

10、从有序表(10,16,25,40,61,28,80,93)中依次二分查找40和61元素时,其查找长度分别为和。

二、单项选择题()1.在表长为n的链表中进行顺序查找,它的平均查找长度为A. ASL=n; B. ASL=(n+1)/2;C. ASL=n+1; D. ASL≈log2(n+1)-1()2.折半查找有序表(4,6,10,12,20,30,50,70,88,100)。

若查找表中元素58,则它将依次与表中比较大小,查找结果是失败。

A.20,70,30,50 B.30,88,70,50C.20,50 D.30,88,50()3.对22个记录的有序表作折半查找,当查找失败时,至少需要比较次关键字。

第八章查找——精选推荐

第八章查找——精选推荐

查找一.选择题1.若查找每个元素的概率相等,则在长度为n 的顺序表上查找到表中任一元素的平均查找长度为_____________。

A. nB. n+1C. (n-1)/2D. (n+1)/2分析:本题主要考查顺序表的平均查长度的计算,在等概率下,ASLsucc=nP1+(n-1)P2+……+2Pn-1 +Pn=[n+(n-1)+ ……+1]/n = (n+1)/2,其中:Pi 为查找第i 个元素的概率。

所以答案为D。

2.折半查找的时间复杂度_____________。

A.O(n*n)B.O(n)C. O(nlog2n)D. O(log2n)分析:本题考查折半查找的基本思想和对应的判定树。

因为对n 个结点的线性表进行折半查找,对应的判定树的深度是 log2n +1,折半查找的过程就是走了一条从判定树的根到末端结点的路径,所以答案为D。

3.采用分块查找时,数据的组织方式为_____________。

A. 把数据分成若干块,每块内数据有序B. 把数据分成若干块,块内数据不必有序,但块间必须有序,每块内最大(或最小)的数据组成索引表C. 把数据分成若干块,每块内数据有序,每块内最大(或最小)的数据组成索引表D. 把数据分成若干块,每块(除最后一块外)中的数据个数相等分析:本题主要考查分块查找的数据组织方式特点。

在分块查找时,要求块间有序,块内或者有序或者无序。

这样,在查找记录所在的块时,可以采用折半查找。

所以答案为B。

4.二叉排序树的查找效率与二叉排序树的(1)有关,当(2)时,查找效率最低,其查找长度为n。

(1) A.高度B.结点的个数C.形状D.结点的位置(2) A.结点太多B.完全二叉树C.呈单叉树D.结点的结构太复杂分析:本题主要考查二叉排序树的查找效率与二叉排序树形存在一定的关系。

当二叉排序树的前 log2n 层是满二叉树时,其查找效率最高,其查找长度最大为 log2n +1;当二叉排序树呈单叉树时,其查找效率最低,其查找长度最大为n,此时相当于顺序查找。

数据结构第8章 查找 答案

数据结构第8章 查找 答案

第8章 查找 测试题 及答案一、填空题1. 在数据的存放无规律而言的线性表中进行检索的最佳方法是 顺序查找(线性查找) 。

2. 线性有序表(a 1,a 2,a 3,…,a 256)是从小到大排列的,对一个给定的值k ,用二分法检索表中与k 相等的元素,在查找不成功的情况下,最多需要检索 8 次。

设有100个结点,用二分法查找时,最大比较次数是 7 。

3. 假设在有序线性表a[20]上进行折半查找,则比较一次查找成功的结点数为1;比较两次查找成功的结点数为 2 ;比较四次查找成功的结点数为 8 ;平均查找长度为 3.7 。

解:显然,平均查找长度=O (log 2n )<5次(25)。

但具体是多少次,则不应当按照公式)1(log 12++=n nn ASL 来计算(即(21×log 221)/20=4.6次并不正确!)。

因为这是在假设n =2m -1的情况下推导出来的公式。

应当用穷举法罗列:全部元素的查找次数为=(1+2×2+4×3+8×4+5×5)=74; ASL =74/20=3.7 !!!4.【计研题2000】折半查找有序表(4,6,12,20,28,38,50,70,88,100),若查找表中元素20,它将依次与表中元素 28,6,12,20 比较大小。

5. 在各种查找方法中,平均查找长度与结点个数n 无关的查找方法是 散列查找 。

6. 散列法存储的基本思想是由 关键字的值 决定数据的存储地址。

7. 有一个表长为m 的散列表,初始状态为空,现将n (n<m )个不同的关键码插入到散列表中,解决冲突的方法是用线性探测法。

如果这n 个关键码的散列地址都相同,则探测的总次数是 n(n-1)/2=( 1+2+…+n-1) 。

(而任一元素查找次数 ≤n-1)二、单项选择题( B )1.在表长为n的链表中进行线性查找,它的平均查找长度为A. ASL=n; B. ASL=(n+1)/2;C. ASL=n +1; D. ASL≈log2(n+1)-1( A )2.折半查找有序表(4,6,10,12,20,30,50,70,88,100)。

第八章 查找

第八章 查找
A.折半查找方法不适用于按值有序链接的链表的查找
B.折半查找方法适用于按值有序的顺序表的查找
C.折半查找方法适用于按关键字值大小有序排列的顺序文件的查找
D.折半查找方法适用于排序连续顺序文件的查找
(5)在有序表(k1,k2,...,k9,)中采用折半查找方法查找99次,其中,至少有一个元素被比较了99次,该元素是--。
A.参加比较的关键字值的多少
B.被查找的关键字值在关键字序列中的位置
C.关键字序列中是否存在被查找关键字值
D.关键字值的平均比较次数的多少
(2)顺序查找方法的优点之一是- 。 ·
A.对于被查找对象几乎没有限制 B.适合排序连续顺序文件的查找
(1)按该线性表中元素的顺序构造出一棵二叉排序树;
(2)若每个元素的查找概率均等,查找此二叉排序树中任意一个结点的平均查找长度ASL是多少?
(3)若对线性表的元素按字典顺序从小到大排列以后,再用折半查找方法,则查找其中任意一个元素的平均查找长度ASL是多少?
(4)画出相应的平衡二叉树。
A.K99 B.k50 C.K49 D.k1
(6)为了实现分块查找,线性表必须采用--结构。
A.顺序存储 B.链式存储
C.索引存储 D.散列存储
(7)只能在顺序存储结构上才能实现的查找方法是 法。
A.顺序查找 B.树型查找
(11)索引文件包括--和--两个部分。
(12)索引表的特点是--,并且--。
(13)在索引文件中查找一个记录的过程是先查--,然后--。
(14)具有144项的表分成--块最好,若每块的最佳长度为8,则平均查找长度为--
(15)在3阶B-树上,每个分支结点包含的子树的数目最多为--,最少为--。

数据结构ppt(c语言版李春葆)

数据结构ppt(c语言版李春葆)

8
基本操作P: 基本操作 : Create(&ST,n): , : 操作结果:构造一个含n个数据元素的静态查找表 个数据元素的静态查找表ST。 操作结果:构造一个含 个数据元素的静态查找表 。 Destroy(&ST): : 初始条件:静态查找表ST存在 存在。 初始条件:静态查找表 存在。 操作结果:销毁表ST。 操作结果:销毁表 。 Search(ST,key): , : 初始条件:静态查找表ST存在 存在, 初始条件:静态查找表 存在,key为和关键字 为和关键字 类型相同的给定值。 类型相同的给定值。 操作结果: 中存在其关键字等于key的数据元素 的数据元素, 操作结果:若ST中存在其关键字等于 的数据元素, 中存在其关键字等于 则函数值为该元素的值或在表中的位置, 则函数值为该元素的值或在表中的位置, 否则为 “空”。
2
查找表的分类: 查找表的分类: 静态查找表(Static Search Table): 静态查找表 : 若对查找表仅作查询和检索操作, 若对查找表仅作查询和检索操作,则称此类查找表为静 态查找表。在查找过程中,查找表本身不发生变化。 态查找表。在查找过程中,查找表本身不发生变化。 对静态查找表进行的查找操作称为静态查找。 对静态查找表进行的查找操作称为静态查找。 动态查找表(Dynamic Search Table): 动态查找表 : 在查找过程中同时插入查找表中不存在的数据元素, 在查找过程中同时插入查找表中不存在的数据元素,或 者从查找表中删除已存在的某个数据元素,此类表为动态查 者从查找表中删除已存在的某个数据元素 此类表为动态查 找表。 找表。
!EQ(ST.elem[i].key, key)
算法 9.1
13
查找操作的性能分析 衡量一个算法好坏的量度有三条: 衡量一个算法好坏的量度有三条: 时间复杂度(衡量算法执行的时间量级) 时间复杂度(衡量算法执行的时间量级) 空间复杂度( 空间复杂度(衡量算法的数据结构所占存储以及大量的附加 存储) 存储) 算法的其它性能 对于查找算法来说,通常只需要一个或几个辅助空间。 对于查找算法来说,通常只需要一个或几个辅助空间。 查找算法中的基本操作是将记录的关键字和给定值进行比 因此,通常以“ 较 , 因此 , 通常以 “ 其关键字和给定值进行过比较的记录 个数的平均值”作为衡量查找算法好坏的依据。 个数的平均值”作为衡量查找算法好坏的依据。 定义:为确定记录在查找表中的位置, 定义:为确定记录在查找表中的位置,需和给定值进行 比较的关键字个数的期望值称为查找算法在查找成功时的 平均查找长度(Average Search Length)。 线性链表表示静态查找表,则Search函数可 以顺序表或线性链表表示静态查找表, 函数可 用顺序查找来实现。 用顺序查找来实现。本节中只讨论它在顺序存储结构模块中 的实现。 的实现。 //静态查找表的顺序存储结构 静态查找表的顺序存储结构 typdef struct{ ElemType * elem; //数据元素存储空间基址 数据元素存储空间基址 //建表时按实际长度分配,0号单元留空 建表时按实际长度分配, 号单元留空 建表时按实际长度分配 int length; //表长度 表长度 }SSTable; ;

第8章 查找

第8章 查找

72
85
88
90
11
[ 35 ↑ ↑ low mid [ 35 ↑ low
64
72
85
88
90
98
5
11
23 ] ↑ high
64
72
85
88
90
98
(b) 查找K=30的过程(三次关键字比较后查找失败)
6 3 9
1
4
7
10
•不成功:从根到叶子或度1结点
2
5
8
11
二、算法实现
(略)
三、性能分析
•最坏:不超过树高, log2(n + 1) •平均:ASL≈(n+1)/n*log2(n+1)-1 ≈log2(n+1)-1=O(log2n) 。
第8章 查找
8.1 8.2 8.3 8.4 基本概念 静态查找表 树表的查找 散列表
查找就是在数据集合中寻找满足某种条件的数据对象。
知识点结构
查找的基本概念 查找结构 查找算法的时间性能
静态表的查找技术 顺序查找 二分查找
树表的查找技术 二叉排序树
散列表的查找技术 散列的基本思想
插值查找
斐波那契查找
6 3 9
1
4
7
10
2
5
8
11

10个结点的有序表,用二分查找,成功和不成功的ASL=?
首先,建立判定树:mid=(low+high)/2
5 2 1 3 4 6 7 8 9 10
查找成功时:ASL=(1×1+2×2+3×4+4×3)/10 不成功时:ASL=(3×5+4×6)/11

数据结构与算法(软件)课程第八章 查找

数据结构与算法(软件)课程第八章 查找

第八章查找1.若有18个元素的有序表存放在一维数组A[19]中,第一个元素放A[1]中,现进行二分查找,则查找A[3]的比较序列的下标依次为( )A. 1,2,3B. 9,5,2,3C. 9,5,3D. 9,4,2,32.设二叉排序树中有n个结点,则在二叉排序树的平均平均查找长度为()。

A. O(1)B. O(log2n) C. O(n) D. O(n2) 3.在二叉排序树中插入一个结点的时间复杂度为()。

A. O(1)B. O(n)C. O(log2n) D. O(n2) 4.设有序顺序表中有n个数据元素,则利用二分查找法查找数据元素X的最多比较次数不超过()。

A. log2n+1 B. log2n-1 C. log2n D. log2(n+1)5.设有序表中有1000个元素,则用二分查找查找元素X最多需要比较()次。

A. 25B. 10C. 7D. 16.顺序查找不论在顺序线性表中还是在链式线性表中的时间复杂度为()。

A. O(n) B. O(n2) C. O(n1/2) D. O(1og2n) 7.设二叉排序树上有n个结点,则在二叉排序树上查找结点的平均时间复杂度为()。

A. O(n)B. O(n2)C. O(nlog2n) D. O(1og2n)8.()二叉排序树可以得到一个从小到大的有序序列。

A. 先序遍历B.中序遍历C. 后序遍历D. 层次遍历9.设一组初始记录关键字序列为(13,18,24,35,47,50,62,83,90,115,134),则利用二分法查找关键字90需要比较的关键字个数为()。

A. 1B. 2C. 3D. 410.设某散列表的长度为100,散列函数H(k)=k % P,则P通常情况下最好选择()。

A. 99B. 97C. 91D. 9311.在二叉排序树中插入一个关键字值的平均时间复杂度为()。

A. O(n)B. O(1og2n) C. O(nlog2n) D. O(n2)12.设一个顺序有序表A[1:14]中有14个元素,则采用二分法查找元素A[4]的过程中比较元素的顺序为( )。

第8章 查找 习题参考答案

第8章 查找 习题参考答案

习题八 参考答案一、选择题1.对线性表进行二分查找时,要求线性表必须( B )A.以顺序方式存储B.以顺序方式存储,且结点按关键字值有序排列C.以链接方式存储D.以链接方式存储,且结点按关键字值有序排列2. 用二分查找法查找具有n 个结点的顺序表时,查找每个结点的平均比较次数是( D )A.O(n 2)B.O(nlog 2n)C.O(n)D.O(log 2n)3. 对长度为4的顺序表进行查找,若查找第一个记录的概率为1/24, 查找第二个记录的概率为1/6, 查找第三个记录的概率为2/3, 查找第四个记录的概率为1/8,则查找任意一个记录的平均查找长度为( A )A.23/8B.20/8C.17/8D.14/84. 若有一个长度为64的有序表,现用二分查找方法查找某一记录,则查找不成功,最多需要比较( B )次。

A.9B.7C.5D.35. 当采用分块查找时,数据的组织方式为( C )A.数据必须有序B.数据不必有序C.数据分成若干块,每块内数据不必有序,但块间必须有序D.数据分成若干块,每块内数据必须有序,但块间不必有序6. 一棵深度为k 的平衡二叉树,其每个非终端结点的平衡因子均为0,则该平衡二叉树共有( C )个结点。

A.2k-1-1B.2k-1+1C.2k -1D.2k +17. 具有5层结点的平衡二叉树至少有( B )个结点。

A.10B.12C.15D.178. 若结点的存储地址与其关键字之间存在某种映射关系,则称这种存储结构为( D )A.顺序存储结构B.链式存储结构C.索引存储结构D.散列存储结构9. 以下有关m 阶B-树的叙述中,错误的是( B )。

A.根结点至多有m 棵子树B.每个结点至少有⎥⎥⎤⎢⎢⎡2m 棵子树 C.所有叶子结点都在同一层上 D.每个结点至多有m-1个关键字10.哈希表的地址区间为0~17,哈希函数为h(key)=K%17。

采用线性探测法处理冲突,并将关键字序列{26,25,72,38,8,18,59}依次存储到哈希表中,则在哈希表中查找元素59需要搜索的次数为( C )。

程序设计基础(C语言)第8章 查找和排序算法

程序设计基础(C语言)第8章 查找和排序算法
mid = low + (high - low) / 2;
8.2.3二分查找的实际应用
• 【例8.3】用二分法求下面的
一元三次方程 x3 x 1 0
在区间[1, 3]上误差不大于 10-6的根。先从键盘输入迭 代初值 x0和允许的误差 , 然后输出求得的方程根和所 需的迭代次数。
//函数功能:用二分法计算并返回方程的根 double Iteration(double x1, double x2, double eps) {
8.1.2线性查找算法的程序实现
#include <stdio.h>
#define N 40
int ReadRecord(int num[], int weight[]);
int LinSearch(int num[], int key, int n);
//主函数
int main(void)
{
int num[N], weight[N], n, pos, key;
double x0; do{
return BinSearch(num, key, mid+1, high); //在后一子表查找 } else if (key < num[mid]) {
return BinSearch(num, key, low, mid-1); //在前一子表查找 } return mid; //找到,返回找到的位置下标 }
序排列的。
int BinSearch(int num[], int key, int low, int high) {
int mid = (high + low) / 2; //取数据区间的中点 if (low > high) //递归结束条件 {

查找表

查找表

2、二叉排序树的查找算法 、二叉排序树的查找算法 若二叉树为空,则查找不成功 否则,1 否则,1)若给定值等于根结点的关键字,则 查找成功。 2)若给定值小于根结点的关键字,则 继续在左子树上进行查找。 3)若给定值大于根结点的关键字,则 继续在右子树上进行查找。 继续在右子树上进行查找。
算法描述如下: Status searchBST(BiTree T,keyType,BiTree f,BiTree &p){ if (!T) {p=f; return false;}//查找不成功 else if (key=T→data) (key=T→ {P=T;return Tree;}//查找成功 else if (key<T→data) (key<T→ searchBST (T→lchild,key,T,P);//在左子树中继续查找 (T→lchild,key,T,P);// else searchBST(T→rchild,key,T,P);// searchBST(T→rchild,key,T,P);//在右子树中继续查找 }//searchBST
h
三、静态查找树表 不等概率查找的情况下,折半查找不是最好 的查找方法 四、索引顺序表(分块查找) 四、索引顺序表(分块查找) 对比顺序表和有序表的查找性能之差别 顺序表 有序表 表的特征 无序表 有序表 存储结构 顺序结构或 顺序结构 链表结构 插删操作 易于进行 需移动元素 ASL值 ASL值 大 小
3、二叉排序树的插入算法 、二叉排序树的插入算法 Status InsertBST(BiTree &T,ElemType e){ if (!SearchBST (T,e.key,null,p)){ S=(BiTree)malloc(sizeof(BiTNode)); S→data=e; S →lchild=S →rchild=Null; if (!P) T=S; else if (e.key<P →data.key) P →lchild=S;//插入S为左孩子 插入S else P →rchild=S;//插入S为右孩子 插入S Return True;} else return false;}//Insert BST
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

9.1(1)无序表:顺序查找不成功时,查找长度为n+1;成功时,平均查找长度为1/(n+1)*(1+2+…+(n+1))=(n+2)/2;两者不相同。

(2)表中只有一个关键字等于给定值k 的记录,无序表、有序表:顺序查找成功时,平均查找长度均为1/(n)*(1+2+…+n)=(n+1)/2;两者相同。

(3)表中只有m 个关键字等于给定值k 的记录,无序表:ASL=n+1;有序表:ASL=(n+1)/2+m ;两者不相同。

9.3ASL=1/10(1+2*2+4*3+3*4)=2.9 9.119.14652 83 197 410删除50后删除68后0 1 2 3 45 6 7 8 910ASL=(4*1+2*2+3+6)/8=17/8 9.25int Search-Seq(SSTable ST, KeyType key){//在顺序表ST 中顺序查找其关键字等于key 的数据元素,ST 按关键字自大至小有序, //若找到,则函数值为该元素在表中的位置,否则为0 ST.elem[ST.length+1].key=key;for (i=1; ST.elem[i].key>key; ++i);if (ST.elem[i].key==key)&&(i<=ST.length) return ielse return 0 ;}//Search-Seq9.31TelemType Maxv(Bitree T){//返回二叉排序树T中所有结点的最大值for (p=T; p->rchild; p=p->rchild);return p->data;}//MaxvTelemType Minv(Bitree T){//返回二叉排序树T中所有结点的最小值for (p=T; p->lchild; p=p->lchild);return p->data;}//MinvStatus IsBST(Bitree T){//判别T是否为二叉排序树if (!T) return OK;else if((!T->lchild)||((T->lchild)&&(IsBST(T->lchild)&&(Maxv(T->lchild)<T->data))) &&((!T->rchild)||((T->rchild)&&(IsBST(T->rchild)&&(Minv(T->rchild)>T->data)))return OKelse return ERROR;}//IsBST9.33Status OutputGEx(Bitree T, TelemType x){//从大到小输出给定二叉排序树T中所有值不小于x的数据元素if (T) {if (OutputGEx(T->rchild, x))if (T->data>=x) {print(T->data);if (OutputGEx(T->lchild, x)) return OK;}else return OK;}else return OK;}//OutputGEx第九章查找9.25int Search_Sq(SSTable ST,int key)//在有序表上顺序查找的算法,监视哨设在高下标端{ST.elem[ST.length+1].key=key;for(i=1;ST.elem[i].key>key;i++);if(i>ST.length||ST.elem[i].key<key) return ERROR;return i;}//Search_Sq分析:本算法查找成功情况下的平均查找长度为ST.length/2,不成功情况下为ST.length.9.26int Search_Bin_Digui(SSTable ST,int key,int low,int high)//折半查找的递归算法{if(low>high) return 0; //查找不到时返回0mid=(low+high)/2;if(ST.elem[mid].key==key) return mid;else if(ST.elem[mid].key>key)return Search_Bin_Digui(ST,key,low,mid-1);else return Search_Bin_Digui(ST,key,mid+1,high);}}//Search_Bin_Digui9.27int Locate_Bin(SSTable ST,int key)//折半查找,返回小于或等于待查元素的最后一个结点号{int *r;r=ST.elem;if(key<r.key) return 0;else if(key>=r[ST.length].key) return ST.length;low=1;high=ST.length;while(low<=high){mid=(low+high)/2;if(key>=r[mid].key&&key<r[mid+1].key) //查找结束的条件return mid;else if(key<r[mid].key) high=mid;else low=mid;} //本算法不存在查找失败的情况,不需要return 0;}//Locate_Bin9.28typedef struct {int maxkey;int firstloc;} Index;typedef struct {int *elem;int length;Index idx[MAXBLOCK]; //每块起始位置和最大元素,其中idx[ 0 ]不利用,其内容初始化为{0,0}以利于折半查找int blknum; //块的数目} IdxSqList; //索引顺序表类型int Search_IdxSeq(IdxSqList L,int key)//分块查找,用折半查找法确定记录所在块,块内采用顺序查找法{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;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; //设置监视哨for(k=j;L.elem[k]!=key;k--); //顺序查找L.elem[i-1]=temp; //恢复元素if(k<i) return ERROR; //未找到return k;}//Search_IdxSeq分析:在块内进行顺序查找时,如果需要设置监视哨,则必须先保存相邻块的相邻元素,以免数据丢失.9.29typedef struct {LNode *h; //h指向最小元素LNode *t; //t指向上次查找的结点} CSList;LNode *Search_CSList(CSList &L,int key)//在有序单循环链表存储结构上的查找算法,假定每次查找都成功{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++);elsefor(p=L.t,i=L.tpos;p->data!=key;p=p->next,i++);L.t=p; //更新t指针return p;}//Search_CSList分析:由于题目中假定每次查找都是成功的,所以本算法中没有关于查找失败的处理.由微积分可得,在等概率情况下,平均查找长度约为n/3.9.30typedef struct {DLNode *pre;int data;DLNode *next;} DLNode;typedef struct {DLNode *sp;int length;} DSList; //供查找的双向循环链表类型DLNode *Search_DSList(DSList &L,int key)//在有序双向循环链表存储结构上的查找算法,假定每次查找都成功{p=L.sp;if(p->data>key){while(p->data>key) p=p->pre;L.sp=p;}else if(p->data<key){while(p->data<key) p=p->next;L.sp=p;}return p;}//Search_DSList分析:本题的平均查找长度与上一题相同,也是n/3.9.31int last=0,flag=1;int Is_BSTree(Bitree T)//判断二叉树T是否二叉排序树,是则返回1,否则返回0{if(T->lchild&&flag) Is_BSTree(T->lchild);if(T->data<last) flag=0; //与其中序前驱相比较last=T->data;if(T->rchild&&flag) Is_BSTree(T->rchild);return flag;}//Is_BSTree9.32int last=0;void MaxLT_MinGT(BiTree T,int x)//找到二叉排序树T中小于x的最大元素和大于x的最小元素{if(T->lchild) MaxLT_MinGT(T->lchild,x); //本算法仍是借助中序遍历来实现if(last<x&&T->data>=x) //找到了小于x的最大元素printf("a=%d\n",last);if(last<=x&&T->data>x) //找到了大于x的最小元素printf("b=%d\n",T->data);last=T->data;if(T->rchild) MaxLT_MinGT(T->rchild,x);}//MaxLT_MinGT9.33void Print_NLT(BiTree T,int x)//从大到小输出二叉排序树T中所有不小于x的元素{if(T->rchild) Print_NLT(T->rchild,x);if(T->data<x) exit(); //当遇到小于x的元素时立即结束运行printf("%d\n",T->data);if(T->lchild) Print_NLT(T->lchild,x); //先右后左的中序遍历}//Print_NLT9.34void Delete_NLT(BiTree &T,int x)//删除二叉排序树T中所有不小于x元素结点,并释放空间{if(T->rchild) Delete_NLT(T->rchild,x);if(T->data<x) exit(); //当遇到小于x的元素时立即结束运行q=T;T=T->lchild;free(q); //如果树根不小于x,则删除树根,并以左子树的根作为新的树根if(T) Delete_NLT(T,x); //继续在左子树中执行算法}//Delete_NLT9.35void Print_Between(BiThrTree T,int a,int b)//打印输出后继线索二叉排序树T中所有大于a且小于b的元素{p=T;while(!p->ltag) p=p->lchild; //找到最小元素while(p&&p->data<b){if(p->data>a) printf("%d\n",p->data); //输出符合条件的元素if(p->rtag) p=p->rtag;else{p=p->rchild;while(!p->ltag) p=p->lchild;} //转到中序后继}//while}//Print_Between9.36void BSTree_Insert_Key(BiThrTree &T,int x)//在后继线索二叉排序树T中插入元素x {if(T->data<x) //插入到右侧{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有右子树时,插入右子树中}//ifelse if(T->data>x) //插入到左子树中{if(!T->lchild) //T没有左子树时,作为左孩子插入{q=(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_Key9.37Status BSTree_Delete_key(BiThrTree &T,int x)//在后继线索二叉排序树T中删除元素x {BTNode *pre,*ptr,*suc;//ptr为x所在结点,pre和suc分别指向ptr的前驱和后继p=T;last=NULL; //last始终指向当前结点p的前一个(前驱)while(!p->ltag) p=p->lchild; //找到中序起始元素while(p){if(p->data==x) //找到了元素x结点{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;} //转到中序后继last=p;}//while //借助中序遍历找到元素x及其前驱和后继结点if(!ptr) return ERROR; //未找到待删结点Delete_BSTree(ptr); //删除x结点if(pre&&pre->rtag)pre->rchild=suc; //修改线索return OK;}//BSTree_Delete_keyvoid Delete_BSTree(BiThrTree &T)//课本上给出的删除二叉排序树的子树T的算法,按照线索二叉树的结构作了一些改动{q=T;if(!T->ltag&&T->rtag) //结点无右子树,此时只需重接其左子树T=T->lchild;else if(T->ltag&&!T->rtag) //结点无左子树,此时只需重接其右子树T=T->rchild;else if(!T->ltag&&!T->rtag) //结点既有左子树又有右子树{p=T;r=T->lchild;while(!r->rtag){s=r;r=r->rchild; //找到结点的前驱r和r的双亲s}T->data=r->data; //用r代替T结点if(s!=T)s->rchild=r->lchild;else s->lchild=r->lchild; //重接r的左子树到其双亲结点上q=r;}//elsefree(q); //删除结点}//Delete_BSTree分析:本算法采用了先求出x结点的前驱和后继,再删除x结点的办法,这样修改线索时会比较简单,直接让前驱的线索指向后继就行了.如果试图在删除x结点的同时修改线索,则问题反而复杂化了.9.38void BSTree_Merge(BiTree &T,BiTree &S)//把二叉排序树S合并到T中{if(S->lchild) BSTree_Merge(T,S->lchild);if(S->rchild) BSTree_Merge(T,S->rchild); //合并子树Insert_Key(T,S); //插入元素}//BSTree_Mergevoid Insert_Key(Bitree &T,BTNode *S)//把树结点S插入到T的合适位置上{if(S->data>T->data){if(!T->rchild) T->rchild=S;else Insert_Key(T->rchild,S);}else if(S->data<T->data){if(!T->lchild) T->lchild=S;else Insert_Key(T->lchild,S);}S->lchild=NULL; //插入的新结点必须和原来的左右子树断绝关系S->rchild=NULL; //否则会导致树结构的混乱}//Insert_Key分析:这是一个与课本上不同的插入算法.在合并过程中,并不释放或新建任何结点,而是采取修改指针的方式来完成合并.这样,就必须按照后序序列把一棵树中的元素逐个连接到另一棵树上,否则将会导致树的结构的混乱.9.39void BSTree_Split(BiTree &T,BiTree &A,BiTree &B,int x)//把二叉排序树T分裂为两棵二叉排序树A和B,其中A的元素全部小于等于x,B的元素全部大于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_Key(A,T);else Insert_Key(B,T); //将元素结点插入合适的树中}//BSTree_Splitvoid Insert_Key(Bitree &T,BTNode *S)//把树结点S插入到T的合适位置上{if(!T) T=S; //考虑到刚开始分裂时树A和树B为空的情况else if(S->data>T->data) //其余部分与上一题同{if(!T->rchild) T->rchild=S;else Insert_Key(T->rchild,S);}else if(S->data<T->data){if(!T->lchild) T->lchild=S;else Insert_Key(T->lchild,S);}S->lchild=NULL;S->rchild=NULL;}//Insert_Key9.40typedef struct {int data;int bf;int lsize; //lsize域表示该结点的左子树的结点总数加1BlcNode *lchild,*rchild;} BlcNode,*BlcTree; //含lsize域的平衡二叉排序树类型BTNode *Locate_BlcTree(BlcTree T,int k)//在含lsize域的平衡二叉排序树T中确定第k小的结点指针{if(!T) return NULL; //k小于1或大于树结点总数if(T->lsize==k) return T; //就是这个结点else if(T->lsize>k)return Locate_BlcTree(T->lchild,k); //在左子树中寻找else return Locate_BlcTree(T->rchild,k-T->lsize); //在右子树中寻找,注意要修改k的值}//Locate_BlcTree9.41typedef struct {enum {LEAF,BRANCH} tag; //结点类型标识int keynum;BPLink parent; //双亲指针int key[MAXCHILD]; //关键字union {BPLink child[MAXCHILD];//非叶结点的孩子指针struct {rectype *info[MAXCHILD];//叶子结点的信息指针BPNode *next; //指向下一个叶子结点的链接} leaf;}} BPNode,*BPLink,*BPTree;//B+树及其结点类型Status BPTree_Search(BPTree T,int key,BPNode *ptr,int pos)//B+树中按关键字随机查找的算法,返回包含关键字的叶子结点的指针ptr以及关键字在叶子结点中的位置pos{p=T;while(p.tag==BRANCH) //沿分支向下查找{for(i=0;i<p->keynum&&key>p->key[i];i++); //确定关键字所在子树if(i==p->keynum) return ERROR; //关键字太大p=p->child[i];}for(i=0;i<p->keynum&&key!=p->key[i];i++); //在叶子结点中查找if(i==p->keynum) return ERROR; //找不到关键字ptr=p;pos=i;return OK;}//BPTree_Search9.42void TrieTree_Insert_Key(TrieTree &T,StringType key)//在Trie树T中插入字符串key,StringType的结构见第四章{q=(TrieNode*)malloc(sizeof(TrieNode));q->kind=LEAF;q->lf.k=key; //建叶子结点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) //如果最后落到分支结点(无同义词):{p->bh.ptr[ord(key[i])]=q; //直接连上叶子p->bh.num++;}else //如果最后落到叶子结点(有同义词):{r=(TrieNode*)malloc(sizeof(TrieNode)); //建立新的分支结点last->bh.ptr[ord(key[i-1])]=r; //用新分支结点取代老叶子结点和上一层的联系r->kind=BRANCH;r->bh.num=2;r->bh.ptr[ord(key[i])]=q;r->bh.ptr[ord(p->lf.k[i])]=p; //新分支结点与新老两个叶子结点相连}}//TrieTree_Insert_Key分析:当自上而下的查找结束时,存在两种情况.一种情况,树中没有待插入关键字的同义词,此时只要新建一个叶子结点并连到分支结点上即可.另一种情况,有同义词,此时要把同义词的叶子结点与树断开,在断开的部位新建一个下一层的分支结点,再把同义词和新关键字的叶子结点连到新分支结点的下一层.9.43Status TrieTree_Delete_Key(TrieTree &T,StringType key)//在Trie树T中删除字符串key{p=T;i=1;while(p&&p->kind==BRANCH&&i<=key[ 0 ]) //查找待删除元素{last=p;p=p->bh.ptr[ord(key[i])];i++;}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_Key9.44void Print_Hash(HashTable H)//按第一个字母顺序输出Hash表中的所有关键字,其中处理冲突采用线性探测开放定址法{for(i=1;i<=26;i++)for(j=i;H.elem[j].key;j=(j+1)%hashsize[sizeindex]) //线性探测if(H(H.elem[j].key)==i) printf("%s\n",H.elem[j]);}//Print_Hashint H(char *s)//求Hash函数{if(s) return s[ 0 ]-96; //求关键字第一个字母的字母序号(小写)else return 0;}//H9.45typedef *LNode[MAXSIZE] CHashTable; //链地址Hash表类型Status Build_Hash(CHashTable &T,int m)//输入一组关键字,建立Hash表,表长为m,用链地址法处理冲突. {if(m<1) return ERROR;T=malloc(m*sizeof(WORD)); //建立表头指针向量for(i=0;i<m;i++) T[i]=NULL;while((key=Inputkey())!=NULL) //假定Inputkey函数用于从键盘输入关键字{q=(LNode*)malloc(sizeof(LNode));q->data=key;q->next=NULL;n=H(key);if(!T[n]) T[n]=q; //作为链表的第一个结点else{for(p=T[n];p->next;p=p->next);p->next=q; //插入链表尾部.本算法不考虑排序问题.}}//whilereturn OK;}//Build_Hash9.46Status Locate_Hash(HashTable H,int row,int col,KeyType key,int &k)//根据行列值在Hash表表示的稀疏矩阵中确定元素key的位置k{h=2*(100*(row/10)+col/10); //作者设计的Hash函数while(H.elem[h].key&&!EQ(H.elem[h].key,key))h=(h+1)%20000;if(EQ(H.elem[h].key,key)) k=h;else k=NULL;}//Locate_Hash分析:本算法所使用的Hash表长20000,装填因子为50%,Hash函数为行数前两位和列数前两位所组成的四位数再乘以二,用线性探测法处理冲突.当矩阵的元素是随机分布时,查找的时间复杂度为O(1).数据结构辅导站返回主页。

相关文档
最新文档