各种排序算法及Python源代码

排序算法

排序算法稳定性
  • 在满足排序规则的前提下,保持原有顺序即具备稳定性,不保持原有顺序即不具稳定性
冒泡排序
源代码

具备稳定性,最坏时间复杂度=O(n^2)

def bubble_list(list):

    for i in range(len(list)):
        for k in range(len(list)-1-i):
            if list[k] > list[k+1]:
                list[k],list[k+1] = list[k+1],list[k]
        print(list,end="\n\n")  #看下每个泡泡的上升情况
    return list

print(bubble_list([232,1,54,3463,22,121232,-8,99]))
选择排序
源代码

不具备稳定性(不具备吗?应该具备吧?)

def select (list):
    select_list =[]
    for j in range(len(list)):
        min = list[j]    #如果min用作下标,不用重新构建一个select_list素组,这样可以少一次迭代
        for i in range(j+1,len(list)):
            if list[i] < min:
                min,list[i] = list[i],min

        select_list.append(min)
        print(select_list)  #还是看看过程
    return select_list


select([-101,232,1,22,54,3463,22,121232,-8,99])
插入排序
源代码

源代码包含在下面希尔排序中

具备稳定性,最坏时间复杂度=O(n^2)

希尔排序

不具备稳定性,最坏时间复杂度=O(n^2)。它的好处就是平均时间复杂度较小(它的最好情况甚至也不如插入排序)
在这里插入图片描述

源代码
def insert(list):
    for i in range(len(list)-1):
        for j in range(i,-1,-1):
            if list[j+1] < list[j]:
                list[j+1],list[j] = list[j],list[j+1]
            else:
                break
        print(list)  #仍然看过程
    return list

def shell(list):   #在插入排序基础上建立希尔排序
    gap = len(list)
    while gap//2 != 1 :
        gap = gap//2
        gap_list = [list[k] for k in range(0,len(list),gap) ]  #构建基于每个gap的小列表
        insert(gap_list)
    return list

print(insert([-101, 232, 1, 22, 54, 3463, 22, 121232, -8, 99,-1234]))

print(shell([-101, 232, 1, 22, 54, 3463, 22, 121232, -8, 99,344543,-2123,12]))
快速排序

基本思路:使用两个游标(low和high),从列表的两端进行逼近(或者叫遍历)。从列表第一个元素开始查找正确位置,游标low(high)遇到比当前要确认位置的元素小(大)的元素,则继续遍历,否则停止,并交换low和high两个游标所指元素。这个过程一直进行,进行到low和high指向的元素一样的时候,则这个位置就是当前要确认位置的元素的正确位置,原有列表也被这个元素分割成两个列表,后面再按这个思路一直进行下去

思路改进:先用high(或者low)进行遍历,遇到小于待确认位置元素的元素的时候,把这个元素赋值给low,然后low游标开始遍历,直到找到比待确认位置元素大的元素,把这个值赋值给high,循此往复

不具备稳定性,最好时间复杂度O(n*log n) (log以2为底),最坏时间复杂度O(n^2)

难点:理解函数嵌套的递归思路;注意列表中下标+1,-1的情况

源代码
def fast(list, first, last):  #为了后面递归能继续操作list中的元素,引入first和last

    if first-1 == last:  #这个判断只能写在前面,因为后面的嵌套内部要用, 思考:这里为什么first要-1?当分割到列表仅剩一个元素的时候,low= first , last = low-1,所以last比low还小1
        return list

    mid_value = list[first]  #mid_value就是待确认位置的元素, high与low游标都和它进行对比
    low = first
    high = last
    while high > low:

        while list[high] >= mid_value:
            high -= 1
            if high == low:   #防止中间有过多一样的元素,导致high一直减少,导致high与low游标错过
                break
        list[low] = list[high]   #刚开始的时候list[low]=mid_value=list[0],所以第一个list[low]的值不会丢

        while list[low] < mid_value:  #这里和上面while list[high] >= mid_value只有一个地方能加=,否则有可能在上面break后下面再操作一遍(这里比较抽象)
            low += 1
            if high == low:   #防止中间有过多一样的元素,导致low一直增多,导致high与low游标错过
                break
        list[high] = list[low]
    list[low] = mid_value
    print(list,end="\n\n") #仍然要看过程


    fast(list,first,low-1)
    # print("---------------------------------------")
    fast(list,low+1,last)

li = [-8,1,23,5,5,43,-9,100,4,6,7,2,4,-100]
li2 = [121,434,23,2,0,3,0,444,0]
fast(li, 0, len(li) - 1)
fast(li2,0,len(li2)-1)
print(li)
print(li2)

输出(注意看过程)

"C:\Users\Lenovo\Desktop\Python coding\venv\Scripts\python.exe" "C:/Users/Lenovo/Desktop/Python coding/05_fast.py"
[-100, -9, -8, 5, 5, 43, 23, 100, 4, 6, 7, 2, 4, 1]

[-100, -9, -8, 5, 5, 43, 23, 100, 4, 6, 7, 2, 4, 1]

[-100, -9, -8, 5, 5, 43, 23, 100, 4, 6, 7, 2, 4, 1]

[-100, -9, -8, 1, 4, 2, 4, 5, 100, 6, 7, 23, 43, 5]

[-100, -9, -8, 1, 4, 2, 4, 5, 100, 6, 7, 23, 43, 5]

[-100, -9, -8, 1, 2, 4, 4, 5, 100, 6, 7, 23, 43, 5]

[-100, -9, -8, 1, 2, 4, 4, 5, 100, 6, 7, 23, 43, 5]

[-100, -9, -8, 1, 2, 4, 4, 5, 100, 6, 7, 23, 43, 5]

[-100, -9, -8, 1, 2, 4, 4, 5, 5, 6, 7, 23, 43, 100]

[-100, -9, -8, 1, 2, 4, 4, 5, 5, 6, 7, 23, 43, 100]

[-100, -9, -8, 1, 2, 4, 4, 5, 5, 6, 7, 23, 43, 100]

[-100, -9, -8, 1, 2, 4, 4, 5, 5, 6, 7, 23, 43, 100]

[-100, -9, -8, 1, 2, 4, 4, 5, 5, 6, 7, 23, 43, 100]

[-100, -9, -8, 1, 2, 4, 4, 5, 5, 6, 7, 23, 43, 100]

[0, 0, 23, 2, 0, 3, 121, 444, 434]

[0, 0, 23, 2, 0, 3, 121, 444, 434]

[0, 0, 23, 2, 0, 3, 121, 444, 434]

[0, 0, 3, 2, 0, 23, 121, 444, 434]

[0, 0, 0, 2, 3, 23, 121, 444, 434]

[0, 0, 0, 2, 3, 23, 121, 444, 434]

[0, 0, 0, 2, 3, 23, 121, 444, 434]

[0, 0, 0, 2, 3, 23, 121, 434, 444]

[0, 0, 0, 2, 3, 23, 121, 434, 444]

[-100, -9, -8, 1, 2, 4, 4, 5, 5, 6, 7, 23, 43, 100]
[0, 0, 0, 2, 3, 23, 121, 434, 444]

Process finished with exit code 0

归并排序

在这个排序中,嵌套的理解仍是难点

最有时间复杂度和最坏时间复杂度都是O(n*log n),具备稳定性

源代码
def merge(list):
    if len(list) == 1:
        return list

    mid = len(list) //2

    left_list = merge(list[:mid])  #难点:理解这个嵌套

    right_list = merge(list[mid:])
    left_point = 0
    right_point = 0
    result_list = []


    print(left_list)#这里仍然用于看过程
    print(right_list)
    print(result_list,end="\n\n")

    while left_point < mid and right_point < mid:
        if left_list[left_point] <= right_list[right_point]:
            result_list.append(left_list[left_point])
            left_point +=1
        else:
            result_list.append(right_list[right_point])
            right_point +=1

    result_list= result_list +left_list[left_point:]  #把剩余元素补上,注意,这里不能用append
    result_list= result_list +right_list[right_point:]

    return result_list


li = [12,53,1]
merge(li)
二分法查找

只能作用于排序后的顺序表
最坏时间复杂度O(log n)
难点仍在于对嵌套递归的理解

源代码
def binary_search(in_list, target): #in_list是有序列表
    n = len(in_list)
    if n == 0:
        return "Nogo"

    # print(n,end="****")

    else:
        n = n // 2
        print(n)
        if target == in_list[n]:
            return "bingo"

        else:
            if target > in_list[n]:
                in_list = in_list[n+1:]
                print(in_list, end= "\n")
                return binary_search(in_list, target) #层层return最终结果
            else:
                in_list = in_list[:n]
                print(in_list,end= "\n")
                return binary_search(in_list, target)

print(binary_search([5,6,7,66,77,88,99,100,1000,10000],5))

猜你喜欢

转载自blog.csdn.net/m0_49963403/article/details/121309097