【查找】有序表查找

折半查找(二分查找)

概念

每次取中间记录查找的方法。

前提

线性表中的记录必须是关键码有序(通常从小到大有序),线性表必须采用顺序存储。

基本思想

在有序表中,取中间记录作为比较对象:

  • 若给定值与中间记录的关键字相等,则查找成功;
  • 若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;
  • 若给定值大于中间记录的关键字,则在中间记录的右半区继续查找。

不断重复上述过程,直到查找成功,或所有查找区域无记录,查找失败为止。

算法实现

function Binary_Search(a,key){
    var low,high,mid;
    low = 0; /* 定义最低下标为记录首 */
    high = a.length-1; /* 定义最高下标为记录尾 */
    while (low <= high) {
        mid = parseInt((low + high) / 2); /* 折半 */
        if (key < a[mid]) { /* 若查找值比中值小 */
            high = mid - 1; /* 最高下表调整到中间下标小一位 */
        }else if(key >a[mid]){ /* 若查找值比中值大 */
            low = mid + 1; /* 最低下表调整到中间下标大一位 */
        }else{
            return mid; /* 若相等则说明 mid 即为查找到的位置 */
        }
    } 
    return a.length; /* 返回原数组长度则说明查找失败 */
}

时间复杂度分析

折半算法的时间复杂度为 O(logn)

对于需要频繁执行插入或删除操作的数据集来说,维护有序的排序会带来不小的工作量,因此不建议使用折半算法。

插值查找

基本思想

折半查找最关键的一段代码就是求中间值:

mid=low+high2=low+12(highlow)

也就是 mid 等于最低下标 low 加上最高下标 high low 的差的一半。
考虑将这个 12 改进为下面的计算方案:
mid=low+keya[low]a[high]a[low](highlow)

假设 a[11]=1,16,24,35,47,59,62,73,88,99low=0high=9a[low]=0a[high]=99 ,如果要找的是 key=16 ,按照折半的做法,需要四次才可以得到结果。
但如果用新方法: keya[low]a[high]a[low]=1619910.153mid1+0.153×(90)=2.377 ,取整 mid=2 ,则只需要两次就查找到结果了,大大提高了查找的效率。

插值查找是根据要查找的关键字 key 与查找表中最大最小记录的关键字比较后的查找方法,其核心就在于插值的计算公式: keya[low]a[high]a[low]

算法实现

/* 插值查找 */
function Interpolation_search(a,key){
    var low,high,mid;
    low = 0; /* 定义最低下标为记录首 */
    high = a.length-1; /* 定义最高下标为记录尾 */
    while (low <= high) {
        mid = parseInt(low + (key -a[low]) / (a[high]-a[low])*(high-low)); /* 插值 */
        if (key < a[mid]) { /* 若查找值比中值小 */
            high = mid - 1; /* 最高下表调整到中间下标小一位 */
        }else if(key >a[mid]){ /* 若查找值比中值大 */
            low = mid + 1; /* 最低下表调整到中间下标大一位 */
        }else{
            return mid; /* 若相等则说明 mid 即为查找到的位置 */
        }
    }
    return a.length; /* 返回原数组长度则说明查找失败 */
}

时间复杂度分析

也是 O(logn) 。但对于表长较长,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好得多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值