python排序算法-冒泡排序,选择排序,直接插入排序,希尔排序,归并排序,快速排序,堆排序

学习量化也有一段时间了,借csdn博客记录下学习过程的点点滴滴。

准备总结的内容:

(1)CFA二级知识点;(2)期权期货相关(魏振祥《商品期权》总结);(3)统计学(可汗学院统计学课程总结);(4)数据结构与leetcode的一些实践(python实现);(5)一些简单设计模式的python实现;(6)基于tushare的一些策略实现(均线策略与择股策略等);(7)时间序列分析;

接下来几篇为python3实现的排序算法。

(一)冒泡算法。

首先最初级的冒泡算法,每次iteration会将i位置的数据调整至最小值,但是其他位置数据并没有变得更加有序,故效率较低。

def bubble_sort(src):
    if len(src) == 0:
        return src
    for i in range(len(src)):
        for j in range(i+1, len(src)):
            if src[j] < src[i]:
                tem = src[j]
                src[j] = src[i]
                src[i] = tem
    return src

src = [10, 12, 8, 9, 20, 18, 40, 15]
print(bubble_sort(src))
接下来改进版的冒泡算法,每次交换会把数据变得更加有序。

这么写的话,每次循环是将最大的值放到最后,不是严格意义的冒泡,如果是每次循环将最小的元素排到最前,第二层循环应该从后往前,for j in range(len(src)-1, i, -1),循环内判断条件为if src[j] < src[j-1],将两个元素互换。

def bubble_sort(src):
    if len(src) == 0:
        return src
    for i in range(len(src)):
        for j in range(0, len(src)-i-1):
            if src[j] > src[j+1]:
                tem = src[j]
                src[j] = src[j+1]
                src[j+1] = tem
    return src

src = [10, 12, 8, 9, 20, 18, 40, 15]
print(bubble_sort(src))
如果有一次循环已经没有交换元素,那说明已经排序完成,没必要继续循环了,加入flag判断代码如下。
def bubble_sort(src):
    if len(src) == 0:
        return src
    flag = True
    for i in range(len(src)):
        if not flag:
            break
        flag = False
        for j in range(len(src)-1, i, -1):
            if src[j-1] > src[j]:
                tem = src[j]
                src[j] = src[j-1]
                src[j-1] = tem
                flag = True
    return src
冒泡算法最好情况是比较n-1次,时间复杂度是O(n),最坏情况是1+2+...+n-1=n(n-1)/2,时间复杂度O(n^2)。

(二)选择排序算法。

i每次循环将i+1及之后里面最小的与i进行交换,i最后循环到len(src)-2就行。

def selected_sort(src):
    if len(src) == 0:
        return src
    for i in range(len(src)-1):
        min = i
        for j in range(i+1, len(src)):
            if src[j] < src[min]:
                min = j
        if i != min:
            tem = src[min]
            src[min] = src[i]
            src[i] = tem
    return src

src = [10, 12, 8, 9, 20, 18, 40, 15]
print(selected_sort(src))

时间复杂度也为O(n^2)。

(三)直接插入排序。

每次i循环将i位置元素插入到0至i-1序列中。

def insert_sort(src):
    if len(src) == 0:
        return src
    for i in range(1, len(src)):
        j = i-1
        tem = src[i]
        while j >= 0:
            if tem < src[j]:
                src[j+1] = src[j]
            else:
                src[j+1] = tem
                break
            j -= 1
        if j < 0:#如果j循环结束而不是break结束的情况,说明原来的src[0]都比tem小
            src[0] = tem
    return src

src = [10, 12, 8, 9, 20, 18, 40, 15]
print(insert_sort(src))

时间复杂度也为O(n^2)。

这篇文章先写这么多,接下来继续。

(四)希尔排序,设置一个incremental对原序列提取出子序列,对子序列直接插入排序,然后逐渐减小步长,直至步长为1。

def shell_sort(src):
    if len(src) == 0:
        return src
    incremental = len(src)
    while incremental >= 1:
        for i in range(0, len(src)):#i为每组的第一个元素
            for j in range(i, len(src), incremental):#j为每组间隔incremental的元素
                if j == i:#第一个元素不用排序
                    continue
                #插入排序
                tem = src[j]
                k = j - incremental
                while k >= i:
                    if src[k] > tem:
                        src[k+incremental] = src[k]
                        k -= incremental
                    else:
                        src[k+incremental] = tem
                        break
                if k < i:
                    src[i] = tem
        incremental = int(incremental/2)
    return src

src = [10, 12, 8, 9, 20, 18, 40, 15]
print(shell_sort(src))

(五)归并排序,递归至同类小问题,再归并排序。

def merge(left, right):
    res = []
    i, j = 0, 0
    while i < len(left) and j < len(right):
        if left[i] < right[j]:
            res.append(left[i])
            i += 1
        else:
            res.append(right[j])
            j += 1
    while i < len(left):
        res.append(left[i])
        i += 1
    while j < len(right):
        res.append(right[j])
        j += 1
    return res

def merge_sort(src):
    if len(src) <= 1:
        return src
    middle = int(len(src)/2)
    left = merge_sort(src[:middle])
    right = merge_sort(src[middle:])
    return merge(left, right)

src = [10, 12, 8, 9, 20, 18, 40, 15]
print(merge_sort(src))

归并排序时间复杂度O(nlogn),为稳定的排序算法。

(六)快速排序,设置partition,每次将元素依照key分割开,再递归排序两边的元素。

def quick_sort(src, left, right):
    if left >= right:
        return src

    low = left
    high = right
    key = src[left]
    while low < high:
        while low < high and src[high] >= key:
            high -= 1
        src[low] = src[high]
        while low < high and src[low] <= key:
            low += 1
        src[high] = src[low]
    src[low] = key

    quick_sort(src, left, low-1)
    quick_sort(src, low+1, right)
    return src
         
src = [10, 12, 8, 9, 20, 18, 40, 15]
print(quick_sort(src, 0, len(src)-1))

时间复杂度为O(nlogn),非稳定的排序算法。

(七)堆排序,时间复杂度O(nlogn)

def heap_sort(src):
    length = len(src)
    if len(src) <= 1:
        return src
    def adjust_heap(src, i, end):
        tem = src[i]
        k = 2*i+1#左孩子index
        while k <= end:
            if k+1 <= end and src[k] < src[k+1]:
                k += 1
            if tem < src[k]:
                src[i] = src[k]
                i = k
                k = 2*k + 1
            else:
                break
        src[i] = tem

    for i in range(int((length-1)/2), -1, -1):
        adjust_heap(src, i, length-1)
    for j in range(length-1, 0, -1):
        src[0], src[j] = src[j], src[0]
        adjust_heap(src, 0, j-1)
    return src

print(heap_sort([5,4,3,2,1]))


你可能感兴趣的:(python排序算法-冒泡排序,选择排序,直接插入排序,希尔排序,归并排序,快速排序,堆排序)