有三种常用的方法找到需要找到值的下标—顺序查找,二分查找,插值查找
顺序查找:很明显,就是从开始到后面开始遍历,找到就退出,并返回下标。
没找到就返回-1.
下面是代码:
public static int seqSearch(int[] arr,int value) {
for (int i = 0; i < arr.length; i++) {
if(arr[i]==value) {
return i+1;
}
}
return -1;
}
二分查找:有个缺点,就是必须要先得到排好序的数列。下面步骤是由小到大排序的,要是从大到小就处理相反即可。
步骤:先找到中间下标mid,每次用mid对应的数值跟要查找的值比较,如果等于就直接返回对应下标,如果小于查找值就向左边处理,大于就向右边处理。
代码如下:递归方法。
public static int binarySearch(int[] arr,int left,int right,int findValue) {
if(left>right) {
return -1;
}
int mid=(left+right)/2;
int midVal=arr[mid];
if(findValue>midVal) {
return binarySearch(arr, mid+1, right, findValue);
}else if(findValue<midVal){
return binarySearch(arr, left, mid-1, findValue);
}else {
return mid;
}
}
非递归方法:与递归的区别就是用while循环,直到找到return。
public static int binarySearch(int[] arr,int left,int right,int findValue) {
if(left>right) {
return -1;
}
int mid = (left+right)/2;
while(left <= right){
if(arr[mid] = findValue){
return mid-1;
}
if(arr[mid] > findValue){
right = mid - 1;
}
if(arr[mid] < findValue){
left = mid +1;
}
}
}
但是有可能这个有序数列中不止这一个数据和查找的数据相同,哪就是在处理等于情况下再做处理。(查找多个相同的,将下标放在一个List里面了。)
代码如下:
public static ArrayList<Integer> binarySearch(int[] arr,int left,int right,int findValue) {
if(left>right) {
return new ArrayList<Integer>();
}
int mid=(left+right)/2;
int midVal=arr[mid];
if(findValue>midVal) {
return binarySearch(arr, mid+1, right, findValue);
}else if(findValue<midVal){
return binarySearch(arr, left, mid-1, findValue);
}else { //值和查找的相同。
List<Integer> list=new ArrayList<Integer>();
int temp=mid-1;
//处理左边的
while(true) {
//在这个数组左边范围内
if(temp<0||arr[temp]!=findValue) {
break;
}
//找到放入。
list.add(temp);
temp-=1;
}
//处理中间的
list.add(mid);
//处理右边的。
temp=mid+1;
while(true) {
//在这个数组右边范围内
if(temp>arr.length-1||arr[temp]!=findValue) {
break;
}
//找到放入。
list.add(temp);
temp+=1;
}
return (ArrayList<Integer>) list;
}
}
插值查找:如果要查找这个顺序的数列的最左边或最右边,哪还要查找log2(n)次,比较麻烦,所以要使用插值查找。
插值查找根二分查找也差不多,只不过那个找中间mid的公式不同,如下:
mid=left+(right-left)*(findValue-arr[left]/(arr[right]-arr[left]));
代码如下:
public static int insertValueSearch(int[] arr,int left,int right,int findValue) {
if(left>right|| findValue<arr[0]|| findValue>arr[arr.length-1]) {
return -1;
}
int mid=left+(right-left)*(findValue-arr[left]/(arr[right]-arr[left]));
int midVal=arr[mid];
if(findValue>midVal) {
return insertValueSearch(arr, mid+1, right, findValue);
}else if(findValue<midVal){
return insertValueSearch(arr, left, mid-1, findValue);
}else {
return mid;
}
}