当前位置:首页 » 操作系统 » 查找的算法

查找的算法

发布时间: 2022-12-18 21:08:54

‘壹’ 常见查找和排序算法

查找成功最多要n 次,平均(n+1)/2次, 时间复杂度为O(n)
优点:既适用顺序表也适用单链表,同时对表中元素顺序无要求,给插入带来方便,只需插入表尾即可。
缺点:速度较慢。

改进:在表尾设置一个岗哨,这样不用去循环判断数组下标是否越界,因为最后必然成立。

适用条件:

二分查找的判定树不仅是二叉排序树,而且是一棵理想平衡树。 时间复杂度为O(lbn)

循环实现

递归实现

待排序的元素需要实现 Java 的 Comparable 接口,该接口有 compareTo() 方法,可以用它来判断两个元素的大小关系。

从数组中选择最小元素,将它与数组的第一个元素交换位置。再从数组剩下的元素中选择出最小的元素,将它与数组的第二个元素交换位置。不断进行这样的操作,直到将整个数组排序。

选择排序需要 ~N2/2 次比较和 ~N 次交换,==它的运行时间与输入无关==,这个特点使得它对一个已经排序的数组也需要这么多的比较和交换操作。

从左到右不断 交换相邻逆序的元素 ,在一轮的循环之后,可以让未排序的最大元素上浮到右侧。

在一轮循环中,如果没有发生交换,那么说明数组已经是有序的,此时可以直接退出。

每次都 将当前元素插入到左侧已经排序的数组中 ,使得插入之后左侧数组依然有序。

对于数组 {3, 5, 2, 4, 1},它具有以下逆序:(3, 2), (3, 1), (5, 2), (5, 4), (5, 1), (2, 1), (4, 1),插入排序每次只能交换相邻元素,令逆序数量减少 1,因此插入排序需要交换的次数为逆序数量。

==插入排序的时间复杂度取决于数组的初始顺序,如果数组已经部分有序了,那么逆序较少,需要的交换次数也就较少,时间复杂度较低==。

对于大规模的数组,插入排序很慢,因为它只能交换相邻的元素,每次只能将逆序数量减少 1。希尔排序的出现就是为了解决插入排序的这种局限性,它通过交换不相邻的元素,每次可以将逆序数量减少大于 1。

希尔排序使用插入排序对间隔 h 的序列进行排序。通过不断减小 h,最后令 h=1,就可以使得整个数组是有序的。

希尔排序的运行时间达不到平方级别,使用递增序列 1, 4, 13, 40, ... 的希尔排序所需要的比较次数不会超过 N 的若干倍乘于递增序列的长度。后面介绍的高级排序算法只会比希尔排序快两倍左右。

归并排序的思想是将数组分成两部分,分别进行排序,然后归并起来。

归并方法将数组中两个已经排序的部分归并成一个。

将一个大数组分成两个小数组去求解。

因为每次都将问题对半分成两个子问题,这种对半分的算法复杂度一般为 O(NlogN)。

先归并那些微型数组,然后成对归并得到的微型数组。

取 a[l] 作为切分元素,然后从数组的左端向右扫描直到找到第一个大于等于它的元素,再从数组的右端向左扫描找到第一个小于它的元素,交换这两个元素。不断进行这个过程,就可以保证左指针 i 的左侧元素都不大于切分元素,右指针 j 的右侧元素都不小于切分元素。当两个指针相遇时,将切分元素 a[l] 和 a[j] 交换位置。

快速排序是原地排序,不需要辅助数组,但是递归调用需要辅助栈。

快速排序最好的情况下是每次都正好将数组对半分,这样递归调用次数才是最少的。这种情况下比较次数为 CN=2CN/2+N,复杂度为 O(NlogN)。

最坏的情况下,第一次从最小的元素切分,第二次从第二小的元素切分,如此这般。因此最坏的情况下需要比较 N2/2。为了防止数组最开始就是有序的,在进行快速排序时需要随机打乱数组。

因为快速排序在小数组中也会递归调用自己,对于小数组,插入排序比快速排序的性能更好,因此在小数组中可以切换到插入排序。

最好的情况下是每次都能取数组的中位数作为切分元素,但是计算中位数的代价很高。一种折中方法是取 3 个元素,并将大小居中的元素作为切分元素。

对于有大量重复元素的数组,可以将数组切分为三部分,分别对应小于、等于和大于切分元素。

三向切分快速排序对于有大量重复元素的随机数组可以在线性时间内完成排序。

快速排序的 partition() 方法,会返回一个整数 j 使得 a[l..j-1] 小于等于 a[j],且 a[j+1..h] 大于等于 a[j],此时 a[j] 就是数组的第 j 大元素。

可以利用这个特性找出数组的第 k 大的元素。

该算法是线性级别的,假设每次能将数组二分,那么比较的总次数为 (N+N/2+N/4+..),直到找到第 k 个元素,这个和显然小于 2N。

堆中某个节点的值总是大于等于其子节点的值,并且堆是一颗完全二叉树。

堆可以用数组来表示,这是因为堆是完全二叉树,而完全二叉树很容易就存储在数组中。位置 k 的节点的父节点位置为 k/2,而它的两个子节点的位置分别为 2k 和 2k+1。这里不使用数组索引为 0 的位置,是为了更清晰地描述节点的位置关系。

在堆中,当一个节点比父节点大,那么需要交换这个两个节点。交换后还可能比它新的父节点大,因此需要不断地进行比较和交换操作,把这种操作称为上浮。

类似地,当一个节点比子节点来得小,也需要不断地向下进行比较和交换操作,把这种操作称为下沉。一个节点如果有两个子节点,应当与两个子节点中最大那个节点进行交换。

将新元素放到数组末尾,然后上浮到合适的位置。

从数组顶端删除最大的元素,并将数组的最后一个元素放到顶端,并让这个元素下沉到合适的位置。

把最大元素和当前堆中数组的最后一个元素交换位置,并且不删除它,那么就可以得到一个从尾到头的递减序列,从正向来看就是一个递增序列,这就是堆排序。

一个堆的高度为logN,因此在堆中插入元素和删除最大元素的复杂度都为 logN。

对于堆排序,由于要对 N 个节点进行下沉操作,因此复杂度为 NlogN。

堆排序是一种原地排序,没有利用额外的空间。

现代操作系统很少使用堆排序,因为它无法利用局部性原理进行缓存,也就是数组元素很少和相邻的元素进行比较和交换。

计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,==计数排序要求输入的数据必须是有确定范围的整数==。

当输入的元素是 n 个 0 到 k 之间的整数时,它的==运行时间是 O(n + k)==。计数排序不是比较排序,排序的速度快于任何比较排序算法。由于用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),这使得计数排序对于数据范围很大的数组,需要大量时间和内存。比较适合用来排序==小范围非负整数数组的数组==。

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点:

同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。

当输入数据均匀分配到每一个桶时最快,当都分配到同一个桶时最慢。

实间复杂度N*K

快速排序是最快的通用排序算法,它的内循环的指令很少,而且它还能利用缓存,因为它总是顺序地访问数据。它的运行时间近似为 ~cNlogN,这里的 c 比其它线性对数级别的排序算法都要小。

使用三向切分快速排序,实际应用中可能出现的某些分布的输入能够达到线性级别,而其它排序算法仍然需要线性对数时间。

‘贰’ 二分查找法的具体算法

折半查找法也称为二分查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(log n)完成搜索任务。它的基本思想是,将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的x作比较,如果x=a[n/2]则找到x,算法终止。如果x<a[n/2],则我们只要在数组a的左半部继续搜索x(这里假设数组元素呈升序排列)。如果x>a[n/2],则我们只要在数组a的右半部继续搜索x。二分搜索法的应用极其广泛,而且它的思想易于理解,但是要写一个正确的二分搜索算法也不是一件简单的事。第一个二分搜索算法早在1946年就出现了,但是第一个完全正确的二分搜索算法直到1962年才出现。Bentley在他的着作《Writing Correct Programs》中写道,90%的计算机专家不能在2小时内写出完全正确的二分搜索算法。问题的关键在于准确地制定各次查找范围的边界以及终止条件的确定,正确地归纳奇偶数的各种情况,其实整理后可以发现它的具体算法是很直观的,我们可用C++描述如下:

template<class Type>

int BinarySearch(Type a[],const Type& x,int n)

{

int left=0;

int right=n-1;

while(left<=right){

int middle=(left+right)/2;

if (x==a[middle]) return middle;

if (x>a[middle]) left=middle+1;

else right=middle-1;

}

return -1;

}

模板函数BinarySearch在a[0]<=a[1]<=...<=a[n-1]共n个升序排列的元素中搜索x,找到x时返回其在数组中的位置,否则返回-1。容易看出,每执行一次while循环,待搜索数组的大小减少一半,因此整个算法在最坏情况下的时间复杂度为O(log n)。在数据量很大的时候,它的线性查找在时间复杂度上的优劣一目了然。

‘叁’ 查找算法有哪些

查找算法常用的有,顺序查找,二分查找,哈希表查找,等等。

‘肆’ 什么是查找算法

查找就是在一个数据集合里查找到你需要的数据,查找算法就是在查找过程中使用的算法。查找算法有好多,最基础的就是线性表查找。
因为提到了算法,所以需要注意的是时间复杂度跟空间复杂度,进而涉及到数据的存储方式,比如数组,链表,矩阵,树,图等等数据结构,这些数据结构可以帮助你降低算法的复杂度。
如果有兴趣,随便找本数据结构书翻翻,里面或多或少都会有讲解。

‘伍’ 二分法查找的算法

假如有一组数为3,12,24,36,55,68,75,88要查给定的值24.可设三个变量front,mid,end分别指向数据的上界,中间和下界,mid=(front+end)/2.
1.开始令front=0(指向3),end=7(指向88),则mid=3(指向36)。因为mid>x,故应在前半段中查找。
2.令新的end=mid-1=2,而front=0不变,则新的mid=1。此时x>mid,故确定应在后半段中查找。
3.令新的front=mid+1=2,而end=2不变,则新的mid=2,此时a[mid]=x,查找成功。
如果要查找的数不是数列中的数,例如x=25,当第三次判断时,x>a[mid],按以上规律,令front=mid+1,即front=3,出现front>end的情况,表示查找不成功。
例:在有序的有N个元素的数组中查找用户输进去的数据x。
算法如下:
1.确定查找范围front=0,end=N-1,计算中项mid=(front+end)/2。
2.若a[mid]=x或front>=end,则结束查找;否则,向下继续。
3.若a[mid]<x,说明待查找的元素值只可能在比中项元素大的范围内,则把mid+1的值赋给front,并重新计算mid,转去执行步骤2;若a[mid]>x,说明待查找的元素值只可能在比中项元素小的范围内,则把mid-1的值赋给end,并重新计算mid,转去执行步骤2。
[一维数组,折半查找]

‘陆’ 查找算法有哪两种类型

二分查找又称折半查找,它是一种效率较高的查找方法。
分块查找又称索引顺序查找,它是顺序查找的一种改进方法。
方法描述:将n个数据元素"按块有序"划分为m块(m ≤ n)。每一块中的结点不必有序,但块与块之间必须"按块有序";即第1块中任一元素的关键字都必须小于第2块中任一元素的关键字;而第2块中任一元素又都必须小于第3块中的任一元素,……。

‘柒’ 数据结构中有哪些查找算法

和二分查找性能接近的:既然可以二分查找,那么关键字肯定可以满足全序关系。那么可以用二叉查找树,一般的就是平摊O(logn),最坏O(n)。如果用平衡树,如AVL,Treap,Splay等等,可以做到保持O(logn)的界。
比二分查找性能更优的:大概只有Hash了吧。如果Hash函数设计的好,基本可以认为是O(1)的。这个你最好系统学习一下,尤其是字符串的Hash函数。

‘捌’ 对比顺序查找,二分查找和哈希查找算法,它们各自的特点是什么

1.对比顺序查找就是顺序的一个一个的比下去..1和2、1 和3、1和4...1和n
2.二分查找就是先和最中间的元素比较 大于此元素时将起始下标设置为此元素下表 继续和右边的中间元素比较,直到查找成功位置 相反小于则和左边的比较(默认数组一从小到大排序完整)
3.哈希算法是将任意长度的二进制值映射为固定长度的较小二进制值,这个小的二进哈希函数是一个数学方程式,它可用文本(如电子邮件信息)来生成称为信息摘要的代码。着名的哈希函数如:MD4,MD5,SHS。

热点内容
linuxshell密码 发布:2025-05-14 17:21:11 浏览:199
安卓手机听筒在哪里关闭 发布:2025-05-14 17:16:20 浏览:454
我的世界炸毁50万服务器 发布:2025-05-14 17:16:07 浏览:123
存储站源 发布:2025-05-14 17:14:20 浏览:864
win2008的ftp设置 发布:2025-05-14 17:03:31 浏览:663
莱克发的工资卡密码是多少 发布:2025-05-14 16:57:10 浏览:178
方舟怎么用自己的存档进入别人的服务器 发布:2025-05-14 16:46:25 浏览:878
微博视频高清上传设置 发布:2025-05-14 16:38:41 浏览:548
数据库图书管理设计 发布:2025-05-14 16:33:52 浏览:379
php开发的网页 发布:2025-05-14 16:22:03 浏览:478