数据结构之旅——搜索、排序和复杂度分析(Python实现)(四)

上一节讲了三个时间复杂度均为O(n)的排序算法,这一节我们讲几个时间复杂度降低了很多的更为快捷的排序算法。

一、堆排序

算法策略:先建立一个最大堆,在建立最大堆的过程中需要不断调整元素的位置。最大堆建立后,顶端元素必定是最大的元素,把该最大元素与最末尾元素位置置换,最大元素就出现在列表末端。重复此过程,直到排序。

代码实现:

import copy

def heapSort(lyst):
    def heap_adjust(parent):
        child = 2 * parent + 1  # left child
        while child < len(heap):
            if child + 1 < len(heap):
                if heap[child + 1] > heap[child]:
                    child += 1  # right child
            if heap[parent] >= heap[child]:
                break
            heap[parent], heap[child] = heap[child], heap[parent]
            parent, child = child, 2 * child + 1

    heap, lyst = copy.copy(lyst), []
    for i in range(len(heap) // 2, -1, -1):
        heap_adjust(i)
    while len(heap) != 0:
        heap[0], heap[-1] = heap[-1], heap[0]
        lyst.insert(0, heap.pop())
        heap_adjust(0)
    return lyst

时间复杂度:O(nlog₂n)

缺点:比下面两种快速的排序方法慢,但比上一节的几种排序方法快。

二、归并排序

算法策略:归并排序是一种典型的分治思想,把一个无序列表一分为二,对每个子序列再一分为二,继续下去,直到无法再进行划分为止。然后,就开始合并的过程,对每个子序列和另外一个子序列的元素进行比较,依次把小元素放入结果序列中进行合并,最终完成归并排序。

代码实现:

def merge(lyst, low, mid, high):
    tmp = []
    i = low
    j = mid +1
    while i <= mid and j <= high:
        if lyst[i] <= lyst[j]:
            tmp.append(lyst[i])
            i += 1
        else:
            tmp.append(lyst[j])
            j += 1
    while i <= mid:
        tmp.append(lyst[i])
        i += 1
    while j <= high:
        tmp.append(lyst[j])
        j += 1
    lyst[low:high+1] = tmp

def mergeSort(lyst, low, high):
    if low < high:
        mid = (low + high) // 2
        mergeSort(lyst, low, mid)
        mergeSort(lyst, mid+1, high)
        merge(lyst, low, mid, high)

时间复杂度:O(nlogn)

缺点:需要额外的内存开销 

三、快速排序

算法策略:首先在列表中取一项,这一项又叫做基准点,然后将列表中的项分区,比基准点小的都放在基准点左边,比基准点大的都放基准点右边,对于由于基准点分割而成的两个子列表重复之前的步骤,每次遇到少于 2个项的一个子列表,就结束分割过程。

代码实现:

def quickSort(lyst):
    if lyst == []:
        return []
    else:
        point = lyst[0]
        p_min = quickSort([l for l in lyst[1:] if l < point])
        p_max = quickSort([m for m in lyst[1:] if m >= point])
        return p_min + [point] + p_max

时间复杂度:O(nlogn)  最坏时间复杂度为 O(n2)

缺点:极端情况下排序效率低

这三个排序方法在一般情况下的速度快慢为:快排>归并排>堆排

原文地址:https://www.cnblogs.com/Misakikure/p/9764908.html