[数组]折半查找原理:
折半顾名思义就是中间,即取该数组中的中间的那个值arr[mid],与需要查找的key数作判断,先判断是否等于,否则判断key>arr[mid]或者key<arr[mid],大于则最小值需要重新指向原中间值后一个元素,小于则最大值需要重新指向中间值前一个元素,即判断大于则最小值往右边移,判断小于则最大值往左边移,然后继续取间值进行判断是否等于...否则继续判断key>arr[mid]或者key<arr[mid],直到找到符合的值,或没找到符合的值,返回结果
写代码时发生过的错误:
1.数组必须为有序的数组
2.无法查找对应值的时候,继续折半的话,并不只是min或者max重新指向了,还必须重新计算mid的值
3.循环体用错
4.min>max理解错误,误以为必须单纯的一直往最左或最右移动,没考虑到运行时,min和max都是有机会变化的,所以min>max很正常。
示例:
以下有一组数 int [9] arr ={2,4,7,15,25,37,56,85,152,477};
需要查找的是152
min初始化为0
max初始化为arr.length-1 (这里要拿的是数组角标值,数组从arr[0]开始,所以需要元素个数减去1)
mid=(max+min)/2
所以首先取中间值是 mid = arr[4]=25,这里只取中间的整数即9/2=4
判断 25是不是要找的数?不是
判断 152>25? 是
继续折半处理
此时
min=mid+1=arr[5]
max不变=arr[9]
mid=arr[7]=45
判断 45是不是要找的数?不是
判断 152>45? 是
第三次折半处理
此时
min=mid+1=arr[8]
max不变=arr[9]
mid=arr[8]=152
判断 152是不是要找的数?是
则返回该值
如果折中完所有元素都不符合的话,就要返回一个空值-1(即没有),需要一个判断条件,min>max,意思当最小值都大于最大值的时候,不可能再折半了(已理解注:min>max这个条件思维上不是太明白,数组里如果取到最值的情况下,应该min=max,不知什么情况下会出现min>max,方法2中的 while(min<=max)同理,但方法2还是较好理解,只要min<=max,肯定能折半)
min>max 理解模型:当数组中没有符合的元素的情况下 要一个判断来返回-1(即没有),所以取一个不存在数组里的数 比如 148
数组 {2,4,7,15,25,37,56,85,152,477}
min=0,max=9,mid=4=25,148>25?是,继续
min=4+1=5,max=9,mid=(5+9)/2=7=85,148>25?是继续
min=7+1=8,max=9,mid=(7+9)/2=8=152,148<152,max值左移,min不变
min=8,max=8-1=7,此时min>max
--------------以下为源代码--------------------------------------------------------------------
/*
数组的查找操作-折半查找-方法1
*/
class ArrayTest4
{
public static void main(String[] args)
{
int[]arr={2,4,7,15,25,37,56,45,152,477};
int index=halfSearch(arr,4770);
System.out.println("index="+index);
}
//折半查找-方法1-以判断找不找得到符合的值为条件进行折半查找,当找到之后直接返回该值,找不到则继续循环体折半直到无法折半查找
public static int halfSearch(int []arr,int key)
{ /*定义三个变量,最大值,最小值,中间值,初始化中间值即为最大值与最小值的和的一半*/
int min,max,mid;
max=arr.length-1;//这里要拿的是数组角标值,数组从arr[0]开始,所以需要元素个数减去1
min=0;
mid=(max+min)/2;
//循环体,直到找到符合条件的数结束循环并返回mid
while (arr[mid]!=key)
{
if (key>arr[mid])
min=mid+1;//继续折半,因为判断大于,需要右移,则min需要重新指向中间值之后的一个元素,max不变
else if(key<arr[mid])
max=mid-1;//继续折半,因为判断小于,需要左移移,则max需要重新指向中间值之前的一个元素,min不变
if(min>max) //当找不到符合值的判断条件
return -1;
mid=(max+min)/2; //继续取中间值
}
return mid;
}
}
-------------------------------------有木有见过这么可爱的分割线^_^-------------------------------------------------
/*
数组的查找操作-折半查找-方法2
*/
class ArrayTest4
{
public static void main(String[] args)
{
int[]arr={2,4,7,15,25,37,56,45,152,477};
int index=halfSearch_2(arr,4770);
System.out.println("index="+index);
}
//折半查找-方法2-以判断最小值和最大值为条件,min不论小于还是等于max,就存在中间值
public static int halfSearch_2(int []arr,int key)
{
int min,max,mid;
max=arr.length-1;
min=0;
while (min<=max)//只要这个条件成立,肯定能折半
{
mid=(max+min)/2;//循环体内取中间值
if (key>arr[mid])
min=mid+1;
else if(key<arr[mid])
max=mid-1;
else
return mid;//即不大于也不小于,那就只能是等于,也就是找到这个值了,返回即可
}
return -1;//当条件min<=max不成立的时候,返回-1
}
}