赞
踩
❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容,和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣!
推荐:数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注
导航:
- LeetCode解锁1000题: 打怪升级之旅:每题都包括3-5种算法,以及详细的代码实现,刷题面试跳槽必备
- 漫画版算法详解:通过漫画的形式和动态GIF图片把复杂的算法每一步进行详细可视解读,看一遍就掌握
- python源码解读:解读python的源代码与调用关系,快速提升代码质量
- python数据分析可视化:企业实战案例:企业级数据分析案例与可视化,提升数据分析思维和可视化能力
- 程序员必备的数学知识与应用:全面详细的介绍了工程师都必备的数学知识
期待与您一起探索技术、持续学习、一步步打怪升级 欢迎订阅本专栏❤️❤️
现在你是一名军官,负责一个小队的战斗准备。小队有6名士兵,每个人的战斗力不同。为了最大化战斗效率,你需要根据士兵们的战斗力将他们从小到大排序。
这时候你需要让他们根据战斗力从小到大排序你会怎么做?
你命令:“比20战斗力低的,到他左边!比20战斗力高的,到他右边!动作快!”
行动实施:
最终,基准士兵走到中间,正确的位置上。
递归排序:
结局
以上过程你作为军官用的就是快速排序的算法,看着步骤少是因为你能直接知道每个人的战斗力,并且每个人也知道其他人的战斗力,所以大家很快能排序好,实际通过代码实现的话步骤会更多一些,需要有更多的对比,因为没有提前知道其他人战斗力的前提在。
快速排序是一种非常高效的排序算法,由托尼·霍尔在1960年发明。它是一种使用分治策略的递归排序算法,目的是将一个大列表分为两个小列表,小列表中的元素分别比另一列表的元素小,然后递归地排序这两个子列表。
选择基准值(Pivot Selection):
快速排序首先从数组中选择一个元素作为基准值,选择方法有多种,可以是第一个元素、最后一个元素、中间元素,或者随机元素,下图使用第一个元素。
分区操作(Partitioning):
通过重新排列数组,使得比基准值小的元素全部移动到基准值的左侧,而比基准值大的元素全部移动到基准值的右侧。这个操作结束时,基准值就处于数组的中间位置。这一过程称为分区(Partitioning)。
递归排序子数组(Recursively Sorting the Sub-arrays):
递归地将左侧子数组和右侧子数组进行排序。递归的基准情形是子数组的大小为0或1,这时子数组已经达到完全排序。
def quicksort(nums, left, right): """ 递归执行快速排序,不断分割列表。 参数: nums : list[int] -- 待排序的列表 left : int -- 当前分割区域的左边界索引 right : int -- 当前分割区域的右边界索引 """ if left < right: pi = partition(nums, left, right) print(nums, left,pi) quicksort(nums, left, pi - 1) # 递归排序基准左侧的部分 quicksort(nums, pi + 1, right) # 递归排序基准右侧的部分 def partition(nums, left, right): """ 对数组进行划分,返回基准值的最终位置。 参数: nums : list[int] -- 待排序的列表 left : int -- 当前分割区域的左边界索引 right : int -- 当前分割区域的右边界索引 返回: int -- 基准值的最终位置索引 """ pivot = nums[left] # 选择最左边的元素作为基准 i = left + 1 # 将i初始化为基准右边的第一个元素 j = right # 将j初始化为最右边的元素 while True: while i <= j and nums[i] <= pivot: # i从左向右移动,直到找到一个大于基准的值 i += 1 while i <= j and nums[j] > pivot: # j从右向左移动,直到找到一个小于基准的值 j -= 1 if i <= j: nums[i], nums[j] = nums[j], nums[i] # 交换找到的两个值 else: break nums[left], nums[j] = nums[j], nums[left] # 将基准值进行交换 return j # 返回基准值的位置 # 测试代码 arr = [20, 15, 10, 25, 30, 5] quicksort(arr, 0, len(arr) - 1) print("Sorted array:", arr)
# 排序前 初始值
20, 15, 10, 25, 30, 5
# 第一次分区后 比基准值20小的在左边,比20大的在右边
5, 15, 10, 20, 25, 30
详细的动态GIF图参考,每个步骤变化时间2s,建议详细查看对比
# right = 3,指向20
quicksort(nums, left, pi - 1) # 递归排序基准左侧的部分
# 第一次递归左分区 5,15,10
5, 15, 10, 20, 25, 30
# 执行后还是返回 因为交换自己保持不变
5, 15, 10, 20, 25, 30
# pi = 0,指向5
quicksort(nums, left, pi - 1) # 递归排序基准左侧的部分
# 继续调用 quicksort,这时候 left < -1,不成立,所以走到右侧部分
quicksort(nums, pi + 1, right)
# 5, 15, 10, 20, 25, 30 排序 15,10 后
5, 10 ,15, 20, 25, 30
4. 交换后返回j=2
同上忽略
时间复杂度:
空间复杂度:
优点:
缺点:
基于快速排序存在的缺点,我们一起来探讨一下这些问题,并提供几种改进策略,包括代码示例。
最坏情况性能:当输入数组已经接近排序完成或完全逆序时,快速排序的性能退化到 (O(n^2))。这种情况发生在基准值选取不当时,如始终选择第一个元素作为基准值。
重复元素处理:当数组中存在大量重复元素时,快速排序可能会进行不必要的比较和交换,导致效率降低。
一个好的基准值选择可以最大限度地确保数组被均等地分割,从而优化递归的深度和效率。
快速排序通常通过递归实现,递归调用会消耗额外的栈空间。优化递归调用可以减少栈空间的使用。
插入排序在小数组上表现更优,因为它的常数因子较小,简单且快速。
大量重复元素会减慢快速排序的速度,因为它们增加了不必要的比较和交换。
以下是一个集成了这些改进策略的快速排序的Python实现:
import random def quicksort(arr, low, high): while low < high: if high - low < 16: # 小数组使用插入排序 insertion_sort(arr, low, high) break else: pivot_index = partition(arr, low, high) if pivot_index - low < high - pivot_index: quicksort(arr, low, pivot_index - 1) low = pivot_index + 1 else: quicksort(arr, pivot_index + 1, high) high = pivot_index - 1 def partition(arr, low, high): mid = (low + high) // 2 pivot = sorted([arr[low], arr[mid], arr[high]])[1] pivot_index = arr.index(pivot) arr[pivot_index], arr[high] = arr[high], arr[pivot_index] i = low for j in range(low, high): if arr[j] <= pivot: arr[i], arr[j] = arr[j], arr[i] i += 1 arr[i], arr[high] = arr[high], arr[i] return i def insertion_sort(arr, low, high): for i in range(low + 1, high + 1): key = arr[i] j = i - 1 while j >= low and key < arr[j]: arr[j + 1] = arr[j] j -= 1 arr[j + 1] = key array = [random.randint(0, 100) for _ in range(100)] quicksort(array, 0, len(array) - 1) print(array)
这段代码首先处理小数组的优化,并且使用三数取中法来选择基准值,以提高快速排序处理含有重复元素和部分排序数组的效率。此外,通过尾递归优化来减少栈深度。
快速排序适用于大数据集合,尤其是在平均性能很关键的场合。由于其就地排序的特性,也适合用于内存空间有限的系统。然而,对于小数组,其他 (O(n^2)) 的算法如插入排序可能更优,因此在实际应用中,快速排序常与其他排序算法结合使用。例如,在快速排序接近完成时切换到插入排序。
快速排序由于其优异的平均性能,广泛用于各种编程库和系统中,是处理大数据集的首选算法之一。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/616746
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。