查找与排序
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
折半查找只适用于有序表,且限于顺序存储结构, 在链式存储上是无法进行折半查找的。
15
讨论:对顺序查找除了折半改进法外,还有无其他改进算法? 答案: 有,例如分块查找法
三、分块查找(索引顺序查找)
思路:先让数据分块有序,即分成若干子表,要求 每个子表中的数据元素值都比后一块中的数值小(但 子表内部未必有序)。 然后将各子表中的最大关键字构成一个索引表, 表中还要包含每个子表的起始地址(或头指针)。
9
算法实现:
int Binsearch ( int x[],int k) //在长度为n的有序表x[n]中查找关键字为k的元素 { low=1; high=n;//置初值 while (low<=high) { mid=(low+high)/2; if (k==x[mid]) return (mid); else if ( k>x[mid]) low=mid+1;//向右找 else high=mid-1;//向左找 } return (-1); // low>high,查找不成功返回-1 }
4
一、线性查找( 又称顺序查找)
顺序查找:按顺序逐一比较,查找关键字。
对顺序结构如何线性查找?
对单链表结构如何线性查找? 对树结构如何顺序查找?
见下一例子
wk.baidu.com
从头指针开始 “顺藤摸瓜”
用各种遍历算法
5
对顺序结构查找算法的实现技巧: 把待查关键字key存入表头或表尾(俗称“哨兵”),这 样可以加快执行速度。
4)不成功的查找次数不超过树的高度.
13
例1:试构造具有9个节点的折半查找判定树,并求成功的 平均查找次数ASL.
解:构造的判定树如下图所示:
平均查找次数:
1 2 * 2 3* 4 4 * 2 ASL= 9
2 1 3
5 7 6 8
25 = 9
4
9
可以看出:折半查找判定树除最下层节点个数可能不满外, 其余各层节点个数都是满的。
//不要用:for(i=1; i<=n; i+ +) } // Search_Seq 那样太慢 //找不到=不成功,返回值必为 i=0; 找得到=成功,返回值i正好代表所找元素的位置。
return i;
优点:减少了对循环次数的判断比较
6
讨论:怎样衡量查找效率?
——用平均查找长度(ASL)衡量。 其意义:为确定数据元素在表中的位置所进行的和关键字比较次 数的期望值
如何计算ASL------平均每个数据的查找时间?
分析: 查找第1个元素所需的比较次数为1; 查找第2个元素所需的比较次数为2; …… 查找第n个元素所需的比较次数为n;
总计全部比较次数为:1+2+…+n = (1+n)n/2 因为是计算某一个元素的平均查找次数,还应当除以n, (假设查找任一元素的概率相同) 即: ASL=(1+n)/2 ,时间效率为 O(n)
全部比较总次数为1×20+2×21+3×22+4×23…+m×2m—1
=
j 1
n
j 2 j 1
11
请注意:ASL的含义是“平均每个数据的查找时间”,而上式 是n个数据查找时间的总和,所以:
1 n n 1 j 1 ASL j 2 log 2 (n 1) 1 log 2 n n j 1 n
第1块
第2块
第3块
查找步骤分两步进行:
① 对索引表使用折半查找法(因为索引表是有序表); ② 确定了待查关键字所在的子表后,在子表内采用顺序 查找法(因为各子表内部是无序表) 分块查找算法要点:块间折半查找,块内顺序查找
17
课堂练习:
题 1:对序列( 8, 10, 15, 26, 35, 47, 59, 63) 进行折半查找15,要经过 A、2 B 、3 C、4 B 次比较。 D、5
例:
22 12 13 8 9 20 33 42 44 38 24 48 60 58 74 49 86 53
16
特点:块间有序,块内无序
分块查找过程举例:
块内最大关键字 各块起始地址
22 12 13 8 9 22 1
索引表
48 7 86 13
20 33 42 44 38 24 48 60 58 74 49 86 53
有冲突! 问题:出现冲突怎么办?
H(25)=25%7=4 H(11)=11%7=4
题2:设有100个结点,用二分法查找时,最大比
较次数是
A、25
D
。
C、10 D、7
18
B、50
四、散列查找(又称哈希/hash查找)
1)哈希表的概念
2)哈希函数的构造方法 3)冲突处理方法 4)哈希表的查找及分析
19
1)哈希表的概念
哈希表:即散列存储结构。 散列法存储的基本思想:建立关键码值与其存储位置的对应 关系,或者说,由关键码的值决定数据的存储地址。 优点:查找速度极快(O(1)),查找效率与元素个数n无关!
int Search_Seq(KeyType key )
{ S[0] =key; //在顺序表S中,查找关键字与key相同的元素;
若成功,返回其位置信息,否则返回0 for( i=length; S[ i ]!=key; - - i ); //设立哨兵,可免去查找过程中每一步都要检测查找 是否超出边界。当n>1000时,查找时间将减少一半。
1. 数字分析法
2. 平方取中法
3. 除留余数法
4. 折叠法
5. 直接地址法 6. 乘余取整法 7. 随机数法
22
强调:
散列函数没有“万能”通式(故名杂凑), 要根据元素集合的特性而分别构造。
哈希方法中使用的转换函数称为哈希函数(杂凑函数) 通常关键码的集合比哈希地址集合多,因而经过哈 希函数变换后,可能将不同的关键码映射到同一个哈 希地址上,这种现象称为冲突。
8
折半查找举例: 已知如下11个元素的有序表: (05 13 19 21 37 56 64 75 80 88 92), 请查找关键字为21 和85的数据元素。
Low指向待查元素 所在区间的下界 mid指向待查元素所在 区间的中间位置 high指向待查元素所 在区间的上界
解:① 先设定3个辅助标志: low,high,mid, 显然有:mid= (low+high)/2 ② 运算步骤:
3
2.5.1 查找
基本概念:
查 找
查找成功
是一种数据结构
查找表 ——由同一类型的数据元素(或记录)构成的集合。
——查询特定元素(关键字)是否在表中。
——若表中存在特定元素,称查找成功,应输出该记录;
查找不成功 ——否则,称查找不成功(也应输出失败标志或失败位置) 静态查找 ——只查找,不改变集合内的数据元素。 动态查找 ——既查找,又可能要插入一新记录到表中,或者 要删除原有的一个记录。 关键字 ——一个记录可由一个或多个不同类型的数据项组 成,其中用来标识记录的数据项称为记录的关键字。
数据结构课程的内容
1
第二章 数据结构
2.1 基本概念
2.2 线性表
2.3 栈、队列和数组
2.4 树和二叉树
2.5 查找和排序
2
2.5 查找和排序
2.5.1 查找
一、线性查找(顺序查找) 二、对分查找(折半查找) 三、分块查找(索引顺序查找) 四、哈希查找(散列查找)
2.5.2 排序
一、选择排序(简单选择排序) 二、插入排序 (线性插入、对半插入) 三、交换排序(冒泡排序和快速排序)
14
例2:50个有序数折半查找,有多少个节点成功的查找 次数是6,其成功的平均查找次数是多少? 解:第一层一个节点,第二层2个,第三层4个,第四 层8个,第五层16个,第六层只有19个节点,可知 只有19个节点成功查找次数为6.
243 1 2 * 2 3 * 4 4 * 8 5 *16 6 *19 ASL= = 50 50
(1) low =1,high =11 ,故mid =6 ,待查范围是 [1,11]; (2) 若 S[mid] < key,说明 key[ mid+1,high] , 则令:low =mid+1; 重算 mid= (low+high)/2; (3) 若 S[mid] > key,说明 key[low ,mid-1], 则令:high =mid–1; 重算 mid ; (4)若 S[ mid ] = key,说明查找成功,元素序号 = mid; 结束条件:(1)查找成功 : S[mid] = key (2)查找不成功 : high<low (意即区间长度小于0)
7
小结: 顺序查找的特点: 优点:算法简单,且对顺序结构或链表结构均适用。 缺点: ASL 太大,时间效率太低。 如何改进?
二、对分查找(又称二分查找或折半查找)
如果记录在文件中是按关键字有序排列的,则在进行查找时 可不必逐个比较,而采用较快的跳跃式查找,即对分查找。
先给数据排序(例如按升序排好),形成有 序表,然后再将待查key与正中位置的元素相比, 若key小,则缩小至左半部分内查找;再与其中位 元素比较,每次缩小1/2的范围,直到查找成功或 失败为止。
23
冲突现象举例:
有 6 个元素的关键码分别为:( 14 , 23 , 39 , 9 , 25 , 11)。选取关键码与元素位置间的函数为H(k)=k mod 7 通过哈希函数对6个元素建立哈希表: 0
14 H(14)=14%7=0
6个元素用7个 地址应该足够!
1
2
23 9
3
4
39 25 11
5
6
如查找表:( 05 , 13 , 17, 42, 46, 55, 70, 94 )
1)与关键字的比较次数即为该结点所 在的层次数; 2)对分查找的过程恰好是 走一条从根 结点到被查结点的路径; 3) 折半查找成功的平均查找次数:
节点个数
42 13 5 17 55 46 70 94
层数 各节点成功的查找次数 各节点所在判定树中的 ASL= = 节点个数
讨论:如何进行散列查找?
根据存储时用到的散列函数H(k)表达式,立即可查到结果! 例如,查找key=9,则访问H(9)=9号地址,若内容为9则成功; 若查不到,应当设法返回一个特殊值,例如空指针或空记录。 明显缺点:空间效率低 如何解决? 精心设计Hash函数
21
2)哈希函数的构造方法
要求一:n个数据原仅占用n个地址, 虽然散列查找是以空间换时间,但仍 希望散列的地址空间尽量小(散列的 地址集中)。 要求二:无论用什么方法存储,目 的都是尽量均匀地存放元素,以尽量 减少冲突。 常用的哈希函数构造方法有:
例1:若将学生信息按如下方式存入计算机,如:
将2001011810201的所有信息存入V[01]单元; 将2001011810202的所有信息存入V[02]单元; …… 将2001011810231的所有信息存入V[31]单元。
这样一来,欲查找学号为2001011810216的信息,便可直接 访问V[16]!
20
例2 : 有数据元素序列 (14,23,39,9,25,11),若规定
每个元素k的存储地址H(k)=k,请画出存储结构图。 H(k)称为散列函数 解:根据散列函数H(k)=k ,可知元素14应当存入地址 为14的单元,元素23应当存入地址为23的单元,……, 对应散列存储表(哈希表)如下: 地址 … 9 … 11 … 14 … 23 24 25 … 39 … 25 9 11 14 23 39 内容
10
讨论: 如何计算二分查找的时间效率(ASL)? 推 导 过 程
经1次比较就查找成功的元素有1个(20),即中间值; 经2次比较就查找成功的元素有2个(21),即1/4处和3/4处; 3次比较就查找成功的元素有4个(22),即1/8,3/8, 5/8,7/8处 4次比较就查找成功的元素有8个(23),即1/16处,3/16处…… …… 则第m次比较时查找成功的元素应该有(2m-1)个。 注:为方便起见,假设表中经m次比较后全部元素刚好是 2m-1 个,此时暂不讨论第m次比较后还有剩余元素的情况。
课堂练习(多项选择):
应用:折半查找过程与在二叉排序树上进行查找的过程类似。 有了对分查找的判定树,查找效率高(折半查找O(log2n))
使用折半查找算法时,要求被查文件: A.采用链式存贮结构 B.记录的长度≤128 C.采用顺序存贮结构 D.记录按关键字递增有序
√ √
12
折半查找判定树
因查找文件中各个记录的关键字比较次数与待查记录在文件中的相 对位置有关,若把比较次数相同的记录的关键字放在同一层次,各层之 间用分支相连,可得到一棵二叉树。
15
讨论:对顺序查找除了折半改进法外,还有无其他改进算法? 答案: 有,例如分块查找法
三、分块查找(索引顺序查找)
思路:先让数据分块有序,即分成若干子表,要求 每个子表中的数据元素值都比后一块中的数值小(但 子表内部未必有序)。 然后将各子表中的最大关键字构成一个索引表, 表中还要包含每个子表的起始地址(或头指针)。
9
算法实现:
int Binsearch ( int x[],int k) //在长度为n的有序表x[n]中查找关键字为k的元素 { low=1; high=n;//置初值 while (low<=high) { mid=(low+high)/2; if (k==x[mid]) return (mid); else if ( k>x[mid]) low=mid+1;//向右找 else high=mid-1;//向左找 } return (-1); // low>high,查找不成功返回-1 }
4
一、线性查找( 又称顺序查找)
顺序查找:按顺序逐一比较,查找关键字。
对顺序结构如何线性查找?
对单链表结构如何线性查找? 对树结构如何顺序查找?
见下一例子
wk.baidu.com
从头指针开始 “顺藤摸瓜”
用各种遍历算法
5
对顺序结构查找算法的实现技巧: 把待查关键字key存入表头或表尾(俗称“哨兵”),这 样可以加快执行速度。
4)不成功的查找次数不超过树的高度.
13
例1:试构造具有9个节点的折半查找判定树,并求成功的 平均查找次数ASL.
解:构造的判定树如下图所示:
平均查找次数:
1 2 * 2 3* 4 4 * 2 ASL= 9
2 1 3
5 7 6 8
25 = 9
4
9
可以看出:折半查找判定树除最下层节点个数可能不满外, 其余各层节点个数都是满的。
//不要用:for(i=1; i<=n; i+ +) } // Search_Seq 那样太慢 //找不到=不成功,返回值必为 i=0; 找得到=成功,返回值i正好代表所找元素的位置。
return i;
优点:减少了对循环次数的判断比较
6
讨论:怎样衡量查找效率?
——用平均查找长度(ASL)衡量。 其意义:为确定数据元素在表中的位置所进行的和关键字比较次 数的期望值
如何计算ASL------平均每个数据的查找时间?
分析: 查找第1个元素所需的比较次数为1; 查找第2个元素所需的比较次数为2; …… 查找第n个元素所需的比较次数为n;
总计全部比较次数为:1+2+…+n = (1+n)n/2 因为是计算某一个元素的平均查找次数,还应当除以n, (假设查找任一元素的概率相同) 即: ASL=(1+n)/2 ,时间效率为 O(n)
全部比较总次数为1×20+2×21+3×22+4×23…+m×2m—1
=
j 1
n
j 2 j 1
11
请注意:ASL的含义是“平均每个数据的查找时间”,而上式 是n个数据查找时间的总和,所以:
1 n n 1 j 1 ASL j 2 log 2 (n 1) 1 log 2 n n j 1 n
第1块
第2块
第3块
查找步骤分两步进行:
① 对索引表使用折半查找法(因为索引表是有序表); ② 确定了待查关键字所在的子表后,在子表内采用顺序 查找法(因为各子表内部是无序表) 分块查找算法要点:块间折半查找,块内顺序查找
17
课堂练习:
题 1:对序列( 8, 10, 15, 26, 35, 47, 59, 63) 进行折半查找15,要经过 A、2 B 、3 C、4 B 次比较。 D、5
例:
22 12 13 8 9 20 33 42 44 38 24 48 60 58 74 49 86 53
16
特点:块间有序,块内无序
分块查找过程举例:
块内最大关键字 各块起始地址
22 12 13 8 9 22 1
索引表
48 7 86 13
20 33 42 44 38 24 48 60 58 74 49 86 53
有冲突! 问题:出现冲突怎么办?
H(25)=25%7=4 H(11)=11%7=4
题2:设有100个结点,用二分法查找时,最大比
较次数是
A、25
D
。
C、10 D、7
18
B、50
四、散列查找(又称哈希/hash查找)
1)哈希表的概念
2)哈希函数的构造方法 3)冲突处理方法 4)哈希表的查找及分析
19
1)哈希表的概念
哈希表:即散列存储结构。 散列法存储的基本思想:建立关键码值与其存储位置的对应 关系,或者说,由关键码的值决定数据的存储地址。 优点:查找速度极快(O(1)),查找效率与元素个数n无关!
int Search_Seq(KeyType key )
{ S[0] =key; //在顺序表S中,查找关键字与key相同的元素;
若成功,返回其位置信息,否则返回0 for( i=length; S[ i ]!=key; - - i ); //设立哨兵,可免去查找过程中每一步都要检测查找 是否超出边界。当n>1000时,查找时间将减少一半。
1. 数字分析法
2. 平方取中法
3. 除留余数法
4. 折叠法
5. 直接地址法 6. 乘余取整法 7. 随机数法
22
强调:
散列函数没有“万能”通式(故名杂凑), 要根据元素集合的特性而分别构造。
哈希方法中使用的转换函数称为哈希函数(杂凑函数) 通常关键码的集合比哈希地址集合多,因而经过哈 希函数变换后,可能将不同的关键码映射到同一个哈 希地址上,这种现象称为冲突。
8
折半查找举例: 已知如下11个元素的有序表: (05 13 19 21 37 56 64 75 80 88 92), 请查找关键字为21 和85的数据元素。
Low指向待查元素 所在区间的下界 mid指向待查元素所在 区间的中间位置 high指向待查元素所 在区间的上界
解:① 先设定3个辅助标志: low,high,mid, 显然有:mid= (low+high)/2 ② 运算步骤:
3
2.5.1 查找
基本概念:
查 找
查找成功
是一种数据结构
查找表 ——由同一类型的数据元素(或记录)构成的集合。
——查询特定元素(关键字)是否在表中。
——若表中存在特定元素,称查找成功,应输出该记录;
查找不成功 ——否则,称查找不成功(也应输出失败标志或失败位置) 静态查找 ——只查找,不改变集合内的数据元素。 动态查找 ——既查找,又可能要插入一新记录到表中,或者 要删除原有的一个记录。 关键字 ——一个记录可由一个或多个不同类型的数据项组 成,其中用来标识记录的数据项称为记录的关键字。
数据结构课程的内容
1
第二章 数据结构
2.1 基本概念
2.2 线性表
2.3 栈、队列和数组
2.4 树和二叉树
2.5 查找和排序
2
2.5 查找和排序
2.5.1 查找
一、线性查找(顺序查找) 二、对分查找(折半查找) 三、分块查找(索引顺序查找) 四、哈希查找(散列查找)
2.5.2 排序
一、选择排序(简单选择排序) 二、插入排序 (线性插入、对半插入) 三、交换排序(冒泡排序和快速排序)
14
例2:50个有序数折半查找,有多少个节点成功的查找 次数是6,其成功的平均查找次数是多少? 解:第一层一个节点,第二层2个,第三层4个,第四 层8个,第五层16个,第六层只有19个节点,可知 只有19个节点成功查找次数为6.
243 1 2 * 2 3 * 4 4 * 8 5 *16 6 *19 ASL= = 50 50
(1) low =1,high =11 ,故mid =6 ,待查范围是 [1,11]; (2) 若 S[mid] < key,说明 key[ mid+1,high] , 则令:low =mid+1; 重算 mid= (low+high)/2; (3) 若 S[mid] > key,说明 key[low ,mid-1], 则令:high =mid–1; 重算 mid ; (4)若 S[ mid ] = key,说明查找成功,元素序号 = mid; 结束条件:(1)查找成功 : S[mid] = key (2)查找不成功 : high<low (意即区间长度小于0)
7
小结: 顺序查找的特点: 优点:算法简单,且对顺序结构或链表结构均适用。 缺点: ASL 太大,时间效率太低。 如何改进?
二、对分查找(又称二分查找或折半查找)
如果记录在文件中是按关键字有序排列的,则在进行查找时 可不必逐个比较,而采用较快的跳跃式查找,即对分查找。
先给数据排序(例如按升序排好),形成有 序表,然后再将待查key与正中位置的元素相比, 若key小,则缩小至左半部分内查找;再与其中位 元素比较,每次缩小1/2的范围,直到查找成功或 失败为止。
23
冲突现象举例:
有 6 个元素的关键码分别为:( 14 , 23 , 39 , 9 , 25 , 11)。选取关键码与元素位置间的函数为H(k)=k mod 7 通过哈希函数对6个元素建立哈希表: 0
14 H(14)=14%7=0
6个元素用7个 地址应该足够!
1
2
23 9
3
4
39 25 11
5
6
如查找表:( 05 , 13 , 17, 42, 46, 55, 70, 94 )
1)与关键字的比较次数即为该结点所 在的层次数; 2)对分查找的过程恰好是 走一条从根 结点到被查结点的路径; 3) 折半查找成功的平均查找次数:
节点个数
42 13 5 17 55 46 70 94
层数 各节点成功的查找次数 各节点所在判定树中的 ASL= = 节点个数
讨论:如何进行散列查找?
根据存储时用到的散列函数H(k)表达式,立即可查到结果! 例如,查找key=9,则访问H(9)=9号地址,若内容为9则成功; 若查不到,应当设法返回一个特殊值,例如空指针或空记录。 明显缺点:空间效率低 如何解决? 精心设计Hash函数
21
2)哈希函数的构造方法
要求一:n个数据原仅占用n个地址, 虽然散列查找是以空间换时间,但仍 希望散列的地址空间尽量小(散列的 地址集中)。 要求二:无论用什么方法存储,目 的都是尽量均匀地存放元素,以尽量 减少冲突。 常用的哈希函数构造方法有:
例1:若将学生信息按如下方式存入计算机,如:
将2001011810201的所有信息存入V[01]单元; 将2001011810202的所有信息存入V[02]单元; …… 将2001011810231的所有信息存入V[31]单元。
这样一来,欲查找学号为2001011810216的信息,便可直接 访问V[16]!
20
例2 : 有数据元素序列 (14,23,39,9,25,11),若规定
每个元素k的存储地址H(k)=k,请画出存储结构图。 H(k)称为散列函数 解:根据散列函数H(k)=k ,可知元素14应当存入地址 为14的单元,元素23应当存入地址为23的单元,……, 对应散列存储表(哈希表)如下: 地址 … 9 … 11 … 14 … 23 24 25 … 39 … 25 9 11 14 23 39 内容
10
讨论: 如何计算二分查找的时间效率(ASL)? 推 导 过 程
经1次比较就查找成功的元素有1个(20),即中间值; 经2次比较就查找成功的元素有2个(21),即1/4处和3/4处; 3次比较就查找成功的元素有4个(22),即1/8,3/8, 5/8,7/8处 4次比较就查找成功的元素有8个(23),即1/16处,3/16处…… …… 则第m次比较时查找成功的元素应该有(2m-1)个。 注:为方便起见,假设表中经m次比较后全部元素刚好是 2m-1 个,此时暂不讨论第m次比较后还有剩余元素的情况。
课堂练习(多项选择):
应用:折半查找过程与在二叉排序树上进行查找的过程类似。 有了对分查找的判定树,查找效率高(折半查找O(log2n))
使用折半查找算法时,要求被查文件: A.采用链式存贮结构 B.记录的长度≤128 C.采用顺序存贮结构 D.记录按关键字递增有序
√ √
12
折半查找判定树
因查找文件中各个记录的关键字比较次数与待查记录在文件中的相 对位置有关,若把比较次数相同的记录的关键字放在同一层次,各层之 间用分支相连,可得到一棵二叉树。