常用查找算法

查找算法可分为两种:无序查找有序查找,顾名思义,无序查找就是查找数列中的数是无序的,有序查找要求所查找数列是已经按照一定的规律排好序了,常见算法中大多都是无序查找。下面一一介绍几种常见的查找算法。

1. 顺序查找

  • 类型:无序查找。
  • 基本思想:
    从数据列中的一段开始(通常是起始位置),顺序扫描,依次比较所扫描数和目标值,如果相等则查找成功。若扫描结束仍没有找到那么就查找失败。
  • 复杂度分析:
平均查找长度 时间复杂度
(n+1)/2 O(n)
  • 示例代码:
   public static int sequenceSearch(int[] arr, int target) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == target) {
                return i;
            }
        }
        return -1;
    }

2. 二分查找(折半查找)

  • 类型:有序查找。
  • 基本思想:
    用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找哪个子表,这样递归进行,直到查找到或查找结束发现表中没有这样的结点。
  • 复杂度分析:
平均查找长度 时间复杂度
log2(n+1) O(log2n)
  • 示例代码:
   //二分查找 非递归
   public static int binarySearch(int[] arr, int target) {
        SortUtil.quickSort(arr, 0, arr.length - 1);
        int low = 0, high = arr.length - 1, mid;
        while (low <= high) {
            if (target == arr[low]) {
                return low;
            }
            if (target == arr[high]) {
                return high;
            }
            mid = (low + high) / 2;
            if (target == arr[mid]) {
                return mid;
            } else if (target > arr[mid]) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return -1;
    }

3. 插值查找

  • 类型:有序查找。
  • 基本思想:
    是二分查找的一种优化,将查找点改进为自适应选择以提高查找效率。(将mid = (low + high) /2取中值的取法换成了mid = low + (target - arr[low]) / (arr[high] - arr[low] * (high - low))
  • 时间复杂度分析: O(log2(log2n))
  • 示例代码:
   public static int insertionSearch(int[] arr, int target, int low, int high) {
        if (low <= high) {
            if (target == arr[low]) {
                return low;
            }
            if (target == arr[high]) {
                return high;
            }
            int mid = low + (target - arr[low]) / (arr[high] - arr[low] * (high - low));
            if (target == arr[mid]) {
                return mid;
            } else if (target < arr[mid]) {
                return insertionSearch(arr, target, low, mid - 1);
            } else {
                return insertionSearch(arr, target, mid + 1, high);
            }
        }
        return -1;
    }

3. 斐波那契查找

  • 类型:有序查找。
  • 斐波那契数列:相信很多同学都早已有所耳闻,即1,1,2,3,5,8,13...,从第三个数开始,后面的数都等于前两个数之和,而斐波那契查找就是利用的斐波那契数列来实现查找的。
  • 基本思想:
    同样的是,它是二分查找的一个优化,它是根据斐波那契序列的特点对有序表进行分割。他要求开始表中记录的个数为某个斐波那契数小1,及n=F(k)-1;然后需要装填一个长度为n的新数组,且mid = low + fib(k - 1) - 1,k为fib(k) - 1刚好大于原数组长度的那个值。

开始将k值与第F(k-1)位置的记录进行比较(及mid=low+F(k-1)-1),比较结果也分为三种
1)相等,mid位置的元素即为所求
2)>,low=mid+1,k-=2;
说明:low=mid+1说明待查找的元素在[mid+1,high]范围内,k-=2 说明范围[mid+1,high]内的元素个数为n-(F(k-1))= Fk-1-F(k-1)=Fk-F(k-1)-1=F(k-2)-1个,所以可以递归的应用斐波那契查找。
3)<,high=mid-1,k-=1。
说明:low=mid+1说明待查找的元素在[low,mid-1]范围内,k-=1 说明范围[low,mid-1]内的元素个数为F(k-1)-1个,所以可以递归 的应用斐波那契查找。

  • 时间复杂度:O(log2n)。
    由于时间有些仓促,下面的查找算法尚未理解透彻,暂时只记录基本思想,示例代码后面有空补上 = =。

4. 树表查找

顾名思义,就是将所查找数列构建成一颗树,其中最常见的是构建成一颗二叉查找树(左子节点的值均小于父节点的值,右子节点的值均大于父节点的值),然后通过遍历比较得出查找结果。

你可能感兴趣的:(常用查找算法)