java 查找算法_常用查找算法及Java实现

title: 常用查找算法及Java实现

description: 常用的一些查找算法,经典必会,Java实现。

tags:

查找算法

categories:

算法

toc: true

comments: true

date: 2020-07-30 20:05:54

常用算法

顺序查找

顺序查找也称为线形查找,属于无序查找算法。从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;若扫描结束仍没有找到关键字等于k的结点,表示查找失败。

顺序查找的时间复杂度为O(n)。

public class Search {

public static void main(String[] args) {

int arr[] = {5, 11, 7, 9, 2, 3, 12, 8, 6, 1, 4, 10};

search(arr,3);

}

/**

* 顺序查找

*/

public static int order(int[] arr, int target) {

for (int i = 0; i < arr.length; i++) {

if (arr[i] == target) {

return i;

}

}

return -1;

}

}

二分查找

也称为是折半查找,属于有序查找算法。用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找哪个子表,这样递归进行,直到查找到或查找结束发现表中没有这样的结点。

最坏情况下,关键词比较次数为log2(n+1),且期望时间复杂度为O(log2n);

/**

* 常规二分查找

*/

public static int half(int[] arr, int target) {

//使数组有序

Arrays.sort(arr);

System.out.println(String.format("原数组%s中查找【%s】", Arrays.toString(arr), target));

int left = 0;

int right = arr.length - 1;

while (left <= right) {

int mid = ((right - left) >> 1) + left;

if (target > arr[mid]) {

left = mid + 1;

} else if (target < arr[mid]) {

right = mid - 1;

} else {

return mid;

}

}

return -1;

}

/**

* 递归二分查找

* @param high len-1

*/

public static int halfByRecurse(int[] arr, int target, int low, int high) {

int mid = ((high - low) >> 1) + low;

if (low == high) {

return -1;

}

if (target == arr[mid]) {

return mid;

}

if (target > arr[mid]) {

return halfByRecurse(arr, target, mid + 1, high);

}

if (target < arr[mid]) {

return halfByRecurse(arr, target, low, mid - 1);

}

return -1;

}

插值查找

基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率。当然,差值查找也属于有序查找

代码基本上和二分查找一样,有修改的地方就是mid的获取

在二分查找中$mid=$$low+high \over {2}$ 可改写成 $mid =low + $ $ {high-low} \over {2}$

也就是说我们的mid每次都是折中的取,但是对于一些均匀分布的有序表,这样做感觉有些费时,比如找字典的时候,找a这个字母,我们肯定不会从中间开始,而是偏向于字典前面一些开始。

插值查找就是基于这样的思想

我们对1/2进行改进:

$mid=low+$$key-a[low] \over a[high]=a[low]$$(high-low)$

key就是要查找的值,数组a是有序表

简单的理解就是计算出key所占比,然后更好地找到key所在的区间范围

但是对于极端分布的数组,插值查找的效率就大打折扣了

比如

int a[7]={0,1,2,100,102,1000,10000}

Java代码实现

/**

* 插值查找

*/

public static int insert(int[] arr, int target) {

//使数组有序

Arrays.sort(arr);

System.out.println(String.format("原数组%s中进行插值查找【%s】", Arrays.toString(arr), target));

int left = 0;

int right = arr.length - 1;

while (left <= right) {

int mid = left + (right - left) * ((target - arr[left]) / (arr[right] - arr[left]));

if (target > arr[mid]) {

left = mid + 1;

} else if (target < arr[mid]) {

right = mid - 1;

} else {

return mid;

}

}

return -1;

}

/**

* 递归插值查找

*

* @param high len-1

*/

public static int insertByRecurse(int[] arr, int target, int low, int high) {

int mid = low + (high - low) * ((target - arr[low]) / (arr[high] - arr[low]));

if (low <= high) {

if (target == arr[mid]) {

return mid;

} else if (target > arr[mid]) {

return insertByRecurse(arr, target, mid + 1, high);

} else {

return insertByRecurse(arr, target, low, mid - 1);

}

} else {

return -1;

}

}

斐波那契查找

斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…….(从第三个数开始,后边每一个数都是前两个数的和)。然后我们会发现,随着斐波那契数列的递增,前后两个数的比值会越来越接近黄金分割0.618,利用这个特性,我们就可以将黄金比例运用到查找技术中。

也是二分查找的一种提升算法,通过运用黄金比例的概念在数列中选择查找点进行查找,提高查找效率。同样地,斐波那契查找也属于一种有序查找算法。

876bc4112a1d8c47b4d3125097f054b6.png

树表查找

分块查找

哈希查找

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值