zoukankan      html  css  js  c++  java
  • 数据结构之旅——搜索、排序和复杂度分析(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)

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

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

  • 相关阅读:
    NYOJ 23 取石子(一)
    XYNUOJ 2026 素数环
    XYNUOJ 1756 魔法工会
    XYNUOJ 1784 胜利大逃亡
    NYOJ 18 The Triangle
    NYOJ 737 合并石子
    XYNUOJ 问题 B: 敌兵布阵
    NYOJ 1063 生活的烦恼
    XYNUOJ 1774 最少拦截系统
    XYNUOJ 1248 排队打水问题
  • 原文地址:https://www.cnblogs.com/Misakikure/p/9764908.html
Copyright © 2011-2022 走看看