今天来跟大家分享经典的三个查找算法!
分别是:二分查找(分块查找)、分块查找、哈希查找
目录
一、二分查找(折半查找)
三大查找中的二分查找 二分查找:也叫折半查找 条件是必须为有序列表,且每次都是以序列的中间位置的数来与待查找的关键字进行比较,每次都是缩小一半的查找范围,一直到找到为止 代码实现:有两种方式 1.非递归实现 2.递归实现(一般情况下不用递归) 时间复杂度:最坏情况下两种方式的时间复杂度一样 为:O(log2n) 空间复杂度:递归方式为:O(log2n); 非递归方式为:O(1)
(一)递归方式实现
代码如下:
public class TwoSearch {
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6,8,9,25,250};
int index=getNumIndex(arr,8);
System.out.println(index);
}
//递归实现折半查找
public static int diguiSearch(int[] arr,int key,int low,int high){
//判断查找不到的情况
if(key<arr[low]||key>arr[high]||low>high){
return -1;
}
//定义中间下标位置
int middle=(low+high)/2;
if(key<arr[middle]){//确定什么时候在哪查找
return diguiSearch(arr,key,low,middle-1);
} else if (key>arr[middle]) {
return diguiSearch(arr,key,middle+1,high);
}else{
return middle;
}
}
}
(二)非递归方式实现
代码如下:
public class TwoSearch {
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6,8,9,25,250};
int index=diguiSearch(arr,8,0,arr.length-1);
System.out.println(index);
}
//非递归实现二分查找
public static int getNumIndex(int[] arr,int key){
//arr表示要在哪个数组里查找 key表示要查找的元素值 return返回查找的元素下标,如果查不到元素就返回-1
//定义最低位下标
int low=0;
//定义最高位下标
int high=arr.length-1;
int middle=0;
if(key<arr[low]||key>arr[high]||low>high){
return -1;
}
while(low<=high){
middle=(low+high)/2;
if(key>arr[middle]){
low=middle+1;
}else if(key<arr[middle]){
high=middle-1;
}else{
return middle;
}
}
return -1;
}
}
二、分块查找
算法思想:分块查找也称为索引顺序表查找 分块查找就是将顺序表(主表)分成若干个单元,然后为每个单元建立一个索引表,利用索引在其中一个单元中进行查找。 其中索引表分为两个部分:一个用来存储每个子表的最大元素值,另一个用来存储每个子表第一个元素的下标。 索引表中的元素必须是有序的,顺序表(主表)中元素可以是有序排列,也可以是块内无序但块间有序, 即后一个单元中的所有元素值都大于前一个单元中的元素值。例如,一个索引顺序表如下图所示。 简单的来说,分块查找就是将原序列分成m块 每一块里面的所有数都要比下一块的所有数都小,再将每一块里面的最大值拿出来组成一个有序序列。
代码实现如下:
public class Fenkuai {
public static void main(String[] args) {
int[] arr={3,1,4,5,9,8,14,10,11,22};
int[] arr2={4,9,14,22};
int n=getKuai(arr2,8);
System.out.println(n);
//每一块的起始位置是
int index=n*3;
int index2=youxu(arr,index,8);
System.out.println(index2);
}
//要查找的元素在哪个块中
//arr2表示有序索引数组 key表示要查找的元素 return表示返回在哪个块中
public static int getKuai(int[] arr2,int key){
for(int i=0;i<arr2.length;i++){
if(key<arr2[i]){
return i;
}
}
return -1;
}
//arr表示原数组,index表示起始位置 key表示要查找的元素,return返回要查找元素的下标
public static int youxu(int[] arr,int index,int key){
for(int i=index;i<index+3;i++){
if(arr[i]==key){
return i;
}
}
return -1;
}
}
三、哈希查找
1、哈希查找也叫散列查找,整个散列查找过程大概分两步 (1)在存储时通过散列函数计算记录的散列地址,并按此散列地址存储该记录。 (2)当查找时,一样通过散列函数计算记录的散列地址,然后访问散列地址的记录。 * 散列函数的构造方法 (1)直接定址法 (2)数字分析法 (3)平方取中法 (4)折叠法 (5)除留余数法(此方法为最常用的构造散列函数的方法。) 处理冲突散列的方法 (1)开放定址法 (2)再散列函数法 (3)链地址法 2、散列表查找算法实现 (1)首先定义一个散列表结构 (2)对散列表进行初始化 (3)对散列表进行插入操作 (4)根据不同的情况选择散列函数和处理冲突的方法(这里选用的是除留余数法和开放定址法)
代码实现如下:
public class HashSelect {
public static void main(String[] args) {
int[] a= {7, 4, 1, 14, 100, 30, 5, 9, 20, 134};
HashTable ht = new HashTable();
ht.createHT(ht, a, a.length, 15, 13);
ht.dispHT(ht, 15);
}
public static class HashTable {
public int[] key;
public int nullKey = -1;
public int count = 0;
public HashTable() {
this.key = new int[50];
}
public void insertHT(HashTable ha, int key, int p, int m) {
int i, adr;
adr = key % p;
if (ha.key[adr] == nullKey){
ha.key[adr] = key;
ha.count = 1;
} else {
i = 1;
do {
adr = (adr + 1) % m;
} while (ha.key[adr] != nullKey);
ha.key[adr] = key;
ha.count = i;
}
}
public void createHT(HashTable ha, int [] a, int n, int m, int p) {
int i;
for (i = 0; i < m; i++){
ha.key[i] = nullKey;
ha.count = 0;
}
for (i = 0; i < n; i++) {
insertHT(ha, a[i], p, m);
}
}
public void dispHT(HashTable ha, int m){
int i;
for (i = 0; i < m; i++) {
System.out.println(i + " ");
}
System.out.println();
for (i = 0; i < m; i++) {
if (ha.key[i] != nullKey) {
if (ha.key[i] < 10) {
System.out.println(ha.key[i] + " ");
} else if (ha.key[i] >= 100) {
System.out.println(ha.key[i] + " ");
} else {
System.out.println(ha.key[i] + " ");
}
} else {
System.out.println(" ");
}
}
System.out.println();
}
}
}
以上就是今天为大家分享的内容
PS:本人是计算机专业的大二学生,在这个充满内卷的年代想把自己学习到的经验知识分享给大家,如有错误,请各位大神见谅,也请大家给我意见!
后续会上新我面试时候的面经,请大家继续关注。