IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    快速排序

    博客 - DannySite发表于 2015-08-24 13:27:20
    love 0
    概览 快速排序基于分治模式,其基本思想是在一次排序中将一列元素拆分成两个部分,以一个“中间值”(称之为主元)为界,其左边的元素总是小于等于它,而右边的元素则总是大于或等于它。然后递归的对左列元素和右列元素进行此操作。这样即可实现对整列元素的排序。 Partition 过程 快速排序的关键在于确定这个“左”和“右”,即如何对一个数组进行划分。对于最原始的快速排序来说,总是将要排序数组中的第一个元素当作主元,然后左右交替的迭代数组中的元素,并最终达到之前所说的目标:主元左边的元素始终不大于主元,而右边的元素始终不小于主元。下图展示了该过程: p 为主元,即初始时数组中的第一个元素; i 和 j 的初始状态分别指向数组的最左边和最右边。 第一次从右至左找寻比 p 小的元素,并将两者交换; 第二次从左至右找寻比 p 大的元素,并将两者交换; 循环进行,直到 i、j 相遇。 来看看 Python 实现的示例代码: def partition(l, p, r): """ PARTITION 过程,实现对子列表 l[p, r] 的原址重排 :param l: 排序列表 :param p: 起始位置 :param r: 终止位置 :return: 主元(pivot) """ # 将子列表的第一个元素作为主元, # 则排序后的列表中主元左侧的元素小于或等于主元,右侧的元素大于或等于主元 pivot = l[p] left = p right = r while left < right: # 整个查找左右交替进行 # 当从左至右查找,查询比主元小的元素 # 当从右至左查找,则查询比主元大的元素 while left < right and l[right] >= pivot: right -= 1 l[left], l[right] = l[right], l[left] while left < right and l[left] <= pivot: left += 1 l[left], l[right] = l[right], l[left] # 最后将主元所在的位置返回 return left 快速排序 之后要做的就是针对左右两侧的数组递归的进行划分,这样就构成了快速排序: def quick_sort(l, p=0, r=None): """ 快速排序 :param l: 排序列表 :param p: 排序起始位置 :param r: 排序终止位置 :return: 无返回 """ r = len(l) - 1 if r is None else r if p < r: # 调用 PARTITION 函数对列表进行划分,并得到划分的支点,即主元所在的位置 q = partition(l, p, r) # 以主元为中心,对左、后子数组再次排序 quick_sort(l, p, q - 1) quick_sort(l, q + 1, r) 时间复杂度 快速排序的期望时间复杂度是O(nlgn)。但针对一个已经排好序的数组来说,其递归树呈完全的“一边倒”趋势,导致其最坏情况的时间复杂度为O(n^2)。 当然在之前,我用了一个名词叫最原始的快速排序。因为通过改进可以很好的避免这种情况发生。如随机化快速排序通过随机选取主元来规避”一边倒“的情况。很多资料中都有详细的描述,这仅仅简单一提,而这些也值得我去更深入地探索和学习。 参考文档 《算法导论》第七章


沪ICP备19023445号-2号
友情链接