如何理解快速排序的时间复杂度是O(nlogn)

选择排序、冒泡排序等算法的时间复杂度都比较好理解,但不是很清楚快速排序的时间复杂度为什么是O(nlogn)。从《算法图解》中看到的思路,很赞,解决了一直以来的疑惑。

引用自《算法图解》:

快速排序的情况比较棘手,在最糟情况下,其运行时间为O(n2)。。在平均情况下,快速排序的运行时间为O(nlogn)。

1、平均情况与最糟情况

快速排序的性能高度依赖于你选择的基准值。

  • 最糟情况
    假设你总是将第一个元素用作基准值,且要处理的数组是有序的。由于快速排序算法不检查输入数组是否有序,因此它依然尝试对其进行排序。注意,数组并没有被分成两半,相反,其中一个子数组始终为空,这导致调用栈非常长在这里插入图片描述
  • 平均情况
    假设你总是将中间的元素用作基准值,在这种情况下,调用栈如下。 调用栈短得多!因为你每次都将数组分成两半,所以不需要那么多递归调用。你很快就到达 了基线条件,因此调用栈短得多。
    在这里插入图片描述
    第一个示例展示的是最糟情况,而第二个示例展示的是最佳情况。在最糟情况下,栈长为 O(n),而在最佳情况下,栈长为O(log n)。

现在来看看栈的第一层。你将一个元素用作基准值,并将其他的元素划分到两个子数组中。 这涉及数组中的全部8个元素,因此该操作的时间为O(n)。在调用栈的第一层,涉及全部8个元素, 但实际上,在调用栈的每层都涉及O(n)个元素。
在这里插入图片描述
即便以不同的方式划分数组,每次也将涉及O(n)个元素。
在这里插入图片描述
在这个示例中,调用栈的高度为O(log n),而每层需要的时间为O(n)。因此整个算法需要的时间为O(n) * O(log n) = O(n log n)。这就是最佳情况。 在最糟情况下,有O(n)层,因此该算法的运行时间为O(n) * O(n) = O(n2)。

2、归并排序和快速排序的时间复杂度都是 O(nlogn),为什么说快速排序一般优于归并排序?

首先搬运stackOverflow的回答:Why is mergesort better for linked lists?

One of the main sources of efficiency in quicksort is locality of reference, where the computer hardware is optimized so that accessing memory locations that are near one another tends to be faster than accessing memory locations scattered throughout memory. The partitioning step in quicksort typically has excellent locality, since it accesses consecutive array elements near the front and the back. As a result, quicksort tends to perform much better than other sorting algorithms like heapsort even though it often does roughly the same number of comparisons and swaps, since in the case of heapsort the accesses are more scattered.
Additionally, quicksort is typically much faster than other sorting algorithms because it operates in-place, without needing to create any auxiliary arrays to hold temporary values. Compared to something like merge sort, this can be a huge advantage because the time required to allocate and deallocate the auxiliary arrays can be noticeable. Operating in-place also improves quicksort’s locality.
When working with linked lists, neither of these advantages necessarily applies. Because linked list cells are often scattered throughout memory, there is no locality bonus to accessing adjacent linked list cells. Consequently, one of quicksort’s huge performance advantages is eaten up. Similarly, the benefits of working in-place no longer apply, since merge sort’s linked list algorithm doesn’t need any extra auxiliary storage space.
That said, quicksort is still very fast on linked lists. Merge sort just tends to be faster because it more evenly splits the lists in half and does less work per iteration to do a merge than to do the partitioning step.

翻译一下:
快速排序中效率的主要来源之一是引用位置,在引用位置中,计算机硬件经过优化,因此访问彼此相邻的内存位置往往比访问分散在整个内存中的内存位置更快。quicksort中的分区步骤通常具有很好的局部性,因为它访问前面和后面附近的连续数组元素。因此,快速排序往往比其他排序算法(如heapsort)执行得更好,尽管它通常执行大致相同数量的比较和交换,因为在heapsort的情况下,访问更加分散。

此外,quicksort通常比其他排序算法快得多,因为它在原地运行,而不需要创建任何辅助数组来保存临时值。与merge sort相比,这是一个巨大的优势,因为分配和释放辅助数组所需的时间是显而易见的。就地操作也提高了quicksort的位置。

使用链表时,这两个优点都不一定适用。由于链表单元通常分散在整个内存中,因此访问相邻的链表单元没有额外的局部性好处。因此,quicksort的一个巨大的性能优势被消耗殆尽。类似地,就地工作的好处不再适用,因为merge sort的链表算法不需要任何额外的辅助存储空间。

也就是说,快速排序在链接列表中仍然非常快。合并排序往往更快,因为它更均匀地将列表分成两半,并且每次执行合并所做的工作比执行分区步骤所做的工作更少。

  • 51
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
时间复杂度为O(nlogn)的排序算法有希尔排序,堆排序,快速排序和归并排序。其中归并排序是一种稳定的排序算法,而希尔排序、堆排序和快速排序是不稳定的排序算法。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python-归并排序算法.docx](https://download.csdn.net/download/qq_43934844/87893705)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [时间复杂度O(nlogn)的排序算法](https://blog.csdn.net/qq_43533956/article/details/123978524)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [时间复杂度为O(nlogn)的排序算法](https://blog.csdn.net/qq_46130027/article/details/129765856)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值