数据结构(二)排序

一、性质

  • 稳定性:稳定的算法能够维持序列中所有排序码相同记录的相对位置。
  • 适应性:对接近有序的序列工作更快。

二、插入排序

  • 不断的把元素插入到已经排好序的序列中。
def insert_sort(array):
    for i in range(1, len(array)):
        x = array[i]
        j = i
        while j > 0 and array[j-1] > x:
            array[j] = array[j-1]
            j -= 1
        array[j] = x
  • 空间复杂度O(1)
  • 平均时间复杂度O(n2)
  • 最好情况:已经有序O(n)
  • 最坏情况:逆排序O(n2)
  • 适应性:有
  • 稳定性:稳定。因为遇到和x一样大的,就不再移动,能保持顺序
    稳定性是针对实现的,如果把上述改为array[j-1] >= x,则不稳定。

三、选择排序

  • 每次选择最小的元素,放在已经排好序的序列后面。
def select_sort(array):
    for i in range(len(array)-1):
        k = i
        for j in range(i, len(array)):
            if array[j] < array[k]:
                k = j
        if i != k:
            array[i], array[k] = array[k], array[I]

  • 空间复杂度O(1)
  • 平均时间复杂度O(n2)
  • 最好情况:已经有序O(n2)
  • 最坏情况:逆排序O(n2)
  • 适应性:无
  • 稳定性:无

四、堆排序

  • 首先构建小顶堆
  • 每次弹出的就是最小值,希望能不利用其他空间,每次弹出就后面就会空出来一个位置,正好存放弹出的元素,不过这样的到的结果是从大到小,可以反转,或者直接构建大顶堆。
def heap_sort(elems):
    def siftdown(elems, e, begin, end):
        i ,j = begin, begin * 2 + 1
        while j < end:
            if j + 1 < end and elems[j+1] < elems[j]:
                j += 1
            if e < elems[j]:
                break
            elems[i] = elems[j]
            i, j = j, 2 * j + 1
        elems[i] = e
    end = len(elems)
    # buid heap O(n)
    for i in range(end//2, -1, -1):
        siftdown(elems, elems[i], i, end)
    # O(nlogn)
    for i in range((end - 1), 0, -1):
        e = elems[i]
        elems[i] = elems[0]
        siftdown(elems, e, 0, i)
  • 空间复杂度O(1)
  • 平均时间复杂度O(nlogn)
  • 最好情况:已经有序O(nlogn)
  • 最坏情况:逆排序O(n2)
  • 适应性:无
  • 稳定性:无

五、冒泡排序

反复比较相邻元素,发现相邻的逆序对就交换。

def bubbleSort(array):
    for i in range(len(array)):
        found = False
        for j in range(len(array) - i - 1):
            if array[j] > array[j+1]:
                found = True
                array[j], array[j+1] = array[j+1], array[j]
        if not found:
            break
  • 空间复杂度O(1)
  • 平均时间复杂度O(n2)
  • 最好情况:已经有序O(n)
  • 最坏情况:逆排序O(n2)
  • 适应性:有
  • 稳定性:有

六、快排

按照某种标准把序列划分为大的和小的,并递归执行。

递归实现

def quickSort(array, l, r):
    if l < r:
        mid = partition(array, l, r)
        quickSort(array, l, mid-1)
        quickSort(array, mid+1, r)
def partition(array, l, r):
    i = l - 1
    x = array[r]
    for j in range(l, r):
        if array[j] >= x:
            i += 1
            array[i], array[j] = array[j], array[i]
    array[i+1], array[r] = array[r], array[i+1]
    return i+1

非递归实现

def quickSort(Array):
    l, r = 0, len(Array)-1
    stack = [(l, r)]
    while stack:
        left, right = stack.pop(0)
        x = Array[right]
        i = left - 1
        for j in range(left, right):
            if Array[j] <= x:
                i += 1
                Array[j], Array[i] = Array[i], Array[j]
        Array[i+1], Array[right] = Array[right], Array[i+1]
        mid = i + 1
        if left < mid - 1:
            stack.append((left, mid - 1))
        if mid + 1 < right:
            stack.append((mid + 1, right))
  • 空间复杂度最坏O(n)
  • 平均时间复杂度O(nlogn)
  • 最坏情况:逆排序O(n2)
  • 适应性:无
  • 稳定性:无

七、归并排序

def mergeSort(array):
    if len(array) < 2:
        return array
    mid = len(array) >> 1
    left = mergeSort(array[:mid])
    right = mergeSort(array[mid:])
    return merge(left, right)
def merge(a1, a2):
    m, n = len(a1), len(a2)
    i = j = 0
    a = []
    while i < m and j < n:
        if a1[i] <= a2[j]:
            a.append(a1[i])
            i += 1
        else:
            a.append(a2[j])
            j += 1
    while i < m:
            a.append(a1[i])
            i += 1
    while j < n:
            a.append(a2[j])
            j += 1
    return a
  • 空间复杂度O(n)
  • 平均时间复杂度O(nlogn)
  • 适应性:无
  • 稳定性:有

你可能感兴趣的:(数据结构(二)排序)