逻辑清晰、简单的二分查找
2014-03-05 10:43
267 查看
本文实现了以下功能,并作了简单的分析,逻辑清晰,简单,各个代码维护了一个相似的结构。
1)二分查找元素key的下标,如无 return -1
2)二分查找返回key(可能有重复)第一次出现的下标,如无return -1
3)二分查找返回key(可能有重复)最后一次出现的下标,如无return -1
4)二分查找返回刚好小于key的元素下标,如无return -1
5)二分查找返回刚好大于key的元素下标,如无return -1
测试代码来自 二分查找,你真的会吗?
测试代码如下:
1)二分查找元素key的下标,如无 return -1
2)二分查找返回key(可能有重复)第一次出现的下标,如无return -1
3)二分查找返回key(可能有重复)最后一次出现的下标,如无return -1
4)二分查找返回刚好小于key的元素下标,如无return -1
5)二分查找返回刚好大于key的元素下标,如无return -1
测试代码来自 二分查找,你真的会吗?
#include<stdio.h> #include<stdlib.h> /* bisearch 寻找key下标,不存在 return -1 */ int bisearch(int *arr, int b, int e, int v) { int min=b,max=e,mid; while(min<=max) { mid = min + (max-min) /2; if (arr[mid] == v) return mid; else if(arr[mid]<v) min = mid +1; else max = mid -1; } return -1; } /* bisearch_min 返回key(可能有重复)第一次出现的下标,如无return -1*/ /* 分析 实际上循环过程维持[0,min-1]<v;[max+1, n-1]>=v. 在退出循环时,必然为min=max+1;如下图 a[1],a[2],a[3],....a[i-1],a[i],a[i+1],...,a ^ ^ | | max min 所以循环退出后arr[min]为数组中>=v的第一个元素,判断其是否等于v即可。 但需要注意,当v大于数组中的最大值时,当退出循环时,min>e,需判断这一情况。 */ int bisearch_min(int *arr, int b, int e, int v) { int min=b,max=e,mid; while(min<=max) { mid = min + (max-min) /2; if (arr[mid] < v) min = mid +1; else max = mid -1; } if (!(min > e) && (arr[min]==v)) // when arr[b]>v, max = b-1; return min; else return -1; } /* bisearch_max 返回key(可能有重复)最后一次出现的下标,如无return -1*/ /* 分析 实际上循环过程维持[0,min-1]<=v;[max+1, n-1]>v. 在退出循环时,必然为min=max+1;如下图 a[1],a[2],a[3],....a[i-1],a[i],a[i+1],...,a ^ ^ | | max min 所以循环退出后arr[max]为数组中<=v的最大元素,判断其是否等于v即可。 但需要注意,当v小于数组中的最小值时,当退出循环时,max<b,需判断这一情况。 */ int bisearch_max(int *arr, int b, int e, int v) { int min=b,max=e,mid; while(min<=max) { mid = min + (max-min) /2; if (arr[mid] <= v) min = mid +1; else max = mid -1; } if (!(max < b) && (arr[max]==v)) // when arr[b]>v, max = b-1; return max; else return -1; } /* bisearch_justsmall 返回刚好小于key的元素下标,如无return -1*/ /* 分析 实际上循环过程维持[0,min-1]<v;[max+1, n-1]>=v. 在退出循环时,必然为min=max+1;如下图 a[1],a[2],a[3],....a[i-1],a[i],a[i+1],...,a ^ ^ | | max min 所以循环退出后arr[max]为数组中刚好小于v的第一个元素。 但需要注意,当v小于数组中的最小值时,当退出循环时,max<b,需判断这一情况。 */ int bisearch_justsmall(int *arr, int b, int e, int v) { int min=b,max=e,mid; while(min<=max) { mid = min + (max-min) /2; if (arr[mid] < v) min = mid +1; else max = mid -1; } if (!(max < b)) return max; else return -1; } /* bisearch_justgreat 返回刚好大于key的元素下标,如无return -1 */ /* 分析 实际上循环过程维持[0,min-1]<=v;[max+1, n-1]>v. 在退出循环时,必然为min=max+1;如下图 a[1],a[2],a[3],....a[i-1],a[i],a[i+1],...,a ^ ^ | | max min 所以循环退出后arr[min]为数组中刚好大于v的第一个元素。 但需要注意,当v大于数组中的最大值时,当退出循环时,min>e,需判断这一情况。 */ int bisearch_justgreat(int *arr, int b, int e, int v) { int min=b,max=e,mid; while(min<=max) { mid = min + (max-min) /2; if (arr[mid] <= v) min = mid +1; else max = mid -1; } if (!(min > e)) return min; else return -1; }
测试代码如下:
#define N 20 // 测试数组大小 void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } void my_qsort(int *arr, int left, int right) { int i; int temp; if(left >= right) return; temp = left; for (i= left+1; i<=right; i++) { if (arr[i]<arr[left]) swap(&arr[++temp], &arr[i]); } swap(&arr[temp], &arr[left]); my_qsort(arr, left, temp-1); my_qsort(arr, temp+1, right); } void outputarr(int * arr, int len) { int i; for(i = 0; i < len; ++i) printf("%2d ", arr[i]); printf("\n"); } void main() { int testcase = 0; int * arr = malloc(sizeof(int)*N); int i,key; printf("input test times:\n"); scanf("%d", &testcase); srand(1); // 设置随机种子 while(testcase--) { for(i = 0; i < N; ++i) // 随机生成数组 { arr[i] = rand() % (N); } key = rand() % (N); outputarr(arr,N); my_qsort(arr, 0, N-1); // 排序 outputarr(arr,N); for(i = 0; i < N; ++i) printf("%2d ", i); printf("\n"); printf("binsearch: key-%d %d\n", key, bisearch(arr,0,N-1,key)); printf("binsearch_min: key-%d %d\n", key, bisearch_min(arr,0,N-1,key)); printf("binsearch_max: key-%d %d\n", key, bisearch_max(arr,0,N-1,key)); printf("binsearch_justsmall: key-%d %d\n", key, bisearch_justsmall(arr,0,N-1,key)); printf("binsearch_jus 4000 tgreat: key-%d %d\n", key, bisearch_justgreat(arr,0,N-1,key)); } free(arr); }
相关文章推荐
- 翻翻git之---逻辑清晰,简单好用的App内部锁控件 PinLockView
- Android特效专辑(九)——仿微信雷达搜索好友特效,逻辑清晰实现简单
- 二分查找的简单实现
- 两种简单查找算法之顺序查找和二分查找
- 二分查找,要注意的地方--写一个正确的二分查找,并不简单
- 翻翻git之---逻辑清晰,简单好用的App内部锁控件 PinLockView
- 第十四回 基础才是重中之重~委托实例的几种定义方式(规规矩矩method,逻辑简单delegate,层次清晰lambda)
- 简单的猜数字游戏,二分查找,杨辉三角
- 冒泡排序,简单插入排序,快速排序,二分查找的JAVA实现
- 查找(一)史上最简单清晰的红黑树解说
- 二分查找真的有你想象中那么简单吗?
- 【Cuda并行编程之一】二分查找的探究以及Cuda的简单实现&&相关面试题介绍
- 一个简单的js队列,逻辑很清晰
- 查找(一)史上最简单清晰的红黑树讲解
- (五)数据结构之静态查找的简单实现:顺序查找和二分查找
- 查找(一)史上最简单清晰的红黑树讲解
- java简单算法(二分查找 冒泡排序 判断是否为素数)
- 基础才是重中之重~委托实例的几种定义方式(规规矩矩method,逻辑简单delegate,层次清晰lambda
- 二分查找的简单应用
- CPP一个简单二分查找(查找元素是类对象)