二分查找

二分查找(注意二分查找的前提是: 这个数组是有序的~):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int binary_search(int* a, int len, int goal, int left)    //left代表若查到多个目标,是否需要返回最左边的那个
{
    int low = 0;
    int high = len -1;
    int lastPos = -1;        //default: 没找到
    while (low <= high)
    {
        int middle = (high - low) / 2 + low;        // 直接使用(high + low) / 2 可能导致溢出
        if (a[middle] == goal)                //直接return 则 "若goal有重复==>随机返回其中一个index"
        {
            lastPos = middle;                //这里记录上次已经找到的goal,并让他继续找
            if(left)
                high = middle-1;
            else
                low = middle+1;
        }
        else if (a[middle] > goal)        //在左半边
            high = middle - 1;
        else                                                //在右半边
            low = middle + 1;
    }
    return lastPos;
}

因为二分查找需要数组提前有序,所以下面的demo使用快速排序来处理数组

int Partition(int a[], int start, int end) //返回调整后基准数的位置
{
    int i = start, j = end;
    int x = a[i]; //a[i]就是第一个坑,这里可以先安排一个a[i] <---> a[randint(start,end)]
    while (i < j)
    {
        // 坑在左边,那就先从右向左找小于x的数来填a[i]
        while(i < j && a[j] >= x)
            j--;
        if(i < j)
        {
            a[i] = a[j]; //将a[j]填到a[i]中,a[j]就形成了一个新的坑
            i++;
        }
                      // 从左向右找大于或等于x的数来填a[j]
        while(i < j && a[i] < x)
            i++;
        if(i < j)
        {
            a[j] = a[i]; //将a[i]填到a[j]中,a[i]就形成了一个新的坑
            j--;
        }
    }
    //退出时,i等于j。将x填到这个坑中。
    a[i] = x;
    return i;
}

void _qsort(int *a, int start, int end)
{
    if(start >= end)
    {
        return;
    }
    int i = Partition(a,start,end);
    _qsort(a, start, i-1);
    _qsort(a, i+1, end);
}

void Qsort(int *a, int len)
{
    if(a == NULL || len <= 0)
        return;
    int start = 0;
    int end = len -1;
    _qsort(a, start, end);
}
#define NUM 1000
int main()
{
    int i = 0;
    int *abc = malloc(NUM*sizeof(int));
    srand(0); //生成随机种子

    printf("\n====================随机生成 %d 个数==============================\n",NUM);
    for(i=0;i<NUM;i++)
    {
        abc[i] = rand()%(10*NUM);
        printf("%d ",abc[i]);
    }
    printf("\n");
    printf("\n====================快速排序后结果==============================\n");

    Qsort(abc,NUM);
    for(i=0;i<NUM;i++)
    {
        printf("%d ",abc[i]);
    }
    printf("\n");
    printf("\n====================检查快速排序结果正确性========================\n");

    for(i = 0;i<NUM-1;i++)
    {
        if(abc[i]>abc[i+1])
        {
            printf("ERROR!!!,i=%d\n",i);
            break;
        }
        if(abc[i] == abc[i+1])
        {
            printf("found a equal,i=%d,value %d\n",i,abc[i]);
        }
    }
    if(i == NUM-1)
        printf("good,sort is ok\n");
    printf("\n==================二分查找某个数字是否存在===========================\n");
    printf("\n");
    int target = 123;
    int index = binary_search(abc, NUM, target, 0);
    printf("target %d, index is %d\n",target,index);
    if(index != -1)
        printf("abc[%d] = %d",index,abc[index]);

    printf("\n==========对数组中每个数均二分查找一下,检查二分查找正确性==================\n");

    for(i=0;i<NUM;i++)
    {
        target = abc[i];
        index = binary_search(abc, NUM, target, 1);
        if(index == -1)
        {
            printf("ERROR,the value %d exist but you do not find out\n",target);
            break;
        }
        if(abc[index] != target)
        {
            printf("ERROR,you found a error index!,abc[%d] is not equals to %d\n",index,target);
            break;
        }
    }
    if(i == NUM)
        printf("binary_search check ok\n");

    printf("\n==================特殊情况检查================================\n");

    int tmp[] = {3,3,3,3,3,3,3,3,3,3,3};
    target = 3;
    index = binary_search(tmp, sizeof(tmp)/sizeof(int), target, 1);
    printf("%d\n",index);
    index = binary_search(tmp, sizeof(tmp)/sizeof(int), target, 0);
    printf("%d\n",index);
    printf("\n======================over============================\n");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值