python排序链表快速排序_Python中的快速排序算法,快速排序的优缺点,中级python技术点...

c75c10385343fbf234324591e8e5658664388f8c.jpeg?token=0c42d8b2e6aa2a0c0aa71123e21a203e

Python中的快速排序算法

就像合并排序一样,快速排序算法采用分治法的原理将输入数组分为两个列表,第一个包含小项目,第二个包含大项目。然后,该算法将对两个列表进行递归排序,直到对结果列表进行完全排序为止。

划分输入列表称为对列表进行分区。快速排序首先选择一个主元素并围绕这个主元素对列表进行分区,将每个较小的元素放入一个低数组,将每个较大的元素放入一个高数组。

将低链表中的每个元素放到主链表的左边,将高链表中的每个元素放到主链表的右边,使主链表精确地位于排序后的主链表中所需要的位置。这意味着该函数现在可以递归地对low和high应用相同的过程,直到整个列表被排序。

在Python中实现Quicksort

这是quicksort的一个相当紧凑的实现:

b90e7bec54e736d1beb65112c2cbe0c4d46269a1.jpeg?token=79276096fe1d309be7c77430b6c263f9

以下是代码摘要:

如果数组包含的元素少于两个,第6行将停止递归函数。第12行从列表中随机选择主元素,然后对列表进行分区。第19行和第20行将所有小于pivot的元素放入名为low的列表中。第21行和第22行把每一个等于主元素的元素放到这个叫做相同的列表中。第23行和第24行将每个大于pivot的元素放入名为high的列表中。第28行递归地对低链表和高链表进行排序,并将它们与同一链表的内容组合在一起。下面是快速排序对数组进行排序的步骤的说明[8, 2, 6, 4, 5]:

ca1349540923dd54e1fb76d389921cd89d824827.jpeg?token=c25ffbecdc53162c49f525c044b676f9

黄线表示阵列的划分成三个列表:low,same,和high。绿线表示排序并将这些列表放在一起。以下是步骤的简要说明:

主元是随机选择的。在这种情况下,主元是 6第一个传递分区输入数组,low包含[2,4,5],同样包含[6],high包含[8]。然后递归地调用quicksort(),以low作为输入。这将选择一个随机的主元,并将数组分为[2]低、[4]相同和[5]高。这个过程还在继续,但是在这一点上,low和high都有两个以下的项。这就结束了递归,函数将数组重新组合在一起。将排序后的low和high分别添加到同一个列表的任意一端,生成[2、4、5]。另一方面,包含[8]的高链表有少于两个元素,因此算法返回排序后的低数组,它现在是[2,4,5]。将其与same([6])和high([8])合并将生成最终的排序列表。选择主元

为什么上面的实现会随机选择主元素?一致地选择输入列表的第一个或最后一个元素不是同样的吗?

由于快速排序算法的工作方式,递归层的数量取决于主元在每个分区中的位置。在最佳情况下,算法始终选择中位数元素作为轴心。这将使每个生成的子问题的大小正好是前一个问题的一半,导致最多达到log2n级别。

另一方面,如果算法始终选择数组中最小或最大的元素作为主元素,那么生成的分区将尽可能不相等,导致n-1递归级别。这是快速排序最坏的情况。

正如您所看到的,快速排序的效率通常取决于主选择。如果输入数组是未排序的,那么使用第一个或最后一个元素作为主元素将与随机元素一样工作。但是,如果输入数组是排序的或几乎是排序的,使用第一个或最后一个元素作为主元素可能会导致最坏的情况。随机选择支点使得快速排序更有可能选择一个更接近中位数的值,并且完成得更快。

选择主元的另一种方法是找到数组的中值,并强制算法使用它作为主元。这可以在O(n)时间内完成。虽然这个过程有点复杂,但是使用中间值作为快速排序的主元素可以确保您得到最好的大O场景。

a50f4bfbfbedab64193eac22a0ad00c578311e21.jpeg?token=be51c577114dfa57beac6ea42bd982ee

衡量Quicksort的大复杂性

使用快速排序,输入列表在线性时间O(n)内进行分区,这个过程递归地重复平均log2n次。这就导致了O(n log2n)的最终复杂度。

也就是说,还记得关于支点的选择如何影响算法运行时的讨论吗?O(n)最佳情况发生在所选的主元接近数组的中位数时,O(n2)情况发生在主元是数组的最小值或最大值时。

从理论上讲,如果算法首先集中于寻找中值,然后将其用作主元素,那么最坏情况复杂度将降至O(n log2n)。数组的中位数可以在线性时间内找到,使用它作为轴心可以保证代码的快速排序部分将在O(n log2n)中执行。

通过使用中值作为主元,最终得到O(n) + O(n log2n)的运行时。可以化简为O(n log2n)因为对数部分的增长速度比线性部分快得多。

定时实施Quicksort

到目前为止,您已经熟悉了算法运行时间的计时过程。只需在第8行中更改算法的名称即可:

00e93901213fb80e3aea63f3614a8028b9389478.jpeg?token=91d824f83ffe0f5a8a46543b3f53093e

您可以像以前一样执行脚本:

Shell

$ python sorting.py

Algorithm: quicksort. Minimum execution time: 0.11675417600002902

快速排序不仅在不到一秒内完成,而且比合并排序快得多(0.11秒对0.61秒)。将ARRAY_LENGTH指定的元素数量从10,000增加到1,000,000并再次运行脚本,最终会在97秒内完成合并排序,而快速排序仅在10秒内对列表进行排序。

分析快速排序的优缺点

顾名思义,快速排序非常快。虽然理论上最坏的情况是O(n2),但实际上,快速排序的良好实现胜过大多数其他排序实现。另外,就像归并排序一样,快速排序也可以直接并行化。

快速排序的主要缺点之一是不能保证它将达到平均运行时复杂度。尽管最坏的情况很少出现,但某些应用程序不能冒性能差的风险,因此它们会选择O(n log2n)以内的算法,而不管输入是什么。

就像归并排序一样,快速排序也需要用内存空间来换取速度。这可能会成为对较大列表进行排序的限制。

对10个元素的列表进行快速排序,可以得到以下结果:

Shell

Algorithm: bubble_sort. Minimum execution time: 0.0000909000000000014

Algorithm: insertion_sort. Minimum execution time: 0.00006681900000000268

Algorithm: quicksort. Minimum execution time: 0.0001319930000000004

结果表明,当列表足够小时,快速排序也要付出递归的代价,完成时间比插入排序和冒泡排序都要长。

8d5494eef01f3a2928126c96cfbe13375d607c35.jpeg?token=dd6f0cdb11ff426000f7acc06ea3ef8e

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值