数据结构--杂记-二分查找
2017-10-10 09:52
197 查看
介绍二分查找之前,首先看看简单的数值比较的两种实现;
数值比较是简单的
上面的程序在处理
数值比较的宏实现方式;
使用宏实现的大小比较,在处理
浮点数在计算机的存储和整形的存储是不太一样的,对于小数点后面的数字每一位分别表示
输出结果是:
![](https://img-blog.csdn.net/20171010101711275?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzYyOTQ4NzU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
在进行浮点数的保存和输出过程中,其实是进行了四射五入的,当然不同的编译器对于这个处理也是不同的,这只是数值存储的一种情况,特殊的在整理之后再发;
为了防止特殊情况的发生,浮点数的比较应该采用阀值的思想来进行相等性的比较;
分析二分查找算法执行过程:
1.首先函数原型需要传递的参数包括:
2.对于查找的过程包括三种情况:
1.
2.
3.
程序的执行结果
![](https://img-blog.csdn.net/20171010110933579?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzYyOTQ4NzU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
由执行结果看一个看出,程序首先找出了最右边的
来看看这种情况是如何发生的:
![](https://img-blog.csdn.net/20171010130653669?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzYyOTQ4NzU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
对于这个这种情况可以使用
*使用
代码的执行结果是:
![](https://img-blog.csdn.net/20171010134234012?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzYyOTQ4NzU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
这种方式的查找对于两个重复元素的查找是比较有效的,对于更多的重复元素还需要进行实验,在总结之后在整理;
对于二分查找时间复杂度是
数值比较是简单的
if-else-if语句的使用,先看看函数版本的实现:
int compare(int a,int b){ if(x<y) return -1; else if(x==y)return 0; else return 1; }
上面的程序在处理
int类型的数据,进行比较大小是没有错误的,在绝大多数情况下是可以运行的;
数值比较的宏实现方式;
#define COMPARE(x,y) (((x)<(y)) ? -1 :((x)==(y)) ? 0:1)
使用宏实现的大小比较,在处理
float,
double的数值时是有点小问题的;
浮点数在计算机的存储和整形的存储是不太一样的,对于小数点后面的数字每一位分别表示
1/2,1/4,1/8,1/16,浮点数的存储实际上采用的是微分的思想,也就是在无限进行数值的逼近,对于绝大多数浮点数都是可以准确进行存储并且进行比较的;
float浮点数在进行存储过程中的一个程序验证;
int main(){ float lk=2.424523525566476667; printf("%f\n",lk); double llk=2.42452352556647667; printf("%f\n",llk); }
输出结果是:
在进行浮点数的保存和输出过程中,其实是进行了四射五入的,当然不同的编译器对于这个处理也是不同的,这只是数值存储的一种情况,特殊的在整理之后再发;
为了防止特殊情况的发生,浮点数的比较应该采用阀值的思想来进行相等性的比较;
//这里是用compare变量来允许用户在进行浮点数的比较时,可以传入一个阀值来判断两个浮点数是否相等; int compare(float a,float b,float compare) { if(a<b) return -1; //fabs()如果是浮点数绝对值函数使用fabs(),如果是整型使用函数abs(); else if(fabs(a-b)<compare) return 0; else return 1; }
分析二分查找算法执行过程:
1.首先函数原型需要传递的参数包括:
array[],
searchnum,
left,
right,四个参数的意思分别是查找的有序数组,需要查找数值,查找的左边界,查找的右边界;
2.对于查找的过程包括三种情况:
1.
searchnum<array[middle]:就应该在有序数组的左边进行查找,需要改变
right的值:
right=middle-1;
2.
searchnum==array[middle]找到的数据就是需要的数据,那么直接进行返回:
return middel;
3.
searchnum>array[middle]:说明查找的数值应该在数值的右半本部分,所以应该改变
left=middle+1;
Binary_search()的实现:
#include <stdlib.h> #include <stdio.h> #include "Mystd.h" int Compare(int left, int right, int compare) { if (left < right) return -1; else if (abs(left - right) < compare) return 0; else return 1; } int Binary_search(int array[], int SearchNumber, int left, int right) { if (array == NULL || left == right) exit; int middle = 0; while (left <= right) { middle = (left + right) / 2; switch (Compare(array[middle], SearchNumber, 1)) { case -1: left = middle + 1; break; case 0: return middle; case 1: right = middle - 1; } } return -1; } int main() { int myarray[] = {1, 6, 9, 0, 3, 6, 5,3, 1, 7, 6, 9, 4}; choice_sort(myarray,sizeof(myarray)/sizeof(int)); size_t i=0; for( i=0;i<sizeof(myarray)/sizeof(int);++i) printf("%d ",myarray[i]); printf("\n"); int k = Binary_search(myarray,3,0,sizeof(myarray)/sizeof(int)); if(k==-1) printf("Not found!!"); else printf("Found it at: %d \n",k); k = Binary_search(myarray,3,0,k); if(k==-1) printf("Not found!!"); else printf("Found it at: %d \n",k); }
程序的执行结果
Binary_Search对于没有重复元素的查找是没有丝毫问题的,这里尝试处理的的是具有重复元素的查找过程;
由执行结果看一个看出,程序首先找出了最右边的
3位置是4,然后再修正之后,才找到了左边的三,如果在修正过程中发生错误,那么左边的
3很有可能找不到;
来看看这种情况是如何发生的:
对于这个这种情况可以使用
C++STL来进行尝试;
int main(){ vector<int> myarry={1,6,9,0,3,6,5,3,1,7,9,4}; sort(myarry.begin(),myarry.end()); auto it =binary_search(myarry.begin(),myarry.end(),3); if(it==0) cout << "Not found\n"; else cout << "Find position: " << it << endl; }
*使用
C++STL提供的
Binary_search仅仅可以查看是否有这个元素,如果需要得到元素的位置还需要这样;
int main() { vector<int> mytins = {1, 6, 9, 0, 3, 6, 5, 3, 1, 7, 9, 4}; pair<vector<int>::iterator, vector<int>::iterator> bounds; sort(mytins.begin(), mytins.end()); bounds = equal_range(mytins.begin(), mytins.end(), 3); cout << "bounds at positions " << (bounds.first - mytins.begin()); cout << " and " << (bounds.second - mytins.begin()) << endl; }
代码的执行结果是:
这种方式的查找对于两个重复元素的查找是比较有效的,对于更多的重复元素还需要进行实验,在总结之后在整理;
对于二分查找时间复杂度是
log2 n,查找元素还是很快速的;
相关文章推荐
- 一步一步复习数据结构和算法基础-顺序查找+二分查找
- C语言数据结构中二分查找递归非递归实现并分析
- 数据结构和算法————二分查找
- 数据结构(二分查找)
- 数据结构--二分查找(C++版)
- 数据结构:二分查找与二叉树
- 数据结构 学习笔记(四):树(上):树的表示,二分查找,二叉树,先中后层次遍历
- hdu 2141:Can you find it?(数据结构,二分查找)
- python数据结构与算法28 二分查找
- 数据结构和算法设计专题之---二分查找(Java版)
- 数据结构(Data Structure)——二分查找
- python算法和数据结构笔记--递归--二分查找
- 数据结构--顺序查找、二分查找
- 数据结构图文解析之:二分查找及与其相关的几个问题解析
- java中的数据结构--二分查找
- 数据结构--向量--二分查找
- (五)数据结构之静态查找的简单实现:顺序查找和二分查找
- 数据结构-查找-二分查找(1)有序表复杂度(lg(n))
- 考研路_数据结构_查找1_顺序查找和二分查找
- 【数据结构机试复习9】 二维数组中的查找 & 二分查找 & 寻找字符串