数据结构与算法

  • 一,查找算法
    • 1,简介:
    • 2,顺序查找:
    • 3,二分查找:
    • 4,插值查找:
    • 5,斐波那契(黄金分割法)查找:

一,查找算法

1,简介:

查找算法:常分为四种;

  1. 顺序查找(线性查找);
  2. 二分查找/折半查找;
  3. 插值查找;
  4. 斐波那契查找;

2,顺序查找:

按照原来顺序查找值,找到即返回下标,找不到返回-1,即不存在;

 public static int search(int[] arr, int val) {for (int i = 0; i < arr.length; i++) {if (val == arr[i]) {return i;}}return -1;}

3,二分查找:

分析:

  1. 顾名思义先确定中间值的下标mid=(left+right)/2;
  2. 让需要查找的val与arr[mid]比较;
  3. val<arr[mid]则向左递归查找,反之右递归查找;
  4. 查找过程中,等于时直接退出,或当left>right时如果找不到就退出递归,说明不存在;
  5. 过程中每次都有left、right两个指针在递归段的两端向mid逼近;
package com.search;import java.util.ArrayList;/*** @param* @Author: AaNeei* @Date: 2019/6/17  22:26* @Description: 游学网* @throws:*/
public class BinarySearch {public static void main(String[] args) {int[] arr = {1, 5, 8, 9, 10, 10, 10, 10, 11, 15, 20};int val = 10;int search = search(arr, 0, arr.length - 1, val);ArrayList<Integer> arrayList = searchAll(arr, 0, arr.length - 1, val);System.out.println("查找的值" + val + "下标为" + search);System.out.println("查找的值" + val + "下标为" + arrayList);}/*** @param arr   查找的原数组* @param left  左指针* @param right 右指针* @param val   要找的值* @return 找不到就返回-1*/public static ArrayList<Integer> searchAll(int[] arr, int left, int right, int val) {int mid = (left + right) / 2;int midVal = arr[mid];if (left > right || val < arr[left] || val > arr[right]) {return new ArrayList<>();}if (val < midVal) {//向左递归,right移至递归段的最右端即mid-1return searchAll(arr, left, mid - 1, val);} else if (val > midVal) {//向右递归,left移至递归段的最右端即mid+1return searchAll(arr, mid + 1, right, val);} else {ArrayList<Integer> arrayList = new ArrayList<>(arr.length);arrayList.add(mid);int temp = mid - 1;//向左扫描是否有相同值,并记录while (true) {if (temp < 0 || arr[temp] != val) {break;}arrayList.add(temp--);}temp = mid + 1;//向右扫描是否有相同值,并记录while (true) {if (temp > arr.length - 1 || arr[temp] != val) {break;}arrayList.add(temp++);}return arrayList;}}public static int search(int[] arr, int left, int right, int val) {int mid = (left + right) / 2;int midVal = arr[mid];//因为是有序的,所以不在最小值最大值范围的直接不存在if (left > right || val < arr[left] || val > arr[right]) {return -1;}if (val < midVal) {//向左递归,right移至递归段的最右端即mid-1return search(arr, left, mid - 1, val);} else if (val > midVal) {//向右递归,left移至递归段的最右端即mid+1return search(arr, mid + 1, right, val);} else {return mid;}}
}

注: 二分查找必须是有顺序的数组,如果没有顺序需要先排序;
发现问题: 对于有序排列的数组,查找首尾利用二分会较慢,怎么解决?自适应算法(插值查找);

4,插值查找:

分析:

  1. 类似于二分查找,不同的是插值查找每次从自适应mid处开始查找;
  2. 将二分查找中的mid公式调整为:int mid=left+(right-left)*(val-arr[left])/(arr[right]-arr[left]);
package com.search;import java.util.ArrayList;/*** @param* @Author: AaNeei* @Date: 2019/6/18  21:35* @Description: 游学网* @throws:*/
public class InterpolationSearch {public static void main(String[] args) {int num = 100;int[] arr = init(num);ArrayList<Integer> arrayList = searchAll(arr, 0, num - 1, 80);int search = search(arr, 0, num - 1, 99);System.out.println(arrayList + ":-----:" + search);}public static ArrayList<Integer> searchAll(int[] arr, int left, int right, int val) {if (left > right || val < arr[left] || val > arr[right]) {return new ArrayList<>();}int mid = left + (right - left) * (val - arr[left]) / (arr[right] - arr[left]);int midVal = arr[mid];if (val < midVal) {//向左递归,right移至递归段的最右端即mid-1return searchAll(arr, left, mid - 1, val);} else if (val > midVal) {//向右递归,left移至递归段的最右端即mid+1return searchAll(arr, mid + 1, right, val);} else {ArrayList<Integer> arrayList = new ArrayList<>(arr.length);arrayList.add(mid);int temp = mid - 1;//向左扫描是否有相同值,并记录while (true) {if (temp < 0 || arr[temp] != val) {break;}arrayList.add(temp--);}temp = mid + 1;//向右扫描是否有相同值,并记录while (true) {if (temp > arr.length - 1 || arr[temp] != val) {break;}arrayList.add(temp++);}return arrayList;}}public static int search(int[] arr, int left, int right, int val) {System.out.println("开始查找--");//因为是有序的,所以不在最小值最大值范围的直接不存在if (left > right || val < arr[left] || val > arr[right]) {return -1;}int mid = left + (right - left) * (val - arr[left]) / (arr[right] - arr[left]);int midVal = arr[mid];if (val < midVal) {//向左递归,right移至递归段的最右端即mid-1return search(arr, left, mid - 1, val);} else if (val > midVal) {//向右递归,left移至递归段的最右端即mid+1return search(arr, mid + 1, right, val);} else {return mid;}}public static int[] init(int num) {int[] arr = new int[num];for (int i = 0; i < num; i++) {arr[i] = i;}return arr;}}

注: 对于数据量较大,元素分布均匀的表来说,插值查找优于二分,但是元素分布不均匀的可能会没有二分来的快;

5,斐波那契(黄金分割法)查找:

黄金分割点: 黄金分割点是指把一条线段分割为两部分,使其中一部分与全长之比等于另一部分与这部分之比。其比值是一个无理数,用分数表示为(√5-1)/2,取其前三位数字的近似值是0.618。由于按此比例设计的造型十分美丽,因此称为黄金分割,也称为中外比。这个分割点就叫做黄金分割点(golden section ratio),通常用Φ表示。这是一个十分有趣的数字,以0.618来近似表示,通过简单的计算就可以发现:(1-0.618)/0.618≈0.618,即一条线段上有两个黄金分割点。
斐波那契数列: 斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……后者比上前者无限接近0.618;

分析:

  1. 基于二分查找,只改变中间节点mid的位置;
  2. 不在由中间位或插值得到,而是位于黄金分割点附近;
  3. mid=left+F(k-1)-1,F代表斐波那契数列,k代表数列的第几个元素;
package com.search;import java.util.Arrays;/*** @param* @Author: AaNeei* @Date: 2019/6/19  21:21* @Description: 游学网* @throws:*/
public class FibonacciSearch {public static void main(String[] args) {int[] arr = {1, 5, 9, 13, 15, 46, 191, 1234, 45678};int search = search(arr, 45678);System.out.println(search);}public static int search(int[] arr, int val) {int left = 0;int right = arr.length - 1;int k = 0;//斐波那契分割元素的下标int mid = 0;int[] f = fibonacciArr(arr);//获取得到斐波那契分个数的下标while (right > f[k] - 1) {k++;}int[] temp = Arrays.copyOf(arr, f[k]);for (int i = right + 1; i < temp.length; i++) {temp[i] = arr[right];}while (left <= right) {mid = left + f[k - 1] - 1;if (val < temp[mid]) {right = mid - 1;k--;} else if (val > temp[mid]) {left = mid + 1;k -= 2;} else {if (mid <= right) {return mid;} else {return right;}}}return -1;}//斐波那契数列public static int[] fibonacciArr(int[] arr) {int[] f = new int[arr.length];f[0] = 1;f[1] = 1;for (int i = 2; i < arr.length; i++) {f[i] = f[i - 1] + f[i - 2];}return f;}
}

数据结构与算法--第17篇(查找算法)相关推荐

  1. 【数据结构与算法】第二篇:算法部分

    系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录 前言 一.程序的时间和空间复杂度分析 (1)理解算法时间复杂度的表示法 ( ...

  2. 家族关系查询系统程序设计算法思路_七大查找算法(附C语言代码实现)

    来自:Poll的笔记 - 博客园 链接:http://www.cnblogs.com/maybe2030/p/4715035.html 阅读目录 1.顺序查找 2.二分查找 3.插值查找 4.斐波那契 ...

  3. python二分法查找算法_顺序查找算法和折半(二分法)查找算法,C语言查找算法详解...

    查找是指在大量的信息中寻找一个特定的信息.在计算机中,查找是非常重要的一个应用,比如"百度".查找算法的好坏直接影响查找的速度. 常用的查找算法主要有顺序查找和折半(二分法)查找: ...

  4. 【数据结构与算法】比较法分析查找算法与查找结构

    基本的查找技术: 线性表的查找技术 顺序查找 分块查找 二分查找(折半查找) 插值查找 树表的查找技术 二叉排序树 平衡二叉树 B树(B+树.B-树等) 散列表的查找技术 开散列表 闭散列表 顺序查找 ...

  5. 大数据与算法系列之海量数据查找算法

    在某些时候,可能会涉及在海量数据中的查找,如果采用通常的做法,则很难达到一定的效果,在实际工程实践中,海量数据的查找性能很肯恩鬼成为整个系统的性能瓶颈,在海量数据中的查找包括基于布隆过滤器的方式,以及 ...

  6. python实现二分查找算法_python实现二分查找算法

    ??二分算法的定义不在多说了,百度一下就知道(支持国产 ) import syssource = [1,2,3,4,5,6,7,8,9,10] #must be in orderdes = int(s ...

  7. 算法学习过程入门篇(2)-算法初步

    入门 排序 sort函数 #include <algorithm> using namespace std;//两行必须添加 sort(stu + num -k,stu + num, cm ...

  8. java数组查找算法_JAVA数组中查找算法中equals和==的问题

    importjava.util.*;publicclassTest1{publicstaticvoidmain(String[]args){ScannerS=newScanner(System.in) ...

  9. 数据结构-常用的查找算法

    总第124篇/张俊红 本篇讲讲数据结构里面常用的几个查找算法,数据结构理论篇系列差不多接近尾声了,接下来会分享一些比较特殊的概念,比如KMP.郝夫曼树等等,讲完概念以后会进入刷题阶段.刷题会用Pyth ...

最新文章

  1. Mac OS X Yosemite安装盘U盘制作
  2. [How TO]-python venv虚拟环境
  3. 服务器2003系统文件,win2003图文详解文件服务器的安装步骤
  4. VTK:PolyData之DetermineArrayDataTypes
  5. synaptic不停抖动后自动关闭的问题
  6. Boost中的Timer的使用——计算时间流逝
  7. ASP.NET MVC3源码下载
  8. gpt windows linux,UEFI+GPT环境下安装Windows+Linux+OS X
  9. 服务器端系统饼图,服务器 操作系统 饼图
  10. Spark Streaming之updateStateByKey和mapWithState比较
  11. ubuntu12.04中安装SVN记录
  12. Unity List的拷贝
  13. itest考试切屏能检测出来吗_itest考试作弊怎么检测
  14. CPP QT实现excel的冻结窗格
  15. badboy设置中文_badboy中文手册
  16. 2021最新Java学科全阶段视频教程(从入门到精通)
  17. 利用Python实现scissors-rock-paper-lizard-Spock小游戏
  18. 深度学习模型部署学习一
  19. 阿里云主机遭受DDOS攻击IP不能使用如何更换弹性公网IP
  20. FP、FN、TP、FN解释

热门文章

  1. LOL决赛夜钓鱼攻击分析
  2. R count函数_R最快且比dplyr最高效的大数据处理R包:tidyfst
  3. 分析思维:数据分析中的四种原因
  4. 罗技K845背光机械键盘深度体验报告
  5. Swagger 3.0 官方教材出炉,野生的可以扔了!
  6. PPWOW纯公益性的80级WLK巫妖王之怒怀旧服服务器架构
  7. office project 2013项目计划编制图解
  8. 冬季进补,根据体质吃药膳
  9. poi操作ppt生成文本框
  10. 安装vue脚手架报错