返回介绍

8.4.1 折半查找

发布于 2024-08-19 23:28:45 字数 2756 浏览 0 评论 0 收藏 0

我们在讲树结构的二叉树定义(本书第6.5节)时,曾经提到过一个小游戏,我在纸上已经写好了一个100以内的正整数数字请你猜,问几次可以猜出来,当时已经介绍了如何最快猜出这个数字。我们把这种每次取中间记录查找的方法叫做折半查找,如图8-4-1所示。

图8-4-1

折半查找(Binary Search)技术,又称为二分查找。它的前提是线性表中的记录必须是关键码有序(通常从小到大有序),线性表必须采用顺序存储。折半查找的基本思想是:在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区继续查找。不断重复上述过程,直到查找成功,或所有查找区域无记录,查找失败为止。

假设我们现在有这样一个有序表数组{0,1,16,24,35,47,59,62,73,88,99},除0下标外共10个数字。对它进行查找是否存在62这个数。我们来看折半查找的算法是如何工作的。

/* 折半查找 */
int Binary_Search(int *a, int n, int key)
{
    int low, high, mid;
    /* 定义最低下标为记录首位 */
    low = 1;                       
    /* 定义最高下标为记录末位 */
    high = n;                      
    while (low <= high)
    {
        /* 折半 */
        mid = (low + high) / 2;    
        /* 若查找值比中值小 */
        if (key < a[mid])          
           /* 最高下标调整到中位下标小一位 */
           high = mid - 1;        
        /* 若查找值比中值大 */
        else if (key > a[mid])     
            /* 最低下标调整到中位下标大一位 */
            low = mid + 1;         
        else
            /* 若相等则说明mid即为查找到的位置 */
            return mid;            
    }
    return 0;
}

1.程序开始运行,参数a={0,1,16,24,35,47,59,62,73,88,99},n=10,key=62,第3~5行,此时low=1,high=10,如图8-4-2所示。

图8-4-2

2.第6~15行循环,进行查找。

3.第8行,mid计算得5,由于a[5]=47<key,所以执行了第12行,low=5+1=6,如图8-4-3所示。

图8-4-3

4.再次循环,mid=(6+10)/2=8,此时a[8]=73>key,所以执行第10行,high=8-1=7,如图8-4-4所示。

图8-4-4

5.再次循环,mid=(6+7)/2=6,此时a[6]=59<key,所以执行12行,low=6+1=7,如图8-4-5所示。

图8-4-5

6.再次循环,mid=(7+7)/2=7,此时a[7]=62=key,查找成功,返回7。

该算法还是比较容易理解的,同时我们也能感觉到它的效率非常高。但到底高多少?关键在于此算法的时间复杂度分析。

首先,我们将这个数组的查找过程绘制成一棵二叉树,如图8-4-6所示,从图上就可以理解,如果查找的关键字不是中间记录47的话,折半查找等于是把静态有序查找表分成了两棵子树,即查找结果只需要找其中的一半数据记录即可,等于工作量少了一半,然后继续折半查找,效率当然是非常高了。

图8-4-6

我们之前6.6节讲的二叉树的性质4,有过对“具有n个结点的完全二叉树的深度为。”性质的推导过程。在这里尽管折半查找判定二叉树并不是完全二叉树,但同样相同的推导可以得出,最坏情况是查找到关键字或查找失败的次数为。

有人还在问最好的情况?那还用说吗,当然是1次了。

因此最终我们折半算法的时间复杂度为O(logn),它显然远远好于顺序查找的O(n)时间复杂度了。

不过由于折半查找的前提条件是需要有序表顺序存储,对于静态查找表,一次排序后不再变化,这样的算法已经比较好了。但对于需要频繁执行插入或删除操作的数据集来说,维护有序的排序会带来不小的工作量,那就不建议使用。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文