package searchalgroithm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
// List<Integer> integers1 = insertSearch(arr, 7, 0, arr.length - 1);
// System.out.println(integers1);
int[] fibonacciArray = getFibonacciArray(20);
System.out.println(Arrays.toString(fibonacciArray));
int i = fiboSearch(arr, 1);
System.out.println(i);
}
/**
* 二分查找,返回与查找元素相同的元素的索引的集合
* 只适用与有序数组
* @param arr
* @param findValue
* @param left
* @param right
* @return
*/
public static List<Integer> binarySearch(int[] arr, int findValue, int left, int right){
System.out.println(333);
if(left > right){
return new ArrayList<>();
}
int mid = (left + right) / 2;
//向左找
if(findValue < arr[mid]){
return binarySearch(arr , findValue , left , mid - 1);
//向右找
}else if(findValue > arr[mid]){
return binarySearch(arr , findValue , mid + 1, right);
//找到结果
}else{
List<Integer> resultList = new ArrayList<>();
//向左找
int temp = mid - 1;
while (true){
if(temp < 0 || arr[temp] != findValue){
break;
}
resultList.add(temp);
temp--;
}
//加入原值
resultList.add(mid);
//向左找
temp = mid + 1;
while (true){
if(temp > right || arr[temp] != findValue){
break;
}
resultList.add(temp);
temp++;
}
return resultList;
}
}
/**
* 插值查找,返回与查找元素相同的元素的索引的集合
* 只适用与有序数组,且当数组中有大量连续元素时插值查找快于二分查找
* @param arr
* @param findValue
* @param left
* @param right
* @return
*/
public static List<Integer> insertSearch(int[] arr, int findValue, int left, int right){
System.out.println(222);
if(left > right || findValue < arr[0] || findValue > arr[arr.length - 1]){
return new ArrayList<>();
}
int mid = left + (right - left) * (findValue - arr[left]) / (arr[right] - arr[left]);
//向左找
if(findValue < arr[mid]){
System.out.println(000);
return insertSearch(arr , findValue , left , mid - 1);
//向右找
}else if(findValue > arr[mid]){
return insertSearch(arr , findValue , mid + 1, right);
//找到结果
}else{
List<Integer> resultList = new ArrayList<>();
//向左找
int temp = mid - 1;
while (true){
if(temp < 0 || arr[temp] != findValue){
break;
}
resultList.add(temp);
temp--;
}
//加入原值
resultList.add(mid);
//向左找
temp = mid + 1;
while (true){
if(temp > right || arr[temp] != findValue){
break;
}
resultList.add(temp);
temp++;
}
return resultList;
}
}
/**
* 返回一个有n个元素的斐波那契数列
* @param n
* @return
*/
public static int[] getFibonacciArray(int n){
int[] arr = new int[n];
arr[0] = 1;
arr[1] = 1;
for (int i = 2; i < n; i++) {
arr[i] = arr[i - 1] + arr[i - 2];
}
return arr;
}
/**
* 斐波那契查找,与插值查找和二分查找类似,只适用于有序数组,
* 利用斐波那契数列的特点将分割点固定在0.618的位置
* 非递归的方式
* @param arr
* @param findvalue
* @return
*/
public static int fiboSearch(int[] arr , int findvalue){
int low = 0;
int high = arr.length - 1;
int k = 0;
int mid = 0;
//得到斐波那契数列
int[] fib = getFibonacciArray(20);
//求出k的初始值
while(high > fib[k]){
k++;
}
//创建一个新数组,并将原数组的元素拷贝至新数组中
int[] temp = Arrays.copyOf(arr, fib[k]);
//将新数组中比原数组中多出来的项都设置为原数组的最大值
for (int i = high + 1; i < temp.length; i++) {
temp[i] = arr[arr.length - 1];
}
//输出新数组
//System.out.println(Arrays.toString(temp));
//循环查找
while (low <= high){
//通过不断变化的low和k使mid永远维持在黄金分割点
mid = low + fib[k - 1] - 1;
//向左找
if(findvalue < temp[mid]){
high = mid - 1;
k--;
}else if(findvalue > temp[mid]){
//向右找
low = mid + 1;
k -= 2;
}else{
//已找到相匹配的值
if(mid <= high){
return mid;
}else{
return high;
}
}
}
return -1;
}
}
数据结构与算法练习---二分查找及其拓展代码
最新推荐文章于 2024-09-07 14:37:21 发布