排序算法之快速排序及其优化
快速排序
其他排序方法:选择排序、冒泡排序、归并排序、快速排序、插入排序、希尔排序、堆排序
思想
从数组中选取一个元素,以它作为比较基准,比它小的都放到数组左边;比它大的则放到右边。然后左边的数组和右边的数组也进行同样的操作。这样递归下去,最后数组就会成为一个有序的数组。
图解
借用一下百科的图:
性能
快速排序时不稳定的,它的最好和平均时间复杂度为O(nlogn)。
最坏的情况就是每次所选的基准都是当前序列中的最大或最小元素,这样每次划分的两个子数组中都有一个是空数组,则最终需要经过n次划分,最坏的时间复杂度为O(logn^2)。
python的递归层数是有限制的,当n大到一定程度时,就会崩掉。所以我们应该尽量避免最坏的情况发生。
代码
Python:
# 快速排序
# left为第一个下标,right为最后一个下标
def quickSort(arr, left, right):
if left >= right: return
# 将第一位元素设为比较基准
key = arr[left]
i, j = left, right
# 比基准小的元素都放到左边,大的都放到右边
while i < j:
while i < j and arr[j] >= key:
j -= 1
arr[i] = arr[j]
while i < j and arr[i] <= key:
i += 1
arr[j] = arr[i]
arr[i] = key
# 左右两边的数组进行同样的操作
quickSort(arr, left, i - 1)
quickSort(arr, i + 1, right)
优化
快速排序的优化主要针对于最坏情况的优化,如何避免每次所选的基准都是当前序列中的最大或最小元素?
我们通常是取第一位元素作为基准值。数组如果一开始就是有序的话,就是最坏情况了。
改进方法:
有一种方法就是在排序之前shuffle一下(打乱顺序);
还有一种是不取第一位元素,而是取第一位、最后一位和中间位中的中值元素作为基准值,这样就能完全避免最坏情况了。
# 取中值
def midVal(arr, left, right):
mid = left + right >> 1
if arr[mid] > arr[right]:
arr[mid], arr[right] = arr[right], arr[mid]
if arr[left] > arr[right]:
arr[left], arr[right] = arr[right], arr[left]
if arr[mid] > arr[left]:
arr[left], arr[mid] = arr[mid], arr[left]
return arr[left]
# 快速排序
# left为第一个下标,right为最后一个下标
def quickSort(arr, left, right):
if left >= right: return
# 取第一位、最后一位和中间位中的中值元素作为基准值
key = midVal(arr, left, right)
i, j = left, right
# 比基准小的元素都放到左边,大的都放到右边
while i < j:
while i < j and arr[j] >= key:
j -= 1
arr[i] = arr[j]
while i < j and arr[i] <= key:
i += 1
arr[j] = arr[i]
arr[i] = key
# 左右两边的数组进行同样的操作
quickSort(arr, left, i - 1)
quickSort(arr, i + 1, right)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构