二分检索的多种应用

其实,二分法真的不那么简单,尤其是二分法的各个变种。 最最简单的二分法,就是从一个排好序的数组之查找一个key值。 如下面的程序:

int search(int *arr, int n, int key)
{
    int left = 0, right = n-1;
    while(left<=right) {
        int mid = left + ((right - left) << 1);
        if (arr[mid] == key) return mid;
        else if(arr[mid] > key) right = mid - 1;
        else left = mid + 1;
    }
    return -1;
}

这个程序,相信只要是一个合格的程序员应该都会写。
稍微注意一点, 每次移动left和right指针的时候,需要在mid的基础上+1或者-1, 防止出现死循环, 程序也就能够正确的运行。

但如果条件稍微变化一下, 你还会写吗?如,数组之中的数据可能可以重复,要求返回匹配的数据的最小(或最大)的下标;更近一步, 需要找出数组中第一个大于key的元素(也就是最小的大于key的元素的)下标,等等。 这些,虽然只有一点点的变化,实现的时候确实要更加的细心。 下面列出了这些二分检索变种的实现。

1.
找出第一个与key相等的元素

int searchFirstEqual(int *arr, int n, int key)
{
    int left = 0, right = n-1;
    while(left<=right) {
        int mid = (left+right)/2;
        if(arr[mid] >= key) right = mid - 1;
        else if(arr[mid] < key) left = mid + 1;
    }
    if( left < n && arr[left] == key) return left;
    return -1;
}

2. 找出最后一个与key相等的元素

int searchLastEqual(int *arr, int n, int key)
{
    int left = 0, right = n-1;
    while(left<=right) {
        int mid = (left+right)/2;
        if(arr[mid] > key) right = mid - 1;
        else if(arr[mid] <= key) left = mid + 1;
    }
    if( right>=0 && arr[right] == key) return right;
    return -1;
}

3.
查找第一个等于或者大于Key的元素

int searchFirstEqualOrLarger(int *arr, int n, int key)
{
    int left=0, right=n-1;
    while(left<=right) {
        int mid = (left+right)/2;
        if(arr[mid] >= key) right = mid-1;
        else if (arr[mid] < key) left = mid+1;
    }
    return left;
}

4. 查找第一个大于key的元素

int searchFirstLarger(int *arr, int n, int key)
{
    int left=0, right=n-1;
    while(left<=right) {
        int mid = (left+right)/2;
        if(arr[mid] > key) right = mid-1;
        else if (arr[mid] <= key) left = mid+1;
    }
    return left;
}

5.
查找最后一个等于或者小于key的元素

int searchLastEqualOrSmaller(int *arr, int n, int key)
{
    int left=0, right=n-1;
    while(left<=right) {
        int m = (left+right)/2;
        if(arr[m] > key) right = m-1;
        else if (arr[m] <= key) left = m+1;
    }
    return right;
}

6. 查找最后一个小于key的元素

int searchLastSmaller(int *arr, int n, int key)
{
    int left=0, right=n-1;
    while(left<=right) {
        int mid = (left+right)/2;
        if(arr[mid] >= key) right = mid-1;
        else if (arr[mid] < key) left = mid+1;
    }
    return right;
}

很多的时候,应用二分检索的地方都不是直接的查找和key相等的元素,而是使用上面提到的二分检索的各个变种,熟练掌握了这些变种,当你再次使用二分检索的检索的时候就会感觉的更加的得心应手了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 22:14:31

二分检索的多种应用的相关文章

二分检索

二分检索 二分检索(Binary Search)也叫二分查找,是应用于有序表上的一种检索方法.二分检索的思想是:由于序列已经有序,故不需要顺序遍历,每次只需和序列中间位置的元素进行比较即可,以此确定下次查找的位置.显然每次都可以排除一半的元素,很高效. 二分检索伪代码 BinarySearch(Array, key) 1.low=0,high-n-1; 2.while(low<=high) 3.    mid=(low+high)/2; 4.    if(key<array[mid]) 5.

C++实现二分检索算法

C++实现二分检索算法#include <iostream>#include <iomanip>#include<stdlib.h>using namespace std;void enter(int arrayin[], int n); //输入函数void asort(int arrayin[], int n); //排序函数int Search(int number,int arraylength,int array[]); //查找函数const int N=1

二分检索函数lower_bound()和upper_bound()

二分检索函数lower_bound()和upper_bound() 一.说明 头文件:<algorithm> 二分检索函数lower_bound()和upper_bound() lower_bound():找到大于等于某值的第一次出现upper_bound():找到大于某值的第一次出现必须从小到大排序后才能用 内部查找方式为二分查找,二分查找必定需要排序 返回值为地址 二.代码及结果 1 /* 2 二分检索函数lower_bound()和upper_bound() 3 lower_bound(

(每日算法)LeetCode --- Search in Rotated Sorted Array(旋转数组的二分检索)

Search in Rotated Sorted Array I && II Leetcode 对有序数组进行二分查找(下面仅以非递减数组为例): int binarySort(int A[], int lo, int hi, int target) { while(lo <= hi) { int mid = lo + (hi - lo)/2; if(A[mid] == target) return mid; if(A[mid] < target) lo = mid + 1;

二分检索,顺序检索模板

#include <stdlib.h> #include <iostream> using namespace std; int cmp(const void *a, const void *b) { return ( *(int *)a - *(int *)b ); } int binary_search( int *a, int n, int key ) //二份检索 { qsort(a, n, sizeof(a[0]), cmp); int mid, front=0, bac

二分查找算法java实现

今天看了一下JDK里面的二分法是实现,觉得有点小问题.二分法的实现有多种今天就给大家分享两种.一种是递归方式的,一种是非递归方式的.先来看看一些基础的东西. 1.算法概念. 二分查找算法也称为折半搜索.二分搜索,是一种在有序数组中查找某一特定元素的搜索算法.请注意这种算法是建立在有序数组基础上的. 2.算法思想. ①搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束: ②如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间

查找算法总结(二分查找/二叉查找树/红黑树/散列表)

1.二分查找 二分查找时,先将被查找的键和子数组的中间键比较.如果被查找的键小于中间键,就在左子数组继续查找,如果大于中间键,就在右子数组中查找,否则中间键就是要找的元素. /** * 二分查找 */ public class BinarySearch { public static int find(int[] array, int key) { int left = 0; int right = array.length - 1; // while (left <= right)不能改为<

算法实现回顾1——二分查找

前话: 为什么写这个系列?算法的精髓除了在于算法的一个设计,更在于算法的一个好的设计.前者可能需求一个好的算法工程师,而后者则需求一个优秀的程序员.很多时候我们往往只希望去了解一种设计思路,但是对于程序员,一种优良的实现是非常重要的.实现的细节才决定成败.毕竟程序员面对和输出的都是程序,而不是思路. 引用: 你真的会二分查找吗?http://blog.csdn.net/int64ago/article/details/7425727二分查找,你真的会吗?http://www.ahathinkin

C++ primer plus读书笔记——第16章 string类和标准模板库

第16章 string类和标准模板库 1. string容易被忽略的构造函数: string(size_type n, char c)长度为n,每个字母都为c string(const string & str, size_type pos = 0, size_type n = pos)初始化为str中从pos开始到结尾的字符,或从pos开始的n个字符 string(const char *s, size_type n)初始化为s指向的前n个字符,即使超过了s的结尾: string(Iter b