查找算法——java

 顺序查找(顺序表查找) 

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

顺序查找适合于存储结构为顺序存储或链接存储的线性表。

    private static int sequenceSearch(int[] nums, int target) {for(int index=0;index<nums.length;index++){if (nums[index]==target) return index;}return -1;}

时间复杂度为O(n)

折半查找(有序查找)

折半查找(Binary Search)技术,又称为二分查找。它的前提是线性表中的记录必须是关键码有序(通常从小到大有序) ,线性表必须采用顺序存储。折半查找的基本思想是:在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区继续查找。不断重复上述过程,直到查找成功,或所有查找区域无记录,查找失败为止。 

非递归算法:

    private static int binarySearch1(int[] sortnums, int target) {int left=0;int right=sortnums.length-1;while(left<=right){int mid =(left+right)/2;if (target==sortnums[mid]) return mid;if(target < sortnums[mid]) right=mid-1;if (target > sortnums[mid]) left=mid+1;}return -1;}

递归算法:

    private static int binarySearch2(int[] sortnums, int target,int left,int right) {if (left <= right){int mid=(left+right)/2;if(target==sortnums[mid]) return mid;if(target<sortnums[mid])  return binarySearch2(sortnums,target,left,mid+1);if (target>sortnums[mid]) return binarySearch2(sortnums,target,mid+1,right);}return -1;}

时间复杂度为O(logn)

插值查找(有序查找)

插值查找是根据要查找的关键字key与查找表中最大最小记录的关键字比较后的 查找方法,其核心就在于插值的计算公式mid=low+\frac{target-num[left]]}{nums[right]-nums[left]]}(right-left)

简而言之,基于二分查找算法,将查找点的选择改进为自适应选择。

非递归方法:

    private static int insertSearch1(int[] sortnums, int target) {int left=0;int right=sortnums.length-1;while(left<=right){int mid =left+((target-sortnums[left])/(sortnums[right]-sortnums[left]))*(right-left);if (target==sortnums[mid]) return mid;if(target < sortnums[mid]) right=mid-1;if (target > sortnums[mid]) left=mid+1;}return -1;}

递归算法:

    private static int insertSearch2(int[] sortnums, int target, int left, int right) {if (left <= right){int mid=left+((target-sortnums[left])/(sortnums[right]-sortnums[left]))*(right-left);if(target==sortnums[mid]) return mid;if(target<sortnums[mid])  return binarySearch2(sortnums,target,left,mid+1);if (target>sortnums[mid]) return binarySearch2(sortnums,target,mid+1,right);}return -1;}

查找成功或者失败的时间复杂度均为O(log2 (log2 n))

斐波那契查找(有序)

与二分法、插值排序方法类似,只是关于mid的确定与斐波那契数列有关。

在斐波那契数列中的元素满足这样的关系:F[k]=F[k-1]+F[k-2],此处将这个数组稍微改一下,改成:(F[k]-1)=(F[k-1]-1)+(F[k-2]-1)+1

开始表中记录的个数为某个斐波那契数小1,及len=Fib(k)-1.

斐波那契数列中的数值都是固定的,但要查找的数组的长度不固定,此时需要的是创建新数组,使新数组的长度是斐波那契数列中的值,并且是比原数组长度略大的值,多出来的元素用原数组最高位元素补充

 斐波那契查找算法
1 ) 当 key=nums[mid] 时,查找就成功。
2 ) 当 key<nums[mid]时,新范围是第low个到第mid-1个,此时范围个数为f[k-1]-1个;
3 ) 当 key>nums[mid]时,新范围是第mid+1个到第high个,此时范围个数为f[k-2]-1个。

private static int fibonacciSearch(int[] nums, int target) {int len=nums.length;//构建特殊的Fibonacci数组,ArrayList<Integer> fibo = new ArrayList<Integer>();fibo.add(1);fibo.add(1);int k=2;while (true){int num=fibo.get(k-1)+fibo.get(k-2);fibo.add(num);if (fibo.get(k)-1>len) break;k++;}//斐波那契数列的最符合略大于原数组的Fibonacci数f(k)int[]temp = Arrays.copyOf(nums,fibo.get(k));for (int i=len+1;i<fibo.get(k);i++){temp[i]=nums[len-1];}int start=0;int end=len-1;while (start<=end){int mid=start+fibo.get(k-1)-1;if (target==nums[mid]) return mid;if (target>nums[mid]) {start=mid+1;k--;}if  (target<nums[mid]){end=mid-1;k-=2;}}return -1;}

二叉排序树查询

二叉排序树的性质:

  • 若左子树不空,则左子树上所有结点的键值均小于或等于它的根结点的键值。
  • 若右子树不空,则右子树上所有结点的键值均大于或等于它的根结点的键值。
  • 左、右子树也分别为二叉排序树。

二叉排序树的创建:

    private static void CreateShu(){int[] array = {35,76,6,22,16,49,49,98,46,9,40};BinaryTree root = new BinaryTree(array[0]);for(int i = 1; i < array.length; i++){createBST(root, array[i]);}}public static void createBST(BinaryTree root, int element){BinaryTree newNode = new BinaryTree(element);if(element > root.value){if(root.right == null)root.right = newNode;elsecreateBST(root.right, element);}else if(element < root.value){if(root.left == null)root.left = newNode;elsecreateBST(root.left, element);}else{System.out.println("该节点" + element + "已存在");return;}}

二叉排序树的查找:

基本思想:

与节点进行比较,等于节点的值则查找成功

大于节点的值则遍历查找节点的左孩子

小于节点的值则遍历查找节点的右孩子

public static void searchBST(BinaryTree root, int target, BinaryTree p){if(root == null){System.out.println("查找"+target+"失败");}else if(root.value == target){System.out.println("查找"+target+"成功");}else if(root.value >= target){searchBST(root.left, target, root);}else{ searchBST(root.right, target, root);}}

分块查找 

分块查找的基本思想:将查找表分为若干子块。块内的元素可以无序,但块之间是有序的,即第一个块中的最大关键字小于第二个块中的所有记录的关键字,第二个块中的最大关键字小于第三个块中的所有记录的关键字,以此类推。再建立一个索引表,索引表中的每个元素含有各块的最大关键字和各块中的第一个元素的地址,索引表按关键字有序排列。

以查找36为例

1.在索引表中依次遍历找到第一个大于它的值,即40

2.移动到40指向的数组区间的第一个元素,即数组下标9

3.从数组下标9开始遍历,40→36 找到36

哈希表查找

哈希表则通过计算一个以记录的关键词为自变量的函数(哈希函数H(x))来得到该机里的存储地址,所以在哈希表中进行查找操作时,需要同一哈希函数计算得到待查记录的存储地址,然后到相应的存储单元去获得有关信息在判定查找是否成功。

通过哈希函数H(key)和处理冲突的方法,将一组关键字映射,形成哈希散列

对于某个哈希函数H和两个关键字K_{1}K_{2},如果K_{1}\neq K_{2},而H(K_{1})=H(K_{2}),则称为冲突。具有相同的哈希函数值的关键字对该哈希函数成为同义词。 

哈希函数的构造 

  • 常见的哈希函数构造方法

        直接定址法、数字分析法、平方取中法、折叠法、随机数法、除留余数法

  • 处理冲突的方法

        (1)开放定址法       

线性探测法可能使第i个哈希地址的同义词存入第i+1个哈希地址,这样本应存入第i+1个哈希地址的元素变成第i+2个哈希地址元素的同义词。

        (2)链地址法:查找表的每一个记录中增加一个链域,链域中存放下一个具有相同哈希函数值的记录的存储地址(对于发生冲突时的查找和插入操作就跟线性表一样)。

        (3)再哈希法:RHi均是不同的哈希函数,即在同一词发生地址冲突时计算另一个哈希函数地址,直到冲突不再发生。

哈希函数的装填因子:α标志着哈希表的装满程度,α越小,发生冲突的可能性越小。

\alpha =表中装入的记录数  / 哈希表的长度

算法思想:key-value存储思想,key存值,value存索引

private static int hashSearch(int[] nums, int target) {HashMap<Integer,Integer> hashNums = new HashMap<Integer,Integer>();for (int i=0; i<nums.length; i++){hashNums.put(nums[i],i);}if (hashNums.get(target) !=null) return hashNums.get(target);return -1;}

哈希表的构造方法:

1、直接定址法
  哈希地址:f(key) = a*key+b (a、b为常数)。
2、数字分析法
  假设关键字是R进制数(如十进制)。并且哈希表中可能出现的关键字都是事先知道的,则可选取关键字的若干数位组成哈希地址。选取的原则是使得到的哈希地址尽量避免冲突,即所选数位上的数字尽可能是随机的。
3、平方取中法
  取key平方后的中间几位为哈希地址。通常在选定哈希函数时不一定能知道关键字的全部情况,仅取其中的几位为地址不一定合适。而一个数平方后的中间几位数和数的每一位都相关, 由此得到的哈希地址随机性更大。如key是1234,那么它的平方就是1522756,再抽取中间的3位就是227作为 f(key) 。
4、折叠法
  折叠法是将 key 从左到右分割成位数相等的几个部分(最后一部分位数不够可以短些),然后将这几部分叠加求和,并按哈希表的表长,取后几位作为 f(key) 。
比如key是9876543210,哈希表的表长为3位,我们将 key 分为4组,987 | 654 | 321 | 0 ,然后将它们叠加求和 987+654+321+0=1962,再取后3位即得到哈希位置是:962 。
5、除留余数法
  取关键字被某个不大于哈希表表长 m 的数 p 除后所得的余数为哈希地址。即 f(key) = key % p (p ≤ m)。这种方法是最常用的哈希函数构造方法。

6、随机数法
  哈希地址:random(key) ,这里random是随机函数,当 key 的长度不等时,采用这种方法比较合适。

查找总结:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/504950.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Sublime Text4代码配色自定义方案

文章目录 前言效果图 前言 关于Sublime Text对于我的使用体验&#xff0c;只能说内置的代码主题真的都太low了&#xff0c;一点都不好看。所以接下来我分享一下我自定义代码配色。当然&#xff0c;大家也可以通过我给的中文翻译注释来自定义自己喜欢的颜色。废话不多说&#x…

Unity中URP下实现水体(C#动态生成渐变图)

文章目录 前言一、Shader部分1、申明水渐变图纹理和采样器2、在片元着色器&#xff0c;进行纹理采样&#xff0c;并且输出 二、C#脚本部分1、我们新建一个C#脚本2、我们定义两个变量3、在Start内&#xff0c;new 一个Texture2D(宽&#xff0c;高)4、定义一个Color[宽*高]的颜色…

vue3 vite项目一运行就401(Unauthorized)

问题&#xff1a;项目一执行&#xff1a; pnpm run dev, 启动就出错&#xff0c; Failed to load resource: the server responded with a status of 401 (Unauthorized) 分析&#xff1a; 项目之前是正常运行的&#xff0c;没有问题&#xff0c;回溯刚刚改动&#xff0c;还原…

操作系统原理与实验——实验三优先级进程调度

实验指南 运行环境&#xff1a; Dev c 算法思想&#xff1a; 本实验是模拟进程调度中的优先级算法&#xff0c;在先来先服务算法的基础上&#xff0c;只需对就绪队列到达时间进行一次排序。第一个到达的进程首先进入CPU&#xff0c;将其从就绪队列中出队后。若此后队首的进程的…

Linux:kubernetes(k8s)node节点加入master主节点(3)

Linux&#xff1a;kubernetes&#xff08;k8s&#xff09;搭建mater节点&#xff08;kubeadm&#xff0c;kubectl&#xff0c;kubelet&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136415575?spm1001.2014.3001.5502 我在上一章部署好了主节点&…

【JSON2WEB】07 Amis可视化设计器CRUD增删改查

总算到重点中的核心内容&#xff0c;CRUD也就是增删改查&#xff0c;一个设计科学合理的管理信息系统&#xff0c;95%的就是CRUD&#xff0c;达不到这个比例要重新考虑一下你的数据库设计了。 1 新增页面 Step 1 启动amis-editor Setp 2 新增页面 名称和路径随便命名&#xf…

2024最新算法:电鳗觅食优化算法(Electric eel foraging optimization,EEFO)求解23个基准函数(提供MATLAB代码)

一、电鳗觅食优化算法 电鳗觅食优化算法&#xff08;Electric eel foraging optimization,EEFO&#xff09;由Weiguo Zhao等人提出的一种元启发算法&#xff0c;EEFO从自然界中电鳗表现出的智能群体觅食行为中汲取灵感。该算法对四种关键的觅食行为进行数学建模&#xff1a;相…

【贪心算法】Leetcode 455.分发饼干 376. 摆动序列 53. 最大子数组和

【贪心算法】Leetcode 455 分发饼干 376. 摆动序列【规律很多】53. 最大子数组和 455 分发饼干局部最优推全局最优&#xff1a;尽量用大饼干去满足大胃口的小朋友 376. 摆动序列【规律很多】思想&#xff1a;注意考虑一个坡度留首尾两个点、平坡、首尾 53. 最大子数组和【好思想…

手写模拟器,解放双手!效果炸裂的生产工具

手写模拟器是一款基于Handright的仿手写图片生成软件&#xff0c;可以让你的电脑和手机也能写出漂亮的手写字&#xff0c;你只需要输入你想要写的内容&#xff0c;选择你喜欢的字体和背景&#xff0c;就可以生成一张高仿真的手写图片&#xff0c;用于各种场合&#xff0c;比如做…

vue3 使用实现签到活动demo静态布局详解

文章目录 1. 实现效果2. 签到设置7天布局2.1 实现代码 3 签到设置15天布局3.1 思路分享 4 完整demo代码5. 总结 1. 实现效果 实现一个签到活动的h5页面布局&#xff0c;需求如下 签到活动天数可配置&#xff0c;可配置7天&#xff0c;15天&#xff0c;30天等默认天数要求展示2行…

Github配置ssh key的步骤

1. 检查本地主机是否已经存在ssh key 是否存在 id_rsa 和 id_rsa.pub文件&#xff0c;如果存在&#xff0c;说明已经有SSH Key 如下图所示&#xff0c;则表明已经存在 如果存在&#xff0c;直接跳到第三步 2. 生成ssh key 如果不存在ssh key&#xff0c;使用如下命令生…

数据结构篇十:红黑树

文章目录 前言1. 红黑树的概念2. 红黑树的性质3. 红黑树节点的定义4. 红黑树的插入4.1 情况一&#xff1a; cur为红&#xff0c;p为红&#xff0c;g为黑&#xff0c;u存在且为红4.2 情况二: cur为红&#xff0c;p为红&#xff0c;g为黑&#xff0c;u不存在/u存在且为黑。4.2.1 …