各位老铁们,大家好,今天由我来为大家分享基数排序的时间复杂度,以及基数排序的代码的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们更大的动力,谢谢大家了哈,下面我们开始吧!
本文目录
一、...归并排序”和“堆排序”的时间复杂度分别是多少
所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。分类在计算机科学所使用的排序算法通常被分类为:计算的复杂度(最差、平均、和更好表现),依据串列(list)的大小(n)。一般而言,好的表现是O。(n log n),且坏的行为是Ω(n2)。对於一个排序理想的表现是O(n)。仅使用一个抽象关键比较运算的排序算法总平均上总是至少需要Ω(n log n)。记忆体使用量(以及其他电脑资源的使用)
稳定度:稳定排序算法会依照相等的关键(换言之就是值)维持纪录的相对次序。也就是一个排序算法是稳定的,就是当有两个有相等关键的纪录R和S,且在原本的串列中R出现在S之前,在排序过的串列中R也将会是在S之前。一般的 *** :插入、交换、选择、合并等等。交换排序包含冒泡排序(bubble sort)和快速排序(quicksort)。选择排序包含shaker排序和堆排序(heapsort)。当相等的元素是无法分辨的,比如像是整数,稳定度并不是一个问题。然而,假设以下的数对将要以他们的之一个数字来排序。(4, 1)(3, 1)(3, 7)(5, 6)在这个状况下,有可能产生两种不同的结果,一个是依照相等的键值维持相对的次序,而另外一个则没有:(3, 1)(3, 7)(4, 1)(5, 6)(维持次序)(3, 7)(3, 1)(4, 1)(5, 6)(次序被改变)
不稳定排序算法可能会在相等的键值中改变纪录的相对次序,但是稳定排序算法从来不会如此。不稳定排序算法可以被特别地时作为稳定。作这件事情的一个方式是人工扩充键值的比较,如此在其他方面相同键值的两个物件间之比较,就会被决定使用在原先资料次序中的条目,当作一个同分决赛。然而,要记住这种次序通常牵涉到额外的空间负担。排列算法列表在这个表格中,n是要被排序的纪录数量以及k是不同键值的数量。
冒泡排序(bubble sort)— O(n2)
鸡尾酒排序(Cocktail sort,双向的冒泡排序)— O(n2)
插入排序(insertion sort)— O(n2)
计数排序(counting sort)— O(n+k);需要 O(n+k)额外记忆体
归并排序(merge sort)— O(n log n);需要 O(n)额外记忆体
原地归并排序— O(n2)二叉树排序(Binary tree sort)— O(n log n);需要 O(n)额外记忆体
鸽巢排序(Pigeonhole sort)— O(n+k);需要 O(k)额外记忆体
基数排序(radix sort)— O(n·k);需要 O(n)额外记忆体
Gnome sort— O(n2) Library sort— O(n log n) with high probability,需要(1+ε)n额外记忆体
选择排序(selection sort)— O(n2)
希尔排序(shell sort)— O(n log n)
如果使用更佳的现在版本 Comb sort— O(n log n)
堆排序(heapsort)— O(n log n) Smoothsort— O(n log n)
快速排序(quicksort)— O(n log n)
期望时间, O(n2)最坏情况;对於大的、乱数串列一般相信是最快的已知排序 Introsort— O(n log n) Patience sorting— O(n log n+ k)最外情况时间,需要额外的 O(n+ k)空间,也需要找到最长的递增子序列(longest increasing subsequence)不实用的排序算法 Bogo排序— O(n× n!)期望时间,无穷的最坏情况。 Stupid sort— O(n3);递回版本需要 O(n2)额外记忆体 Bead sort— O(n) or O(√n),但需要特别的硬体 Pancake sorting— O(n),但需要特别的硬体排序的算法排序的算法有很多,对空间的要求及其时间效率也不尽相同。下面列出了一些常见的排序算法。这里面插入排序和冒泡排序又被称作简单排序,他们对空间的要求不高,但是时间效率却不稳定;而后面三种排序相对于简单排序对空间的要求稍高一点,但时间效率却能稳定在很高的水平。基数排序是针对关键字在一个较小范围内的排序算法。插入排序冒泡排序选择排序快速排序堆排序归并排序基数排序希尔排序插入排序插入排序是这样实现的:首先新建一个空列表,用于保存已排序的有序数列(我们称之为"有序列表")。从原数列中取出一个数,将其插入"有序列表"中,使其仍旧保持有序状态。重复2号步骤,直至原数列为空。插入排序的平均时间复杂度为平方级的,效率不高,但是容易实现。它借助了"逐步扩大成果"的思想,使有序列表的长度逐渐增加,直至其长度等于原列表的长度。冒泡排序冒泡排序是这样实现的:首先将所有待排序的数字放入工作列表中。从列表的之一个数字到倒数第二个数字,逐个检查:若某一位上的数字大于他的下一位,则将它与它的下一位交换。重复2号步骤,直至再也不能交换。冒泡排序的平均时间复杂度与插入排序相同,也是平方级的,但也是非常容易实现的算法。选择排序选择排序是这样实现的:设数组内存放了n个待排数字,数组下标从1开始,到n结束。 i=1从数组的第i个元素开始到第n个元素,寻找最小的元素。将上一步找到的最小元素和第i位元素交换。如果i=n-1算法结束,否则回到第3步选择排序的平均时间复杂度也是O(n²)的。快速排序现在开始,我们要接触高效排序算法了。实践证明,快速排序是所有排序算法中更高效的一种。它采用了分治的思想:先保证列表的前半部分都小于后半部分,然后分别对前半部分和后半部分排序,这样整个列表就有序了。这是一种先进的思想,也是它高效的原因。因为在排序算法中,算法的高效与否与列表中数字间的比较次数有直接的关系,而"保证列表的前半部分都小于后半部分"就使得前半部分的任何一个数从此以后都不再跟后半部分的数进行比较了,大大减少了数字间不必要的比较。但查找数据得另当别论了。堆排序堆排序与前面的算法都不同,它是这样的:首先新建一个空列表,作用与插入排序中的"有序列表"相同。找到数列中更大的数字,将其加在"有序列表"的末尾,并将其从原数列中删除。重复2号步骤,直至原数列为空。堆排序的平均时间复杂度为nlogn,效率高(因为有堆这种数据结构以及它奇妙的特征,使得"找到数列中更大的数字"这样的操作只需要O(1)的时间复杂度,维护需要logn的时间复杂度),但是实现相对复杂(可以说是这里7种算法中比较难实现的)。看起来似乎堆排序与插入排序有些相像,但他们其实是本质不同的算法。至少,他们的时间复杂度差了一个数量级,一个是平方级的,一个是对数级的。平均时间复杂度插入排序 O(n2)冒泡排序 O(n2)选择排序 O(n2)快速排序 O(n log n)堆排序 O(n log n)归并排序 O(n log n)基数排序 O(n)希尔排序 O(n1.25)
二、常见排序算法以及对应的时间复杂度和空间复杂度
排序:将杂乱无章的数据,按照一定的 *** 进行排列的过程叫做排序。
排序大的分类可分为内排序和外排序,不需要访问外存就能进行排序的叫做内排序。
排序也可以分为稳定排序和不稳定排序
稳定排序:假设在待排序的文件中,存在两个或两个以上的记录具有相同的关键字,在用某种排序法排序后,若这些相同关键字的元素的相对次序仍然不变,则这种排序 *** 是稳定的。即;若 a[i]=a[j], a[i]在 a[j]之前,经过排序后 a[i]依然在 a[j]之前。冒泡排序、直接插入排序、二分插入排序、归并排序,基数排序都是稳定排序。
不稳定排序:直接选择排序、堆排序、快速排序、希尔排序,猴子排序。
以升序为例,比较相邻的元素,如果之一个比第二个大,则交换他们两个。如果两个元素一样大,则继续比较下一对。所以冒泡排序是一种稳定排序。
选择一个基准元素,通常选择之一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的 *** 递归地排序划分的两部分。快速排序是不稳定排序。
将序列分为两个部分{{有序序列},{无序}},每次处理就是将无序数列的之一个元素与有序数列的元素从后往前逐个进行比较,找出插入位置,将该元素插入到有序数列的合适位置中。如果碰到相等的元素,就会把它插入到想等元素后面,顺序不会改变,所以直接插入排序是稳定排序。
在直接插入排序的基础上,对有序序列进行划分。例如:序列为{{a[0]......a[i-1]},a[i]}其中{a[0]......a[i-1]}为有序序列,取 a[(i-1)/2],将其与 a[i]比较,即可确定 a[i]的范围(a[0]...a[(i-1)/2]或者 a[(i-1)/2]...a[i-1]),然后继续在已确定的范围内进行二分。范围依次缩小为: 1/2、1/4、1/8、1/16......可快速确定a[i]应该插入的位置。二分插入排序也是稳定排序。
将整个序列分割成若干个小的子序列,每个子序列内分别进行插入排序。一般情况下步长取n/2。直到最后一次步长为1,即所有元素在一个组中进行排序。由于希尔排序是先将整个序列划分为多个子序列进行排序,相同的元素顺序在这个过程中顺序可能会被打乱,所以希尔排序是不稳定排序。
从待排序的数据元素中,选出最小或更大的元素与序列之一个数交换。直到所有数据排完。直接选择排序是不稳定排序。例如:{3,3,1},之一次排序就将1和之一个3交换,想等元素的顺序改变了。
以n=10的一个数组49, 38, 65, 97, 26, 13, 27, 49, 55, 4为例
堆排序是一种树形选择排序,是对直接选择排序的有效改进。
更大堆:每个节点的值都大于等于它的孩子节点。
最小堆:每个节点的值都小于等于它的孩子节点。
更大堆第0个数据是更大数,最小堆第0个数据是最小数。
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
如何将两个有序序列合并?(升序)
{a[0]......a[i-1]},{b[0]......b[j-1]}
若 b[0]<a[0],取 b[0]放入数组 c中,然后继续比较数组 a和 b中的之一个元素,直到数组 a和 b中最后一对元素比较完成。
将数组分成二组 a, b如果这二组组内的数据都是有序的,那么就可以按照上述 *** 对这二组数据进行排序。如果这二组数据是无序的?
可以将 a, b组各自再分成二组。递归操作,直到每个小组只有一个数据,每个小组只有一个元素所以我们可以认为它已经是有序序列,然后进行合并。
将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。从更低位起从0-9依次扫描序列,一边扫描一边将扫描到的数据加到新的序列中,得到一个序列。然后比较高一位,重复上述操作,直到更高位排序完成。数列就变成一个有序序列。基数排序是稳定排序。
无限猴子定理:指一只猴子随机在打字机键盘上按键,最后必然可以打出法国国家图书馆的每本图书。
时间复杂度更低1次,更高可执行到世界的尽头。。。
三、基数排序稳定吗
1、基数排序只有从更低位开始才是稳定的排序算法。
2、基数排序每次都调用一个稳定排序,也就是说这一轮比不出大小的数据,保持原来的相对位置顺序不变。(这是稳定排序的定义,是性质,不是某种随意的文字描述)而数字比较大小就是从高位开始,比不出大小去看低位,当然应该让低位先排出“原来的相对顺序”了。
3、从高位开始排,就要分段了,每排完一位,把分不出大小的几个当成一段,一段段的排,不要让排完的数据跨段移动,保证这一段的数都比下一段小,排到最后每段就只有一个数了。这样就完全没有利用到每次调用的都是稳定排序这一点,感觉上丑多了,也没什么意思。
4、任何计算机相关专业的学生都学过很多排序算法,然而在算法竞赛中,我们会发现大部分排序算法都不怎么用得上(尤其是那堆O(n2)算法),快速排序和归并排序已经基本够用了,它们的平均时间复杂度都是O(nlogn)。
5、实际上,学术上已经有证明,任何基于比较的排序算法的时间复杂度不能比这更优了。也就是说,如果不对待排序数据的性质有特殊要求,只任意给出偏序关系,那不可能存在小于O(nlogn)的排序算法。
6、但在竞赛中,这样的复杂度有时是不够的。而我们要排序的数据,有时恰恰满足一些特殊性质。例如当待排序数据是不太大的自然数(均满足≤m)时,可以使用计数排序,把待排序数据当作数组下标处理,时间复杂度是O(n+m),并额外有O(m)的空间复杂度。
OK,关于基数排序的时间复杂度和基数排序的代码的内容到此结束了,希望对大家有所帮助。