003-sorting

108 阅读2分钟

动机:

  1. find max/min item:

    对于一个set来讲,当查询一个最大/小值时,遍历所有item固然可以,不过要花费θ(n)\theta(n)的时间,效率较慢,可是当我们对set进行排序后,便能轻松找到最大/最小值了θ(1)\theta(1)

  2. 更快查找任意元素:

    若排序后,可利用二分查找θ(logn)\theta(log_n)的时间进行查找

时间复杂度:θ(nlogn)\theta(nlog_n)

  • binary sort:
    • 我们知道binary search 的时间复杂度是O(logn)O(log_n),对于set中的每个item,按照从小到大依次查找的复杂度O(n)O(n),所以总的复杂度是nlognnlog_n
  • merge sort:
    • 对于归并排序,每次将两个排序后的数组合并的复杂度nn,不断递归的复杂度是lognlog_n(每次递归,将数组一分为二)

分类:

  • Selection Sort
  • Insertion Sort
  • Merge Sort
  • ......

Selection Sort:

def selection_sort(A, i = None):
    if i is None: i = len(A)-1
    if i > 0:
        j = prefix_max(A, i)
        A[i], A[j] = A[j], A[i]
        selection_sort(A, i-1)
        
def prefix_max(A, i):
    if i > 0:
        j=prefix_max(A, i-1)
        if A[i] < A[j]:
            return j
    return i
  1. 找到当前最大的数,并将其交换到数组最末位
  2. 对前i1i-1位递归

对prefix_max函数解释:

对于数组的最后一位,只有两种情况

  • 是最大数
  • 不是最大数

因此递归出A[:i-1]中的最大数,令其与A[i]进行比较即可
if i >0当数组中只有只有一个元素时,无需比较,当前元素即最大数,直接return i

Merge Sort:

def merge(L, R, A, i, j, a, b,):
    """Merge sorted L[ : i] and R[ : j] into A[a, b]"""
    if a<b:
        if (j <= 0) or (i>0 and L[i-1] > R[j-1]):
            A[b-1] = L[i-1]
            i = i - 1
        else:
            A[b-1] = R[j-1]
            j = j - 1
        merge(L,R,A,i,j,a,b-1)
        
def merge_sort(A,a=0,b=None):
    if b is None: b=len(A)
    if b-a> 1 :
        c = (a+b+1)//2
        merge_sort(A, a, c)
        merge_sort(A, c, b)
        L, R=A[a:c], A[c:b]
        merge(L, R, A, len(A), len(B), a, b)

时间复杂度:

对于merge函数,即将两个子数组归并为一个数组过程中,我们必定要遍历所有元素,复杂度为θ(n)\theta(n),递归的复杂度为lognlog_n,所以总的时间复杂度为nlognnlog_n