python的基础10大排序算法--冒泡,快速,基数,桶。。

python的基础10大排序算法--冒泡,快速,基数,桶。。,第1张

#python的基础10大排序算法--冒泡,快速,基数,桶。。
import random
#冒泡排序
def bubble_f(b_li):
    b_len = len(b_li)   #获取列表的长度
    for i in range(b_len):  #从第一个元素,即0,开始,直到最后一个元素,n - 1,用i来记录循环,总计是n次
    #第一次循环,即i = 0,找到整列表中最大的一个,并且,放在列表的最后一个位置,即n-1的位置
    # 用j来控制比较循环,j从0开始,j与j+1进行比较,故而,j+1的最大值是n-1,那么,j的最大值就是n-2,就是j小于n-1-0,n-1-i
    #第二次循环,即i=1的时候,用j来控制循环,把整个数列的次最大的,放到整个数列的次最后一个位置,即j+1=n-2,就是j小于n-1-1,n-1-i
        for j in range(b_len - i - 1 ):
            if b_li[j] > b_li[j + 1]: #逐个比较,直到把整个列表中的最大的一个放到整个列表的最后一个位置,即n-1的位置
                b_li[j],b_li[j + 1] = b_li[j + 1],b_li[j] #数列进行一个升序排列,小于,就是降序排列
    return b_li

#插入排序
def insert_f(i_li):
    i_len = len(i_li)   #获取整个数列的升序
    for i in range(i_len):  #循环遍历整个数列
        j = i - 1   #取数列比较值的前一个数值
        #i是0的时候,j是-1。不用比较。i是1的时候,j是0,用数列[0]与[1],进行对比
        i_temp = i_li[i]    #把比较值的数值取出,暂存到临时值,temp,中
        #只要j大于,等于0,而且,[j]比temp要大,那么,就把这个[j]移动到[j+1]的位置
        #即向后移动,所有比temp大的。而比temp小的,则停止循环。
        while j >= 0 and i_li[j] > i_temp:  #大于,就是升序排列。小于,就是降序排列。
            i_li[j + 1]= i_li[j]    #[j]向后移动一个位置
            j -= 1  #j向前移动1个位置
        i_li[j + 1] = i_temp    #把temp的数值,赋值给j+1,也就是i
    return i_li

#希尔排序,就是升级版本的插入排序
def shell_f(s_li):
    s_len = len(s_li)   #得到数列的长度
    gap = s_len // 2    #得到第一次的gap,即长度的一半
    #从gap开始进行,逐个加1的循环,把数列分成若干个,以gap为间隔的小数列
    for i in range(gap,s_len):  #i的初值是gap,然后,次值是gap+1。。。
        j = i - gap #将[i]与[i-gap]进行对比
        temp = s_li[i]  #将[i]赋值给temp,空出[i]
        #大于,等于gap,并且,[j]大于temp,则后移。
        #大于,就是升序。小于,就是降序
        while j >= gap and s_li[j] > temp:
            s_li[j + gap] = s_li[j]
            j -= gap
        s_li[j + gap] = temp
    gap //= 2   #对gap地板除以2,得到新的gap,再次进行新的循环遍历
    return s_li

#选择排序
def selection_f(se_li):
    se_len = len(se_li) #获取数列的长度
    for i in range(se_len): #遍历循环整个数列
        se_min = i  #假设当前的i,是整个数列的最小值
        #i是0,即假设0是最小值。i是1,即假设1是最小值
        #j从i+1开始与i比较。
        #i是0,j从1开始,即0与1以后的所有数值进行比较
        for j in range(i + 1,se_len):
            #小于,就是升序排列。找到整个数列中,最小的一个数值
            #并将最小的数值放到i的位置,即0
            #大于,就是降序排列。
            if se_li[j] < se_li[se_min]:
                se_min = j  #j比se_min还要小,则将j赋值给se_min
                #保证,se_min始终指向整个数列的最小的数值
        if se_min != i: #如果整个数列的最小值不是i,则将se_min与i交换
            se_li[se_min],se_li[i] = se_li[i],se_li[se_min]
    return se_li

#归并排序
#先分治,把整个数列划分为一个又一个单独的小数列
#再合并,把整个数列单独的一个一个进行比较,合并
#分治数列,拆分数列
def devide_f(de_li):
    de_len = len(de_li) #获取数列的长度
    if de_len == 1: #直到把数列拆分为单独的一个数列的时候,则返回这个数列
        return de_li    #返回单个的小数列
    #拆分为左数列,左数列是从0开始,直到整个数列升序的一半
    left_li = devide_f(de_li[:de_len // 2])
    #拆分为右数列,右数列是从整个数列长度的一半开始,直到整个数列的最后一个数值
    right_li = devide_f(de_li[de_len // 2:])
    #把最后拆分的,单独的,一个一个的数列,传输给,合并的函数merge
    return merge_f(left_li,right_li)
#合并数列
def merge_f(left_li,right_li):
    #在每次循环,进入合并的函数之前,把左,右赋值为0.
    #在循环之前,始终用一个空的数列来保存,合并函数运行之后的,数列
    left_s, right_s, merge = 0, 0, []
    #控制循环的条件,左值小于左数列的长度,右值小于右数列的长度
    while left_s < len(left_li) and right_s < len(right_li):
        #小于,就是升序排列。大于,就是降序排列。
        #左数列的数值小于右数列的数值,则把,小值赋值到,空的数列中
        if left_li[left_s] <= right_li[right_s]:
            merge.append(left_li[left_s])
            left_s += 1
        # 右数列的数值小于左数列的数值,则把,小值赋值到,空的数列中
        else:
            merge.append(right_li[right_s])
            right_s += 1
    #把将数列进行合并,并且,把左数列剩余的数值,与右数列剩余的数值,分别赋值给merge
    merge = merge + left_li[left_s:] + right_li[right_s:]
    return merge

#快速排序
#比较每个循环之间,保证左边永远是小于temp,右边永远是大于temp
def kuai_f(ku_li,head,tail):
    ku_temp = ku_li[head]   #把数列的第一个数值,即head,赋值给temp
    while head < tail:  #始终保证数列至少有2个数值,如果,小于2,不用进入循环
        #初值必须要始终小于终值,而且,终值必须始终大于temp。直到找到一个小于temp的,则退出循环
        while head < tail and ku_li[tail] >= ku_temp:   #大于号就是升序排列,小于号就是降序排列
            tail -= 1   #大于temp,则前移1个数位
        ku_li[head] = ku_li[tail]   #将小于temp的,赋值给初值
        #初值必须要始终小于终值,而且,终值必须始终小于temp。直到找到一个大于temp的,则退出循环
        while head < tail and ku_li[head] < ku_temp:  #小于号就是升序排列,大于号就是降序排列
            head += 1   #小于temp,则后移1个数位
        ku_li[tail] = ku_li[head]   #将大于temp的,赋值给终值
    #在最后的循环结束的时候,head等于tail的时候,把temp赋值给数列的head,tail
    ku_li[head] = ku_temp
    return tail
#拆分数列
def partion_f(ku_li,heads,tails):
    if heads < tails:   #始终保证数列,至少有2个数值
        # 第一次循环,将数列的第一个数值,[0],赋值给temp,
        #以[0]为中间值,右边全部是比[0]大的数值,左边全部是比[0]小的数值
        mid = kuai_f(ku_li,heads,tails)
        #再次循环比较head到mid-1,的数列
        partion_f(ku_li,heads,mid - 1)
        # 再次循环比较mid+1到tails,的数列
        partion_f(ku_li, mid + 1, tails)
    return ku_li

#堆排序
#比较数列,保证根值,始终是最大的数值
def heap_f(he_li,n_len,i):
    hea_temp = i    #把根值赋值给temp,假设,temp始终指向最大值
    #分别获取左叶子值与右叶子值
    #如,1,3,5,98,7。。这些var对应的index分别是0,1,2,3,4。。
    #所以,左叶子值是,2*0+1,右叶子值是2*0+2。。。
    left_s, right_s = 2 * i + 1, 2 * i + 2
    #只要左叶子值小于长度值,len。并且,左叶子值大于根值
    #则,把temp指向最大值的,左叶子值left,使temp指向left
    #大于号,就是升序排列。小于号,就是降序排列。
    if left_s < n_len and he_li[left_s] > he_li[i]:
        hea_temp = left_s
    #只要右叶子值小于长度值,len。并且,右叶子值大于根值
    #则,把temp指向最大值的,右叶子值right,使temp指向right
    # 大于号,就是升序排列。小于号,就是降序排列。
    if right_s < n_len and he_li[right_s] > he_li[hea_temp]:
        hea_temp = right_s
    #如果,根值与temp不相等,则说明,i没有指向最大值。而是,temp指向最大值。
    #则,交换temp指向的与i指向的数值
    #如果,i与temp相等,说明,数列本身就是一个大顶堆,即i指向最大值
    if i != hea_temp:
        he_li[hea_temp],he_li[i] = he_li[i],he_li[hea_temp]
        #则,把temp传递给新的i值,进行下一次的函数调用排序。
        heap_f(he_li,n_len,hea_temp)
#数列进行循环
def devide_fs(array):
    dev_len = len(array)    #获取数列的长度
    #从n-1到0,要遍历循环数列的每个数值,所以,最终值是-1,倒序以-1进行递减,逐个比较数列的每个数值
    #直到把数列变成一个大顶堆
    for i in range(dev_len - 1,-1,-1):
        heap_f(array,dev_len,i) #倒序把每个数值传递到堆函数中,进行循环比较
    #从n-1到1,只用比较到倒数的第二个数值即可,所以,最终值是0。
    #交换,1指向的与0指向的数值,到1即可停止循环了。
    # 倒序,把j从len-1开始,一个一个的递减,以-1为单位进行递减。
    for j in range(dev_len - 1,0,-1):
        #交换根值与最后一个数值
        array[j],array[0]=array[0],array[j]
        #每次把0赋值给i,每个初值就是0,每个j就是数列的长度。
        heap_f(array,j,0)
    return array

#计数排序   只有一个升序排列,暂时没有降序排列
def count_f(c_arr,c_max = 100000):    #用c_max控制数列的最大长度
    #c_max可以是100,代表,只能对101以内的数值进行排序对比
    # c_max可以是1000,代表,只能对1001以内的数值进行排序对比
    #新建一个,c_amx + 1的长度的数列
    c_li = [0 for _ in range(c_max + 1)]
    #遍历该数列,取出var,即数值
    for var in c_arr:
        #把var相同的数值,添加到var的数值中
        c_li[var] += 1
    #把原数列进行清空,以用于存储新的数值
    c_arr.clear()
    c_len = len(c_li)
    #遍历数列的,var,index,用于对比之后生成,新的数列
    for index,var in enumerate(c_li):
        #遍历var,将var对应的index,分别添加到新的数列中
        for j in range(var):
        #for j in range(c_len - 1,0):
            c_arr.append(index) #添加到新的数列中
    return c_arr

#桶排序
def bucket_f(b_arr,n = 100,n_max = 10000): #用n_max来控制二维数列的长度,n来控制一维数列的长度
    b_lis = [[] for _ in range(n)] #生成一个二维数列
    for var in b_arr:   #遍历要排序的数列
        #189,放在哪个桶中呢。应该是放在,2号桶,即index = 2的桶中
        #所以,2 = 189 // (10000 // 100),地板除。
        #10000,只能放在最后一个桶中,即99号桶,
        #但,10000 // (10000 // 100) = 100,超过了索引值,99
        #所以,要取,地板除与,n-1的最小值
        i = min(var // (n_max // n),n-1)
        b_lis[i].append(var)    #把var加入到对应的索引值中,即i
        #使用类似于冒泡排序的算法,对i的桶进行排序
        for j in range(len(b_lis[i]) - 1,0,-1): #按照倒序的方法,从最后一个索引值开始,递减比较大小
            if b_lis[i][j - 1] > b_lis[i][j]:   #小于号就是降序排列,大于号就是升序排列
                b_lis[i][j - 1],b_lis[i][j] = b_lis[i][j],b_lis[i][j - 1]
            else:
                break   #如果j-1比j要小,则终止if循环,不用交换数值。
    s_lis = []  #新建一个数列,用来存储排序之后的数列
    for k in b_lis: #遍历二维数列
        s_lis.extend(k) #把二维数列的,0到99号的一维数列,把已经排序成功的数列,整个,添加到新的数列中
    return s_lis

#基数排序   只有一个升序排列,暂时没有降序排列
def radix_f(r_arr):
    r_max = max(r_arr)  #获取数列的最大值
    r_pivot = 0 #临时指针,用于记录,每次比较的排序的位数,即从个位数,十位数。。。直到最后的位数
    #保证每次被比较的指针值,全部小于,或者,等于数列的最大值
    while 10 ** r_pivot <= r_max:
        #建立一个二维数列,长度是10的,用于存储按照,指针排序好的数列,即个位数,十位数。。等等
        r_buckets = [[] for _ in range(10)]
        for var in r_arr:   #获取数列的var
            #299的第一次排序,按照个位数来,即9
            #9 = 299 // 10 ** 0 = 299 // 1 = 299,299 % 10 = 9
            digit = (var // 10 ** r_pivot) % 10
            r_buckets[digit].append(var)    #把个位数全部是,digit的,全部存储到,digit中
        r_arr.clear()   #清空老数列
        for r_var in r_buckets: #遍历二维数列
            #从0开始,把个位数从0到9依次升序来输出数列
            r_arr.extend(r_var) #添加到老的数列中
        #个位数排序完毕,指针数值加1,进行十位数的排序比较
        r_pivot += 1
    return r_arr


p_li = [random.randint(0,90000) for _ in range(13)]
random.shuffle(p_li) #把数列的排序随意打乱
print('初始值 : ',p_li)
print(f'1,冒泡排序的升序排列值 : {bubble_f(p_li)}')
print('2,插入排序的升序排列值 : ', insert_f(p_li))
print('3,希尔排序的升序排列值 : {0}'.format(shell_f(p_li)))
print('4,选择排序的升序排列值 : ' , selection_f(p_li))
print('5,归并排序的升序排列值 : ' , devide_f(p_li))
print('6,快速排序的升序排列值 : ' , partion_f(p_li,0,len(p_li) - 1))
print('7,堆排序的升序排列值 : ' , devide_fs(p_li))
print('8,计数排序的升序排列值 : ' , count_f(p_li))
print('9,桶排序的升序排列值 : ' , bucket_f(p_li))
print('10,基数排序的升序排列值 : ' , radix_f(p_li))

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/730879.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-27
下一篇 2022-04-27

发表评论

登录后才能评论

评论列表(0条)

保存