数据结构----基础查找算法
基础查找算法
1.简单线性查找
基本思想:遍历数据进行比对查找
实现代码:
public static void main(String[] args) {
int a[] = {1,23,42,22,21,89};
int result = seqSearch(a,23);
if(result == -1) {
System.out.println("没有查找到");
}else {
System.out.println("有这个数");
}
}
private static int seqSearch(int[] a,int val) {
for (int i = 0; i < a.length; i++) {
if(a[i] == val) {
return i;
}
}
return -1;
}
2.二分查找
基本思想:首先确定一些有序数值的中间值,然后让需要查找的数findVal和中间值进行比较,如果大于中间值,则向中间数的右边递归查找,小于则向左递归查找,等于则找到
实现代码:
public static void main(String[] args) {
int[] a = new int[] { 1, 23, 43, 56, 234, 1000, 1000, 1000, 1231 };
int index = binarySelect(a, 0, a.length - 1, 1000);
System.out.println("index=" + index);
ArrayList<Integer> indexs = new ArrayList<Integer>();
indexs = binarySelect1(a, 0, a.length - 1, 1000);
System.out.println(indexs);
}
// 二分查找单个数
private static int binarySelect(int[] a, int left, int right, int value) {
if (left > right) {
return -1;
}
int mid = (left + right) / 2;
int midVal = a[mid];
if (value > midVal) {
return binarySelect(a, mid + 1, right, value);
} else if (value < midVal) {
return binarySelect(a, left, mid - 1, value);
} else {
return mid;
}
}
// 二分查找查找所有重复的数
private static ArrayList<Integer> binarySelect1(int[] a, int left, int right, int value) {
if (left > right) {
return new ArrayList<Integer>();
}
int mid = (left + right) / 2;
int midVal = a[mid];
if (value > midVal) {
return binarySelect1(a, mid + 1, right, value);
} else if (value < midVal) {
return binarySelect1(a, left, mid - 1, value);
} else {
ArrayList<Integer> list = new ArrayList<Integer>();
// 向左扫描寻找和查找值相等的数
int temp = mid - 1;
while (true) {
if (temp < 0 || a[temp] != value) {
break;
}
list.add(temp);
temp -= 1;
}
list.add(mid);
// 向右扫描看是否有和查找值相等的值
temp = mid + 1;
while (true) {
if (temp > a.length - 1 || a[temp] != value) {
break;
}
list.add(temp);
temp += 1;
}
return list;
}
}
3.插值查找
基本思想:二分查找升级,每次从自适应中值(中值:left + (right - left) * (value - a[left]) / (a[right] - a[left]))开始查找
实现代码:
public static void main(String[] args) {
// 思想:二分查找升级,每次从自适应中值开始查找
// 中值:left + (right - left) * (value - a[left]) / (a[right] - a[left])
int[] a = new int[100];
for (int i = 0; i < 100; i++) {
a[i] = i + 1;
}
int index = insertSelect(a, 0, a.length - 1, 1);
System.out.println(index + "----" + a[index]);
}
private static int insertSelect(int[] a, int left, int right, int value) {
if (left > right || value < a[0] || value > a[a.length - 1]) {
return -1;
}
int mid = left + (right - left) * (value - a[left]) / (a[right] - a[left]);
int midVal = a[mid];
if (midVal > value) {// 向左查询
return insertSelect(a, left, mid - 1, value);
} else if (midVal < value) {// 向右查询
return insertSelect(a, mid + 1, right, value);
} else {
return mid;
}
}
4.斐波那锲查找(黄金分割点)
基本思想:黄金分割查找算法,中间节点改变:mid = F(k-1)-1
实现代码:
public static int maxSize = 20;
public static void main(String[] args) {
// 黄金分割查找算法
// 思想:中间节点改变:mid = F(k-1)-1
int[] a = new int[] { 1, 23, 123, 413, 1233, 3411 };
System.out.println("index----/" + fibSearch(a, 12));
}
// 非递归的方法得到一个斐波那锲数列
public static int[] fib() {
int[] f = new int[maxSize];
f[0] = 1;
f[1] = 1;
for (int i = 2; i < maxSize; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f;
}
public static int fibSearch(int[] a, int key) {
int low = 0;
int high = a.length - 1;
int k = 0;
int mid = 0;
int f[] = fib();// 或得斐波那锲数列
// 获得斐波那锲数值下标
while (high > f[k] - 1) {
k++;
}
// 因为f[k]值可能大于a的长度,因此构造一个新数组
// 不足部分由0补充
int[] temp = Arrays.copyOf(a, f[k]);
// 实际上需求使用a数组最后的填充temp
// 举例
// temp ={1,2,34,231,0,0,0} ---> {1,2,34,231,231,231,231}
for (int i = high + 1; i < temp.length; i++) {
temp[i] = a[high];
}
while (low <= high) {
mid = low + f[k - 1] - 1;
if (key < temp[mid]) {
high = mid - 1;
// 全部元素 = 前面元素 + 后边元素
// f[k] = f[k-1] +f[k-2]
// 因为前面有f[k-1]个元素,所以可以继续拆分为f[k-1] = f[k-2] + f[k-3]
k--;
} else if (key > temp[mid]) {
low = mid + 1;
// 全部元素 = 前面元素 + 后边元素
// f[k] = f[k-1] +f[k-2]
// 因为前面有f[k-1]个元素,所以可以继续拆分为f[k-1] = f[k-3] + f[k-4]
// 即下次循环mid = f[k-1-2] -1
k -= 2;
} else {
if (mid <= high) {
return mid;
} else {
return high;
}
}
}
return -1;
}