python实现快速排序和归并排序

快排基本思想:

按照某种标准将序列划分为“小记录”和“大记录”,并通过递归不断划分。

思想如图所示:

python实现快速排序和归并排序_第1张图片

其中,R为枢轴元素

代码实现如下:

def quick_sort(lst):
    qsort_rec(lst, 0, len(lst)-1)

def qsort_rec(lst, l, r):
    if l > r:
        return                  #分段无记录或只有一个记录
    i = l
    j = r
    pivot = lst[i]              #lst[i]是初始空位
    while i < j:
        while i < j and lst[j] >= pivot:    #大记录,寻找比pivot大的元素
            j -= 1                          #向左扫描比pivot大的元素
        if i < j:                #lst[j] < pivot
            lst[i] = lst[j]
            i += 1               #小于pivot的元素移到左边
        while i < j and lst[i] <= pivot:
            i += 1
        if i < j:                #lst[i] > pivot
            lst[j] = lst[i]
            j -= 1               #大记录移到右边
        lst[i] = pivot           #将pivot存入其最终位置
        qsort_rec(lst, l, i-1)   #递归处理左半区间
        qsort_rec(lst, i+1, r)   #递归处理右半区间


归并排序

基本思想:

将两个或更多有序序列合并为一个有序序列。

代码如下:

def merge(lfrom, lto, low, mid, high):
    i, j, k = low, mid, low
    while i < mid and j < high:      #记录两段段首记录中较小的
        if lfrom[i] <= lfrom[j]:
            lto[k] = lfrom[i]
            i += 1
        else:
            lto[k] = lfrom[j]
            j += 1
        k += 1
    while i < mid:                    #复制第一段记录
        lto[k] = lfrom[i]
        i += 1
        k += 1
    while j < high:                   #复制第二段记录
        lto[k] = lfrom[j]
        j += 1
        k += 1

def merge_pass(lfrom, lto, llen, slen):
    i = 0
    while i + 2*slen < llen:                 #归并长slen的两段
        merge(lfrom, lto, i, i + slen, i + 2 * slen)
        i += 2 * slen
    if i + slen < llen:                      #剩下两段,后段长度小于slen
        merge(lfrom, lto, i, i + slen, llen)
    else:                                    #只剩下一段,复制到表lto
        for j in range(i,llen):
            lto[j] = lfrom[j]

def merge_sort(lst):
    slen, llen = 1, len(lst)
    templst = [None] * llen
    while slen < llen:
        merge_pass(lst, templst, llen, slen)
        slen *= 2
        merge_pass(templst, lst, llen, slen)   #结果存回原位
        slen *= 2
    print lst, templst

需要注意的是,此算法实现归并另外开辟了一片同样大小的存储区,也就是建立了另一个同样大小的表,把一遍归并的结果放在那里,在一遍归并做完后,在保存归并结果的新表里存储加倍长度的有序序列,而且原来的表已经闲置了。在这种情况下,可以考虑调换两个表的角色,在原表张积累下一遍归并的结果。

你可能感兴趣的:(数据结构/算法)