用二叉树描述二分算法,一种直观易记思路

二分查找法

也叫折半查找算法,在一个有序序列R[1,...,n]中,将待查元素(Key)的值和序列的中间位置(标记为mid)的值进行比较,如果相等,则查找成功;如果Key>R[mid].key,说明待查元素的值在R[mid+1,..,n]后半区间内,那么只需要在后半区间查找就可以了;如果Key<R[mid].key,说明待查找元素的值在R[0,mid-1]前半区间内,那么只需要在前半区间插件即可,这样逐步缩小查找范围,直到查找成功或者区间为空时失败为止。

如何用二叉树描述?

假设有一个非重复的有序序列长度为12,以当前查找区间的中间位置序号作为根结点,左半区间和右半区间序号分别为根的左右子树上的结点,这样就构成了二叉判定树。

  1. 首先,使用公式\left \lfloor \frac{\left ( min+max \right )}{2} \right \rfloor(其中\left \lfloor \right \rfloor表示向下取整,min,max分别表示区间的最左最右序号)计算出根节点;
  2. 假设第一步中求的中间数是n,则左右半区间分别为\left [ min,n-1 \right ]\left [ n+1,max \right ]
  3. 根据步骤1计算出根节点为6,根据步骤2求得左右半区间分别为\left [ 1,5 \right ]\left [ 7,12 \right ]
  4. 使用步骤1中的公式\left \lfloor \frac{\left ( min+max \right )}{2} \right \rfloor继续求 \left [ 1,5 \right ]\left [ 7,12 \right ] 两区间的中间数,分别为3和9,根节点为6的左右子数结点分别为3、9;
  5. 重复步骤12,直到构造二叉树结束为止。

 最后构造出具有12个节点的二叉判定树如下图所示:

从二叉判定树可以看出,查找成功时,折半查找的过程恰好走了一条从根节点到被查找结点的路径,与待查找Key进行比较的次数即为被查找结点在树中的层数。因此,二分查找在查找成功时比较次数最多不超过二叉判定树的深度,而具有n个结点的二叉判定树的深度为\left \lfloor log_{2}n \right \rfloor+1,也就是说,二分查找成功时和给定待查找值进行比较次数最多是\left \lfloor log_{2}n \right \rfloor+1。所以时间复杂度为O(log_{2}n)

 代码实现

这种二分法一般性,都可以递归和非递归去实现,两种方式实现如下:

使用非递归实现

int SpSearch(int *arr, int min,int max,int key)
{
    int mid;
    while(min <= max)
    {
        mid = (min + max) / 2;
        if (key == arr[mid]) return mid;
        else if (key < arr[mid]) max = mid - 1; // 走左区间
        else min = mid + 1; // 走右区间
    }
    return -1;
}

使用递归实现

int SpSearch(int arr[], int min,int max,int key)
{
    int mid;
    if ( min <= max) 
    {
        mid = (min + max) / 2;
        if (key == arr[mid])  return mid;
        else if (key < arr[mid]) return SpSearch(arr,min,mid-1,key);// 走左区间
        else return SpSearch(arr,mid+1,max,key); // 走右区间
    }

}

总结

  • 二分查找相对于顺序查找算法效率要高得多,但要求查找序列必须顺序存储且有序。当需要对表进行插入或者删除操作时,需要移动大量的元素。所以二分查找适合查找序列不经常变动且有频繁进行查找操作的情况,当然数据量大的有序非常适合该算法。
  • 二分查找算法是分治法的一种思路,大事化小,分而治之。在实际应用中有很大的用途,比如,二分法求平方根,二分法堆排序、快速排序等;
  • 有时候总是陷入代码思考而无法自拔,没法将数据结构的知识和实际应用串联起来。自从发现二叉树能这么大有用处,激起我重新复习数据结构和算法的知识,并用新的方法看待,确实有一种新的收获。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值