常见的排序算法总结

 

1、冒泡排序

从第一个元素开始,两两比较相邻元素,如果第一个元素比第二个元素大,则交换相邻元素,这样每经过一轮排序,就会有一个元素在最终位置上。

优化:设置一个flag,当在一次遍历中没有元素交换位置,说明列表已经有序。

时间复杂度:最坏:O(n^2), 平均:O(n^2), 最好:O(n)

空间复杂度:O(1)

稳定的排序算法

def bubble_sort(l):
    for i in range(len(l)-1):    # len(l)-1轮排序,把len(l)-1个元素排在相应位置,最后一个元素也在相应的位置
        flag = 1
        for j in range(len(l)-i-1):    
            if l[j+1]

 

2、选择排序

每轮循环从未排序元素中选择一个最大的,排在列表的最后位置

因为每轮只选择一个元素,所以选择排序没有优化算法,一定会循环n轮,不适合大规模数据

时间复杂度(最差/平均/最优):O(n^2)  O(n^2)  O(n^2)

空间复杂度 O(1)

不稳定的排序算法

def select_sort(l):
    for i in range(len(l)-1):
        max_index = 0
        for j in range(len(l)-i):
            if l[j] > l[max_index]:
                max_index = j
        l[j], l[max_index] = l[max_index], l[j]
    return l

 

3、插入排序

将列表分为两部分,左边是排序的,右边未排序。对于未排序部分的每个元素,在已排序列表中从后向前扫描,找到相应位置并插入。

时间复杂度(最差/平均/最优):O(n^2)  O(n^2)  O(n)

空间复杂度:O(1)

稳定的排序算法

def insertion_sort(l):
    for i in range(1,len(l)):
        temp = l[i]
        for j in range(i-1, -1, -1):
            if l[j] > l[i]:
                l[j+1] = l[j]
            else:
                l[j+1] = temp
                break
    return l

 

4、快速排序

选取第一个元素为划分元素,列表中小于划分元素的数字都被移到左面,大于划分元素的数字都被移到右面,每一轮会将一个元素放到最终位置上。递归对列表左半部分和右半部分快速排序。

时间复杂度(最差/平均/最优):O(n^2)  O(nlogn)  O(nlogn)

空间复杂度:O(logn)

不稳定的排序算法

def sub_sort(array, low, high):
    key = array[low]
    key_index = low
    low += 1
    while low < high:
        while low < high and array[high] >= key:
            high -= 1
        while low array[high]:
            array[low], array[high] = array[high], array[low]
    if array[key_index] > array[low]:
        array[key_index], array[low] = array[low], array[key_index]
    return low

def quick_sort1(array,low,high):
    if low < high:
        key_index = sub_sort(array,low,high)
        quick_sort1(array,low,key_index-1)
        quick_sort1(array,key_index+1,high)

if __name__ == '__main__':
    array = [8,8,10,9,6,4,16,5,13,26,18,2,45,34,23,1,7,3]
    quick_sort1(array,0,len(array)-1)
    print array

 

5、归并排序

def merge(left,right):
    temp_ans=[]
    i,j = 0, 0
    while i=len(left):
        temp_ans.extend(right[j:])
    if j>=len(right):
        temp_ans.extend(left[i:])

    return temp_ans


def merge_sort(l):
    if(len(l)<=1):
        return l
    else:
        low=0
        high=len(l)
        mid=(low+high)/2
        left=merge_sort(l[low:mid])
        right=merge_sort(l[mid:high])
        return merge(left,right)

l=[69,3,2,45,67,3,2,4,45,63,24,233]
print merge_sort(l)

 

6、堆排序

第i个元素的孩子是 2*i+1 和 2*i+2,第i个元素的父节点是 (i-1)/2

建堆:构建一个最大堆(父节点的值大于等于左右子节点),从第一个非叶节点开始向下调整,如果该节点小于子节点,交换该节点和子节点的位置,并从该子节点开始递归地向下调整

删除:删除根节点,将最后一个元素插入到根节点,并从根节点开始,递归地向下调整

插入:插入到最后一个位置,从最后一个元素开始,递归地向上调整

时间复杂度:建堆的时间复杂度是 O(n),每次调整堆的时间复杂度是 O(logn) ,需要调整n次,总的时间复杂度为 O(nlogn)

空间复杂度:用列表模拟建堆过程,可以实现原地排序,空间复杂度为O(1)

# 从上到下调整堆, length是需要调整的列表的最后一个元素位置,top是调整的起始位置
def top_down(l, length, top):
    while True:
        child = 2*top+1
        if child > length:
            break
        if child+1 <= length and l[child] < l[child+1]:
            child += 1
        if l[child] > l[top]:
            l[child], l[top] = l[top], l[child]
            top = child
        else:
            break

def heap_sort(l):
    length = len(l)-1
    # 构建最大堆,从第一个非叶子节点开始调整
    for top in range((length-1)/2, -1, -1):
        top_down(l, length, top)
        # print l

    # 将排序好的元素放到列表最后一个位置上并调整堆
    for i in range(length, 0, -1):
        l[0], l[i] = l[i], l[0]
        top_down(l, i-1, 0)
        #print i-1, l

l = [ 1, 2, 3, 3, 5, 12, 11, 13, 5, 6, 7]
heap_sort(l)
print l

 

你可能感兴趣的:(常见的排序算法总结)