Skip to content

Latest commit

 

History

History
219 lines (159 loc) · 6.32 KB

算法-基础篇(2)七大查询.md

File metadata and controls

219 lines (159 loc) · 6.32 KB

查询算法中,最常见的有 7 种,分别是:顺序查询、二分查询、插值查询、斐波那契查询、树表查询、分库查询、哈希查询

顺序查找

算法简介

​ 顺序查找又称为线性查找,是一种最简单的查找方法。适用于线性表的顺序存储结构和链式存储结构。该算法的时间复杂度为O(n)。

基本思路

​ 从第一个元素m开始逐个与需要查找的元素x进行比较,当比较到元素值相同(即m=x)时返回元素m的下标,如果比较到最后都没有找到,则返回-1。

优缺点

​ 缺点:是当n 很大时,平均查找长度较大,效率低; 优点:是对表中数据元素的存储没有要求。另外,对于线性链表,只能进行顺序查找。

二分查找

算法简介

​ 二分查找(Binary Search),是一种在有序数组中查找某一特定元素的查找算法。查找过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则查找过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。 这种查找算法每一次比较都使查找范围缩小一半。

算法描述

给予一个包含 n个带值元素的数组A

  • 1、 令 L为0 , R为 n-1 ;
  • 2、 如果L>R,则搜索以失败告终 ;
  • 3、 令 m (中间值元素)为 ⌊(L+R)/2⌋;
  • 4、 如果 Am<T,令 L为 m + 1 并回到步骤二 ;
  • 5、 如果 Am>T,令 R为 m - 1 并回到步骤二;

复杂度分析

​ 时间复杂度:折半搜索每次把搜索区域减少一半,时间复杂度为 O(logn) 空间复杂度:O(1)

代码实现

//二分查找,递归版本
public class BinarySearch2{
    //递归查找
    public static int binarysearch(int[] a,int value,int low,int high){
        int mid = (low + high)/2;
        if(value == a[mid]){
            return mid;
        }else if(value < a[mid])
            return binarysearch(a,value,low,mid - 1);
        }else if(value > a[mid])
            return binarysearch(a,value,mid + 1,high);	
        }
        return -1;
    }
	//循环查找
    public static int binarysearch(int[] a,int value){
		int left=0;
		int right=a.length-1;
		int middle=0;
		while(left<=right) {
			middle=(left+right)/2;
			if(value == a[middle]){
	            return middle;
	        }else if(value < a[middle]) {
	        	left=middle - 1;
	        }else if(value > a[middle]) {
	        	right=middle + 1;	
	        }
		}
		return middle;
    }
	public static void main(String[] args) {
		//int[] a = {1,4,2,9,8,6,7,0,3,5}
		int[] a = {0,1,2,3,4,5,6,7,8,9};
		System.out.println(binarysearch(a,4,0,a.length-1));
	} 
}

插值查找

算法简介

插值查找是根据要查找的关键字key与查找表中最大最小记录的关键字比较后的 查找方法,

时间复杂度o(logn),空间复杂度:O(1)。

插入查找:选择下标 = left + (right - left) * (key - arr[left])/(arr[right] - arr[left])

(1)序列为有序序列

(2)根据公式选取比较值,相等返回下标,不相等则根据公式继续查找,未找到返回-1

代码实现

public static int insertSearch(int[] array, int key) {
    return search(array, key, 0, array.length - 1);
}
private static int search(int[] array, int key, int left, int right) {
    while (left <= right) {
        if (array[left] == array[right]) {
            if (array[left] == key)
                return left;
            else return -1;
        }
        int middle =  left + (right-left)*(key-array[left])/(array[right]-array[left]);
        if (array[middle] == key) {
            return middle;
        }
        if (key < array[middle]) {
            right = middle - 1;
        } else {
            left = middle + 1;
        }
    }
    return -1;
}

斐波那契查找

斐波那契数列我们都知道{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 },前后的比值会越来越接近0.618,也就是黄金分割点。

查找条件:

(1)数据必须采用顺序存储结构;

(2)数据必须有序。

public static void main(String[] args) {
    int[] array = { 1, 5, 15, 22, 25, 31, 39, 42, 47, 49, 59, 68,88 };
    System.out.println("result: " + fbSearch(array, 42));
}

public static int fbSearch(int[] array, int value) {
    if (array == null || array.length == 0) {
        return -1;
    } else {
        int length = array.length;
        int[] fb = makeFbArray(20);// 制造一个长度为20的斐波数列
        int k = 0;
        while (length > fb[k] - 1) {// 找出数组的长度在斐波数列(减1)中的位置,将决定如何拆分
            k++;
        }

        int[] temp = Arrays.copyOf(array, fb[k] - 1);// 构造一个长度为fb[k] - 1的新数列
        //对新构造的数组进行 元素补充
        for (int i = length; i < temp.length; i++) {
            if (i >= length) {
                temp[i] = array[length - 1];
            }
        }
        int low = 0;
        int hight = array.length - 1;
        while (low <= hight) {
            int middle = low + fb[k - 1] - 1;
            if (temp[middle] > value) {
                hight = middle - 1;
                k = k - 1;
            } else if (temp[middle] < value) {
                low = middle + 1;
                k = k - 2;
            } else {
                if (middle <= hight) {
                    return middle;// 若相等则说明mid即为查找到的位置
                } else {
                    return hight;// middle的值已经大于hight,进入扩展数组的填充部分,即最后一个数就是要查找的数。
                }
            }
        }
        return -1;
    }
}


private static int[] makeFbArray(int length) {
    int[] array = null;
    if (length > 2) {
        array = new int[length];
        array[0] = 1;
        array[1] = 1;
        for (int i = 2; i < length; i++) {
            array[i] = array[i - 1] + array[i - 2];
        }
    }
    return array;
}

树表查找

(------------正在整理中------------)

分块查找

(------------正在整理中------------)

哈希查找

(------------正在整理中------------)