算法导论之排序算法 代码实现

许多程序使用排序作为一个中间步,所以排序是计算机科学中的一个基本操作。

 

 

插入排序

原址排序,在任何时候,最多只有其中的常数个数字存储在需要排序的数组外面。

思想:将当前要排序的值插入到正确的位置。

最佳运行时间O(n),最坏情况O(n2),平均O(n2)。

算法描述:

def sort1(A):
    for j in range(1, len(A)):
        key = A[j]
        i = j - 1
        while i >= 0 and A[i] > key:
            A[i + 1] = A[i]
            i = i - 1
        A[i + 1] = key
    return

 

冒泡排序

 

流行但是低效,反复交换相邻的未按次序排序的元素。

运行时间同插排。

算法描述:

def sort2(A):
    for i in range(len(A) - 2):
        for j in range(len(A) - 1, i, -1):
            if A[j] < A[j - 1]:
                temp = A[j]
                A[j] = A[j - 1]
                A[j - 1] = temp
    return

 

归并排序

 

分治模式:

1.       分解原问题为若干个子问题,这些子问题是原问题的规模较小的实例。

2.       解决这些子问题,递归的求解各个子问题。然而若子问题的规模足够小,则直接求解。

3.       合并这些子问题的解成原问题的解。

平均运行时间与最坏运行时间均为O(nlogn)

算法描述:

def merge(a, p, q, r):
    """
    将已经排好序的a[p...q]和a[q+1...r]有序的合并在一起
    :param a:
    :param p:
    :param q:
    :param r:
    :return:
    """
    n1 = q - p + 1
    n2 = r - q
    L = [0.] * (n1 + 1)
    R = [0.] * (n2 + 1)
    for i in range(n1):
        L[i] = a[p + i]
    L[n1] = float("inf")  # 设置一个守门员
    for i in range(n2):
        R[i] = a[q + 1 + i]
    R[n2] = float("inf")

    i = 0
    j = 0
    for k in range(p, r + 1):
        if L[i] < R[j]:
            a[k] = L[i]
            i = i + 1
        else:
            a[k] = R[j]
            j = j + 1
    return


def sort3(a, p=0, *end):
    if 0 == len(end):
        r = len(a) - 1
    else:
        r = end[0]
    if p < r:
        q = int((p + r) / 2)
        sort3(a, p, q)
        sort3(a, q + 1, r)
        merge(a, p, q, r)
    return

 

希尔排序

 

希尔排序使用一个序列h1,h2,…,叫做增量序列。在使用增量h的一趟排序之后,对于每一个i有A[i]<=A[i+h],相隔h的元素都被排序。当h=1时整个序列被排序。

最坏情形:使用希尔增量i=i/2:O(n2);使用hibbard增量1,3,7,…,2k-1:O(n2/3)。

算法描述:

def sort4(a):
    length = len(a)
    increment = int(len(a) / 2)
    j = 0
    while increment > 0:
        for i in range(increment, length):
            temp = a[i]
            for j in range(i, increment - 1, increment * -1):
                if temp < a[j - increment]:
                    a[j] = a[j - increment]
                else:  # 最后一次循环是从哪里跳出的
                    j = j + increment
                    break
            a[j - increment] = temp
        increment = int(increment / 2)
    return

 

堆排序

 

将要排列的数组构造为一个最大堆,依次删除最大值即堆定。

算法复杂度:O(nlogn)

算法描述:

def perc_down(a, i, n):
    temp = a[i]
    while (2 * i + 1) < n:
        child_max = 2 * i + 1
        if child_max < (n - 1) and a[child_max] < a[child_max + 1]:
            child_max = child_max + 1
        if temp < a[child_max]:
            a[i] = a[child_max]
            i = child_max
        else:
            break
    a[i] = temp
    return


def perc_down1(a, i):
    child_max = 2 * i + 1
    if child_max < len(a):
        if child_max < (len(a) - 1):
            if a[child_max] < a[child_max + 1]:
                child_max = child_max + 1
        if a[i] < a[child_max]:
            temp = a[i]
            a[i] = a[child_max]
            a[child_max] = temp
            perc_down1(a, child_max)
    return


def sort5(a):
    for i in range(int((len(a) - 2) / 2), -1, -1):
        perc_down(a, i, len(a))

    for i in range(len(a) - 1, -1, -1):
        temp = a[0]
        a[0] = a[i]
        a[i] = temp
        perc_down(a, 0, i)
    return

 

快排

 

属于分治的排序算法。

1.       如果S中的元素个数是0或者1,则返回;

2.       取S中任一元素v,称之为枢纽元;

3.       将S-{v}(S中的其他元素)分为两个不相交的集合:S1={x<=v},S2={x>=v};

4.       返回{S1,v,S2}

算法描述:

def swap(a, i, j):
    temp = a[i]
    a[i] = a[j]
    a[j] = temp
    return


def median3(a, left, right):
    center = int((left + right) / 2)
    if a[left] > a[center]:
        swap(a, left, center)
    if a[left] > a[right]:
        swap(a, left, right)
    if a[center] > a[right]:
        swap(a, center, right)
    swap(a, center, right - 1)
    return a[right - 1]


def sort6(a, left, right):
    if (right - left) >= 3:
        pivot = median3(a, left, right)
        i = left + 1
        j = right - 2
        while 1:
            while a[i] < pivot:
                i = i + 1
            while a[j] > pivot:
                j = j - 1
            if i < j:
                swap(a, i, j)
            else:
                if a[i] < pivot:
                    swap(a, right - 1, i + 1)
                    i = i + 1
                else:
                    swap(a, right - 1, i)
                break
        sort6(a, left, i - 1)
        sort6(a, i + 1, right)
    else:
        if 0 == right - left:
            return
        elif 1 == right - left:
            if a[left] > a[right]:
                swap(a, left, right)
            return
        else:
            if a[left] > a[left + 1]:
                swap(a, left, left + 1)
            if a[left] > a[right]:
                swap(a, left, right)
            if a[left + 1] > a[right]:
                swap(a, left + 1, right)
            return

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值