python--几种排序算法(冒泡、插入、希尔、选择、快速排序)

全部为自己学习手打整理,引用请标明出处

一、冒泡排序:
第一次从第一个数开始依次向后比较,如果比后边小则交换位置,每次保证最大的在最后方(倒数第一)。第二次次大的在倒数第二个位置。依次比较下去直到不用再比较。

def bubble_sort(alist):
    n = len(alist)
    for j in range(n-1):#每次都是第一个数走,走n-1次
        count = 0
        for i in range(n-1-j):#班长从头走到尾(尾变化),j=0时对比n-1次(n个数)
            if alist[i] > alist[i+1]:
                alist[i], alist[i+1] = alist[i+1], alist[i]
            count += 1
        # 优化:如果遍历一次之后发现没有任何可以交换的元素,则直接结束
        #时间复杂度由O(n*n)变为O(n)
        if count == 0:
            return

if __name__ =="__main__":
    lst = [54, 26, 93, 17]
    print(lst)
    bubble_sort(lst)
    print(lst)

二、插入排序:把第一个数值默认看成有序(左侧看成有序),后面的序列看成无序,每次从无序序列中拿出第一个数依次向前比较(前面的序列循环),直到放到正确的位置上。(如果比前一个数小,则和前一个数交换位置)
如一个序列: 54 26 93 17 77
第一次: 54 26 93 17 77
26 54 93 17 77
第二次: 26 54 93 17 77
第三次: 26 54 17 93 77
26 17 54 93 77
17 26 54 93 77
第四次: 17 26 54 77 93

def insert_sort(alist):
    n = len(alist)
    for j in range(1, n):# 从右边的无序序列中取出1~n-1个元素进行这样的过程
        # j:1,2,3,4,....,n-1
        i = j # i是内层循环起始值,第一个数比较一次,第二个数比较两次......i=j
        while i > 0:# 判断这个条件只要看第一个数只要比较一次即可
            if alist[i] < alist[i-1]:# 起始alist[1]和alist[0]进行比较
                alist[i], alist[i-1] = alist[i-1], alist[i]
                i -= 1
            # 不需要再进行比较时,前面本身有序,说明此时比前面都大了
            # 退出当前循环,从右边再取比较下一个值
            else:
                break
if __name__ =="__main__":
    lst=[54,26,94,17,77]
    print(lst)
    insert_sort(lst)
    print(lst)

三、希尔排序:
将列表按照间隔看成几个子组,每个子组都进行插入排序,每按一个间隔排序后的算依次。再将间隔减半或其他处理,直至间隔为1结束。
如一个序列:54 26 44 17 77 31 93 55 20
第一次gap=4
python--几种排序算法(冒泡、插入、希尔、选择、快速排序)_第1张图片
再依次gap=2,gap=1 结束

def shell_sort(alist):
    n=len(alist)
    gap = n // 2
    while gap > 0: #或gap>=1,插入算法执行的次数
        for j in range(gap, n):#j=[gap,gap+1,gap+2,...n-1],for和下面的while执行一次gap
            i = j
            while i > 0:
                if alist[i] < alist[i-gap]:
                    alist[i], alist[i-gap] = alist[i-gap], alist[i]
                    i -= gap#这里相当于插入排序每次交换后再往前跟前一个比,只不过前一个的间隔变成了gap
                else:
                    break
        gap = gap // 2#缩短gap步长
if __name__=='__main__':
    lst = [54,26,94,17,77]
    print(lst)
    shell_sort(lst)
    print(lst)

四、选择排序:
整个序列的最左侧看成有序(一开始是第一个元素看成有序),每次把除排好位置的元素外的后面的序列看成无序。从无序序列中一个一个判断找出最小值(后面的序列循环)放到对应的位置并交换相应位置的元素。

如一个序列: 54 226 93 17 77 31 44 55 20
0 1 2 3 4 5 6 7 8
第一次:右侧min=3
alist[0], alist[3] = alist[3], alist[0]
17 226 93 54 77 31 44 55 20
0 1 2 3 4 5 6 7 8
第二次:右侧min=8
alist[1], alist[8] = alist[8], alist[1]
17 20 93 54 77 31 44 55 226
0 1 2 3 4 5 6 7 8
第三次:右侧min=5
alist[2], alist[5] = alist[5], alist[2]
17 20 31 54 77 93 44 55 226
0 1 2 3 4 5 6 7 8
第四次:右侧min=6
alist[3], alist[6] = alist[6], alist[3]
17 20 31 44 77 93 54 55 226
依次往下…

def select_sort(alist):
    n=len(alist)
    for j in range(n-1):#j =0,1,....n-2(共n-1次)
        min_index = j#左侧比较每一次都往后移动一个
        for i in range(j+1, n):#循环选择出最小下标
            if alist[min_index] > alist[i]:#每次记录小的下标
                min_index = i
        alist[min_index],alist[j]= alist[j], alist[min_index]#选出最小下标后和头的交换

if __name__=='__main__':
    lst = [54,26,94,17,77]
    print(lst)
    select_sort(lst)
    print(lst)

五、快速排序:
把alist[0]看成mid_val存储起来,有两个指针low和high, 最开始low=0,high=n-1。从high先开始判断,如果大于等于mid_value(这里等于保证相等的数始终在mid_val的一侧),向左移动一位;如果小于mid_value,将high处的值放到low指向的位置。
low小于mid_val(小于就放那),将low向右移动一位;low大于mid_val(等于时也换,保证等于的值都在右侧一侧),将low处的值放到high指向的位置。直至low和high相遇,此处即为mid_value的位置。接着mid_value将整个序列分成两部分,这两部分仍然把各自部分的第一个值看成mid_value,分别再进行上述的操作,直至每个部分只剩下一个值,即 first >= last 时退出。
python--几种排序算法(冒泡、插入、希尔、选择、快速排序)_第2张图片

def quick_sort(alist, first, last):

    if first >= last:#递归终止条件,否则一直递归
        return

    mid_value = alist[first]
    low = first #每一次的low都是0
    high = last#first last保证左右边界动态传递

    while low < high: #二者不相遇就一直循环,下面两个while交替执行,跳出循环即找到mid_value位置
        while low < high and alist[high] >= mid_value:#high大于mid_value时移动,一直大于一直移
            high -= 1
        alist[low] = alist[high] #high小于mid_value时赋给low
        #这时low处的值一定小于mid_value,low直接靠下面的while移动,如果这里移动会造成二者相遇再错开的情况

        while low < high and alist[low] < mid_value:
            low += 1
        alist[high] = alist[low]
        #这时low处的值一定大于mid_value,low直接靠上面的if移动
    #跳出循环high=low指向的都是mid_value
    alist[low] = mid_value
    quick_sort(alist, first, low - 1)
    #mid_value左侧的结尾是low - 1,每递归一次左侧的左右都会运行(递归进函数时有下一句),此句只管左侧
    quick_sort(alist, low+1, last)
    #mid_value右侧的开始是low + 1,每递归一次右侧的左右都会运行(递归进函数时有上一句),此句只管右侧

if __name__=='__main__':
    lst = [54,26,94,17,77]
    print(lst)
    quick_sort(lst, 0, len(lst)-1)
    print(lst)

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