数据结构之查找(三)——折半查找(二分查找)

  • 折半查找:每次将待查记录所在区间缩小一半。
  • 具体查找过程: 在一个非递减的有序表中,查找值为21的元素。
    在这里插入图片描述
    1.在表的两端设置两个指针high和low,
    在这里插入图片描述
    2.计算中间位置:mid=(low+high)/2。若关键字的值小于中间位置的值,则在前半区找。即,key<mid,则:high=mid+1。
    在这里插入图片描述
    3.再计算中间位置:mid=(low+high)/2。若关键字的值大于中间位置的值,则在后半区找。即,key>mid,则:low=mid+1。
    在这里插入图片描述
    4.再计算中间位置:mid=(low+high)/2。若关键字的值等于中间位置的值,则说明找到。即,key==mid,则:找到。
    在这里插入图片描述

若表中没有元素等于key,例如上表中若查找值为63的元素,重复上述步骤,直到high<low时,结束,此时说明未找到。
在这里插入图片描述

  • 算法步骤(非递归)

    • 设表长为n,low、high和mid分别指向待查元素所在区间的上界、下界和中点,key为给定的要查找的值:
    • 初始时,令low=1,high=n,mid=(low+high)/2
    • 让k与mid指向的记录比较
      • 若key==R[mid].key,查找成功
      • 若key<R[mid].key,则high=mid-1
      • 若key>R[mid].key,则low=mid+1
    • 重复上述操作,直至low>high时,查找失败。
  • 算法描述——非递归实现

int Search_Bin(SSTable ST, KeyType key)
{
	low = 1;                              //置区间初值
	high = ST.length;
	while (low<=high)
	{
		mid = (low + high) / 2;
		if (ST.R[mid].key == key)         //直到待查元素
			return mid;
		else if (key < ST.R[mid].key)     //缩小查找区间
			high = mid - 1;               //继续在前半区间进行查找
		else
			low = mid + 1;                //继续在后半区间进行查找
	}
	return 0;                             //顺序表中不存在待查元素,返回0
}
  • 算法描述——递归实现
int Search_Bin(SSTable ST, KeyType key, int low, int high)
{
	if (low > high)                      //查找不到时返回0
		return 0;
	mid = (low + high) / 2;
	if (key == ST.elem[mid].key)
		return mid;
	else if (key < ST.elem[mid].key)
	{
		high = mid - 1;
		Search_Bin(ST, key, low, high);  //递归在前半区进行查找
	}
	else
	{
		low = mid + 1;
		Search_Bin(ST, key, low, high);   //递归在后半区进行查找
	}
}
  • 性能分析——判定树
    例如有如下的有序表,其每个元素的查找次数如下,
    在这里插入图片描述
    C i C_i Ci表示每个元素的查找次数。

    上图中的每个结点从查找次数的角度来看,可以改写成树的结构——判定树,如下图,
    在这里插入图片描述
    在这里插入图片描述
    圆形——内部点,代表查找成功的情况。
    矩形——外结点,代表查找不成功的情况。

    • 查找成功:
      比较次数=路径上的结点数=结点的层数
      比 较 次 数 ≤ 树 的 深 度 = ⌊ log ⁡ 2 n + 1 ⌋ 比较次数 \le 树的深度 = \left\lfloor {\log _2^n + 1} \right\rfloor =log2n+1
    • 查找不成功:
      比较次数=路径上的内部结点数
      比 较 次 数 ≤ ⌊ log ⁡ 2 n + 1 ⌋ 比较次数 \le \left\lfloor {\log _2^n + 1} \right\rfloor log2n+1
    • 平均查找长度ASL(成功时):
      设表长 n = 2 n − 1 n=2^n-1 n=2n1,则 h = log ⁡ 2 n + 1 h = \log _2^{n + 1} h=log2n+1(此时,判定树为深度=h的满二叉树),且表中每个记录的查找概率相等: P i = 1 / n P_i=1/n Pi=1/n,则ASL为,
      A S L = 1 n ∑ j = 1 h j ⋅ 2 j − 1 = n + 1 n log ⁡ 2 n + 1 − 1 ≈ log ⁡ 2 n + 1 − 1 ( n &gt; 50 ) ASL = \frac{1}{n}\sum\limits_{j = 1}^h {j \cdot {2^{j - 1}}} = \frac{{n + 1}}{n}\log _2^{n + 1} - 1 \approx \log _2^{n + 1} - 1(n &gt; 50) ASL=n1j=1hj2j1=nn+1log2n+11log2n+11(n>50)
      其中j表示第j层的每个结点要比较的次数, 2 j − 1 2^{j-1} 2j1表示第j层的结点数。
  • 优缺点:

    • 优点:效率比顺序表高,时间复杂度为 O ( l o g n ) O(logn) O(logn)
    • 缺点:只适用于有序表,且限于顺序存储结构(对线性链表无效)
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值