Python实现快速排序

快速排序

快速排序使用分而治之来获得与归并排序相同的优点,而不使用额外的存储。

算法步骤:

  1. 首先选择一个值,该值称为 枢轴值 。使用列表中的第一项作为枢轴值。枢轴值的作用是帮助拆分列表。枢轴值属于最终排序列表(通常称为拆分点) 的实际位置,将用于将列表划分为快速排序的后续调用。如果列表的长度小于或等于一,它已经排序。 如果它更大,那么它可以被分区和递归排序。

  2. 分区从通过在列表中剩余项目的开始和结束处定位两个位置标记(我们称为左标记和右标记) 开始。分区的目标是移动相对于枢轴值位于错误侧的项,同时也收敛于分裂点。

  3. 首先增加左标记(左标记右移),直到左标记指向的值大于枢轴值。 然后递减右标(右标记左移),直到右标记指的值小于枢轴值。这两个值就是相对于最终分裂点位置(指的就是枢轴值)不适当的项。 交换这两个项,然后重复该过程。

  4. 在右标变得小于左标记的点时停止。右标记的位置现在是分割点枢轴值可以与拆分点的内容交换,枢轴值现在就位。 此外,分割点左侧的所有项都小于枢轴值,分割点右侧的所有项都大于枢轴值。

  5. 在分割点处划分列表,并且可以在两半上递归调用快速排序

完整代码:

def quickSort(alist):
    """
    快排的主要函数
    :param alist: 要排序的列表
    :return:
    """
    quickSortHepler(alist, 0, len(alist) - 1)


def quickSortHepler(alist, first, last):
    """
    快排使用的递归函数
    :param alist: 要排序的列表
    :param first: 首位作为左标记
    :param last: 末位作为右标记
    :return:
    """
    if first < last:
        # 对列表分区
        splitpoint = partition(alist, first, last)

        # 递归调用,对两个半块上进行快排
        quickSortHepler(alist, first, splitpoint - 1)
        quickSortHepler(alist, splitpoint + 1, last)


def partition(alist, first, last):
    """
    分区函数
    :param alist: 要排序的列表
    :param first: 首位
    :param last: 末位
    :return:
    """
    # 首位作为枢轴值
    pivotvalue = alist[first]

    # 确定左标记和右标记
    leftmark = first + 1
    rightmark = last

    done = False
    while not done:
        # 增加左标记(左标记右移),直到左标记指向的值大于枢轴值
        while leftmark <= rightmark and alist[leftmark] <= pivotvalue:
            leftmark = leftmark + 1

        # 递减右标(右标记左移),直到右标记指的值小于枢轴值
        while alist[rightmark] >= pivotvalue and rightmark >= leftmark:
            rightmark = rightmark - 1

        # 右标变得小于左标记的点时,停止循环
        if rightmark < leftmark:
            done = True
        else:
            # 交换左标记与右标记指向的值
            temp = alist[leftmark]
            alist[leftmark] = alist[rightmark]
            alist[rightmark] = temp
    
    # 交换枢轴值和分割点(右标记)的值
    temp = alist[first]
    alist[first] = alist[rightmark]
    alist[rightmark] = temp

    return rightmark


进阶

通过使用称为中值三的技术来减轻一些不均匀分割的可能性。要选择枢轴值,我们将考虑列表中的第一个,中间和最后一个元素。想法是,在列表中的第一项不属于列表的中间的情况下,中值三将选择更好的“中间”值。当原始列表部分有序时,这将特别有用。

posted @ 2018-08-17 09:07  banshaohuan  阅读(272)  评论(0)    收藏  举报