算法学习之查找算法:静态查找表(2)有序表查找

如果静态查找表是一个有序表,则可以使用折半查找。

折半查找的过程是:先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止。折半查找过程是以处于区间中间位置记录的关键字和给定值比较,若相等,则查找成功,若不等,则缩小范围,直至新的区间中间位置记录的关键字等于给定值或者查找区间的大小小于零时(表明查找不成功)为止。

关键字key与表中某一元素array[i]比较,有3种情况:

1、key==array[i],查找成功

2、key > array[i],待查找元素可能的范围是array[i]之前

3、key < array[i],待查找元素可能的范围是array[i]之后

以如下有序表为例,分析折半查找的方法。

有序表如下:(05,13,19,21,37,56,64,75,80,88,92)

<一>查找有序表中存在的关键字,如查找21,查找过程如下:

(05,13,19,21,37,56,64,75,80,88,92)

↑                                     ↑                                    ↑

low = 0                  mid = (low + high)/2 = 5        high = 10

① 因为array[mid] = 56 > 21,则令high = mid - 1; 说明待查元素若存在,必在区间[low, mid - 1]的范围内。

(05,13,19,21,37,56,64,75,80,88,92)

↑              ↑             ↑

low          mid         high = 5

②因为array[mid] = 19 < 21,则令low = mid + 1; 说明待查元素若存在,必在区间[mid + 1, high]的范围内。

(05,13,19,21,37,56,64,75,80,88,92)

↑      ↑

low/mid high = 5

③ 因为array[mid] = 21,说明待查元素存在。

<二>查找有序表中不存在的关键字,如查找85,查找过程如下:

(05,13,19,21,37,56,64,75,80,88,92)

↑                                     ↑                                    ↑

low = 0                  mid = (low + high)/2 = 5        high = 10

① 因为array[mid] = 56 < 85,则令low = mid + 1; 说明待查元素若存在,必在区间[mid + 1, high]的范围内。

(05,13,19,21,37,56,64,75,80,88,92)

low          mid           high

②因为array[mid] = 80 < 85,则令low = mid + 1; 说明待查元素若存在,必在区间[mid + 1, high]的范围内。

(05,13,19,21,37,56,64,75,80,88,92)

low/mid  high

③ 因为array[mid] = 88 > 85,则令high = mid - 1; 说明待查元素若存在,必在区间[low, mid -1]的范围内。

因为此时high小于low,所以查找失败。

有序表的折半查找C语言实现如下:

/*********************************************************************
Author:李冰 date:2014-9-24
Email:[email protected]
*********************************************************************/
typedef int ElemType;
#define EQ(a, b) ((a) == (b))
#define LT(a, b) ((a) < (b))
#define LQ(a, b) ((a) <= (b))

int Search_Bin(ElemType array[], int num, int length)
{
	int index_low, index_mid, index_high;
	index_low = 1;
	index_high = length;
	while(index_low <= index_high){
		index_mid = (index_low + index_high) / 2;
		if(EQ(num, array[index_mid])) return index_mid + 1;
		else if(LT(num , array[index_mid])) index_high = index_mid - 1;
		else index_low = index_mid + 1;
	}
	return -1;
}

       适用范围:对于规模较大的有序表查找,效率较高。适合很少改动但经常查找的表。

       优点:

1、折半查找的效率比顺序查找要高。

2、折半查找的时间复杂度为log2(n)

3、折半查找的平均查找长度为log2(n+1) - 1

缺点:

1、折半查找只适用于有序表

2、折半查找限于顺序存储结构,对线性链表无法有效地进行折半查找

时间: 2024-08-02 14:47:40

算法学习之查找算法:静态查找表(2)有序表查找的相关文章

算法学习笔记 KMP算法之 next 数组详解

最近回顾了下字符串匹配 KMP 算法,相对于朴素匹配算法,KMP算法核心改进就在于:待匹配串指针 i 不发生回溯,模式串指针 j 跳转到 next[j],即变为了 j = next[j]. 由此时间复杂度由朴素匹配的 O(m*n) 降到了 O(m+n), 其中模式串长度 m, 待匹配文本串长 n. 其中,比较难理解的地方就是 next 数组的求法.next 数组的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀,也可看作有限状态自动机的状态,而且从自动机的角度反而更容易推导一些. "前

算法学习之排序算法:插入排序(直接插入排序、折半插入排序、2-路插入排序)

引言: 插入排序作为最简单易于理解的排序算法,基本实现比较简单.本文详细介绍直接插入排序,并给出实现,简单的介绍折半插入排序,并给出2-路插入排序和表插入排序两种插入排序,但并未给出具体实现. 一.直接插入排序 直接插入排序的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的.记录数增1的有序表. 算法描述: 步骤1.将待排序的一组记录中的第1个记录拿出来作为一组有序的记录(当然此时该组记录仅有1个记录). 步骤2.依次将待排序的一组记录中的记录拿出来插入到前面已排好序的记录中. 步

[算法学习]A星算法

一.适用场景 在一张地图中,绘制从起点移动到终点的最优路径,地图中会有障碍物,必须绕开障碍物. 二.算法思路 1. 回溯法得到路径 (如果有路径)采用"结点与结点的父节点"的关系从最终结点回溯到起点,得到路径. 2. 路径代价的估算:F = G+H A星算法的代价计算使用了被称作是启发式的代价函数. 先说明一下各符号意义:G表示的是 ** 从起点到当前结点的实际路径代价 ** (为啥叫实际?就是已经走过了,边走边将代价计算好了):H表示 ** 当前结点到达最终结点的估计代价 ** (为

算法学习之排序算法:归并排序

"归并"的含义是将两个或两个以上的有序表组合成一个新的有序表.无论是顺序存储还是链表存储结构,都可在O(m+n)的时间量级上实现. 归并排序又是一类不同的排序方法.假设初始序列含有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个为2或1的有序子序列:再两两归并,....... ,如此重复,直至得到一个长度为n的有序序列为止. 初始关键字:[49]   [38]   [65]   [97]   [76]   [13]   [27] A       A

大话数据结构—顺序表、有序表、线性索引查找

查找 根据给定的某个值,在查找表中确定一个其关键字(唯一的标识一个记录)等于给定值的数据元素或数据记录. 静态查找:只查找,不修改元素[线性表.顺序查找.二分查找] 动态查找:查找时,插入或者删除元素[二叉排序树] 顺序表查找 顺序查找(针对静态查找表),也叫线性查找O(n),从头开始遍历,直到最后一个记录. 优化:添加哨兵 //有哨兵的顺序查找 int foo(int *a,int n,int key) { int i; a[0]=key;//哨兵 i=n; while(a[i]!=key)

经典算法学习之贪心算法

贪心算法也是用来求解最优化问题的,相比较动态规划很多问题使用贪心算法更为简单和高效,但是并不是所有的最优化问题都可以使用贪心算法来解决. 贪心算法就是在每个决策点都做出在当时看来最佳的选择. 贪心算法的设计步骤: 1.将最优化问题转换为:对其做出一次选择之后,只剩下一个问题需要求解的形式(动态规划会留下多个问题需要求解) 2.证明做出贪心选择之后,原问题总是存在最优解,即贪心算法总是安全的 3.证明做出贪心选择后,剩余的子问题满足性质:其最优解与贪心选择组合即可得到原问题的最优解,这样就得到了最

[算法学习笔记]排序算法——堆排序

堆排序 堆排序(heapsort)也是一种相对高效的排序方法,堆排序的时间复杂度为O(n lgn),同时堆排序使用了一种名为堆的数据结构进行管理. 二叉堆 二叉堆是一种特殊的堆,二叉堆是完全二叉树或者是近似完全二叉树.二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,且每个节点的左子树和右子树都是一个二叉堆. 如上图显示,(a)是一个二叉堆(最大堆), (b)是这个二叉堆在数组中的存储形式. 通过给个一个节点的下标i, 很容易计算出其父节点,左右子节点的的下标,为了方便,

算法学习之排序算法(三)(选择排序法)

1.引言 选择排序工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完. 选择排序是不稳定的排序方法.选择排序是和冒泡排序差不多的一种排序.和冒泡排序交换相连数据不一样的是,选择排序只有在确定了最小的数据之后,才会发生交换.怎么交换呢?我们可以以下面一组数据作为测试: 2, 1, 5, 4, 9 第一次排序:1, 2, 5, 4, 9 第二次排序: 1, 2, 5, 4, 9 第三次排序: 1, 2, 4, 5, 9 第四次排序:

算法学习之排序算法:堆排序

要了解堆排序,首先要了解堆的概念,因为本文主要研究堆排序的算法,此处对数据结构堆只是给出概念:n个元素的序列{k1,k2,...kn},当且仅当满足如下关系时,称之为堆. k[i] <= k[2i]且k[i] <= k[2i+1] (或 k[i] >= k[2i]且k[i] >= k[2i+1]) 比如:序列96.83.27.38.11.09(或12.36.24.85.47.30.53.91)都是堆. 如果将堆对应的一维数组看成是一个二叉树,则堆的含义表明:完全二叉树中所有非终端结

算法学习之排序算法:选择排序

选择排序:每一趟在n-i+1(i=1,2,...,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录. 一.简单选择排序 一趟选择排序操作: 通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换之. 对L[1...n]中记录进行简单选择排序的算法为:令i从1至n-1,进行n-1趟选择操作.简单选择排序过程中,所需进行记录移动的操作次数较少,然而,无论记录的初始排列如何,所需关键字间的比较次数相同.因此,总的时间复杂度为O(n^2)