Python实现常见的排序算法

冒泡排序(Bubble Sort):列表相邻的两个数,如果前面比后面大,则交换这两个数。一趟排序结束后,无序区减少一个数,有序区增加一个数。
import random
def bubble_sort(li):
    for i in range(len(li)-1):                  #多少趟,每次找出的是最值,所以只需n-1趟
        for j in range(len(li)-i-1):            #循环每趟,排出一个
            if li[j] > li[j+1]:
                li[j],li[j+1] = li[j+1],li[j]
li = [random.randint(0,1000) for i in range(1000)]
print(li)
bubble_sort(li)
print(li)
选择排序:一趟取最小的数,放到第一个位置,在一趟排序记录列表无序区最小的数,放到第二个位置;算法关键:有序区和无序区,无序区最小数的位置。

def select_sort(li):
    for i in range(len(li)-1):   #多少趟,每趟取出一个最小值
        min_loc = i              #取出的值得下标暂时当做每趟最小下标
        for j in range(i+1,len(li)):     #在剩余无序区做循环,拿出最值
            if li[j] <li[min_loc]:
                min_loc = j
        li[i],li[min_loc]= li[min_loc],li[i]
    return li
li = [1,4,5,6,7,7,2,0,7]
print(select_sort(li))
插入排序:初始时手里(有序区)只有一张牌,每次从(无序区)摸一张牌,插入到手里正确位置。

def sort(li):
    for i in range(1,len(li)):    #从无序区开始拿牌,从1开始是将0当为有序区
        tmp = li[i]               #一次拿到的牌
        j = i-1                   #有序区最后一张牌下标
        while j >= 0 and li[j] > tmp:  #有序区有牌且最后一个元素比拿出来的元素大
            li[j+1] = li[j]            #将有序区牌后移给tmp腾地方
            j -= 1                     #遍历有序区
        li[j+1] = tmp     #遍历结束,将tmp放在合适的位置上,j+1是遍历完的符合条件的合适位置
        print(li)
li = [9,1,3,4,6,2]
sort(li)
希尔排序:是一种分组插入排序算法。时间复杂度跟选择的gap有关。
   1、先取一个整数d1=n/2,将元素分为d1个组,每组相邻量元素之间距离为d1,在各组内进行直接插入排序。
   2、取第二个人整数d2=d1/2,重复上述分组排序过程,直到d1=1,即所有元素在同一组内进行直接插入排序。
   希尔排序每趟并不使某些元素有序,而是使整体数据越来越接近有序,最后一躺排序是所有数据有序。

def inser_sort_gap(li,gap):
    for i in range(gap,len(li)):       #从gap开始,可以循环每组无序区,因为gap之前的是每组有序区的第一个元素
        tmp = li[i]                    #每组无序区拿出的元素
        j = i - gap                    #每组有序区的元素
        while j >= 0 and li[j] > tmp:  #每组有序区有元素且拿出的元素与有序区元素冲突
            li[j+gap] = li[j]          #将大小冲突元素后移
            j -= gap                   #合适位置前移
        li[j+gap] = tmp                #将tmp放在前移的j+gap位置上
def shell_sort(li):
    d = len(li)//2                    #分为d组,相邻元素间隔d
    while d >= 1:                     #当分为最小组,停止循环,此时相邻元素间隔1
        inser_sort_gap(li,d)
        d //= 2
li = list(range(19))
import random
random.shuffle(li)
print(li)
shell_sort(li)
print(li)
快速排序:(思路:1.取一个元素p,使p归位。2.列表分为两个部分,左边都比p小,右边都比p大。3.递归。)
         效率:nlog(n)    最坏情况,递归

def guiwei(li,left,right):   #将列表分为2部分,左边比tmp小,右边比tmp大
    tmp = li[left]           #tmp取值
    while left < right:     #更新完left,right后,继续循环
        while li[right] >=  tmp and left < right:  #当右边元素比tmp大
            right -= 1                             #满足条件,right左移,防止一直左移下去,要求left《right
        li[left] = li[right]                       #将比tmp大的元素移到左边
        while li[left] <= tmp and left < right:
            left += 1
        li[right] = li[left]                       #
    li[left] = tmp                                 #left一直在右移,最终到达合适位置
    return left             #返回界限下标
def quick_sort(li,left,right):
    if left < right:                            #
        mid = guiwei(li, left, right)           #找出界限
        quick_sort(li, left, mid - 1)           #对界限左边进行循环
        quick_sort(li, mid + 1, right)          #对界限右边进行循环
import random
li = list(range(19))
random.shuffle(li)
print(li)
quick_sort(li,0,len(li)-1)
print(li)
归并排序:对列表进行递归拆分到单独元素,在进行递归合并为一整个有序列表。

def merge(li,low,mid,high):        #对2个列表进行合并,使得合并后的列表有顺序
    ltmp = []                      #新的列表
    i = low                        #i,j分别为两个列表的开始下标
    j = mid + 1
    while i <= mid and j <= high:  #对2个列表依次拿出比较,符合条件的会加入到ltmp,指针会更新
        if li[i] < li[j]:
            ltmp.append(li[i])
            i += 1
        else:
            ltmp.append(li[j])
            j += 1
    while i <= mid:                #当之前指针更新结束,说明其中一个列表已经全部加入ltmp,另一个列表中的其余元素则全部加入ltmp
        ltmp.append(li[i])
        i += 1
    while j <= high:
        ltmp.append(li[j])
        j += 1
    li[low:high+1] = ltmp         #ltmp每次递归,low-high+1是把一次递归的元素加上,+1是列表的索引性
def merge_sort(li,low,high):        #将列表递归拆分
    if low < high:                  #一个列表左边小于右边就循环,也就是说只要列表有至少2个元素就进行拆分
        mid = (low + high) // 2     #拆分界线
        merge_sort(li, low, mid)    #整除都是向下取整,所以mid,mid+1可以做到以mid为界限进行拆分
        merge_sort(li, mid + 1, high)
        merge(li, low, mid, high)  #拆分递归到最后,是单个元素进行归并;然后再归并递归
li = list(range(9))
import random
random.shuffle(li)
print(li)
merge_sort(li,0,len(li)-1)
print(li)
计数排序:对列表进行排序,已知列表的数范围在0-100之间。设时间复杂度为O(n)的算法。

def count_sort(li):
    count = [0 for _ in range(max(li)+1)]           #count为每个元素的个数表
    for k in li:
        count[k] += 1
    li.clear()
    for kk,kkk in enumerate(count):                  #循环每个元素及其个数,enumerate的作用是遍历索引及其元素
        for p in range(kkk):                         #range个数,打印元素,喵喵!!!
            li.append(kk)
import random
li = [random.randint(0,10) for _ in range(10)]
print(li)
count_sort(li)
print(li)
桶排序:首先将元素分在不同的桶里,在对每个桶里面的元素进行排序。
      桶排序的表现取决于数据的分布。也就是需要对不同数据排序时采用不同的分桶策略。平均情况时间复杂度:O(n+k)

def bar_sort(li,n,max_num):                             #n为桶的个数,max_num为li中的最大数,根据他两确定桶之间的差值
    buckets = [[] for _ in range(n)]                    #建立n个空桶
    for k in li:
        i = min(k//(max_num//n),n-1)                    #循环列表元素,将其放在适当桶里面
        buckets[i].append(k)
        for j in range(len(buckets[i])-1,0,-1):         #循环每个桶里面的元素,0--len-1表示每个桶里面的所有元素
            if buckets[i][j] < buckets[i][j-1]:
                buckets[i][j-1],buckets[i][j] = buckets[i][j],buckets[i][j-1]
            else:
                break
    sort_li = []
    for bucket in buckets:
        sort_li.extend(bucket)
    return sort_li
import random
li = [random.randint(0,100) for _ in range(100)]
print(li)
li = bar_sort(li,10,100)
print(li)
基数排序:
时间复杂度O(kn)   空间复杂度O(k+n)   k表示数字位数

def ratix_sort(li):                          #将数字整除取余,依次按顺序添加到适当位置
    max_num = max(li)                        #列表中的最大数字
    it = 0                                   #首先从个位数开始
    while 10 ** it <= max_num:               #当10的it次方小于最大数
        buckets = [[] for _ in range(10)]    #余数为0--9,一共10个桶
        for var in li:
            geweishu = (var//10**it) % 10    #取每个数的余数
            buckets[geweishu].append(var)  #将其放在余数的桶里,使得每个桶里的元素个位数一样
        li.clear()
        print(buckets)
        for buc in buckets:
            li.extend(buc)
        it += 1                            #一趟结束后,it+1,继续上述操作,可以对之前桶里面的元素进行排序
    return li
import random
li = list(range(1000))
random.shuffle(li)
print(li)
c = ratix_sort(li)
print(c)
堆:一种特殊的完全二叉树结构。
   大根堆:一颗完全二叉树,满足任一节点都比其孩子节点大。(领导机构)
   小根堆:一颗完全二叉树,满足任一节点都比其孩子节点小。
堆的向下调整性:假设根节点的左右子树都是堆,但根节点不满足堆的性质,可以通过一次向下的调整来将其变成一个堆。
堆排序过程:
        1.建立堆.
        2.得到堆顶元素,为最大元素。
        3.去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序。
        4.堆顶元素为第二大元素。
        5.重复步骤3,直到堆变空。
def shift(li,low,high):                  #堆的向下调整,一次将合适元素放在堆顶,low指堆顶
    tmp = li[low]                        #将堆顶暂时存在tmp
    i = low                              #根节点和叶节点
    j = 2*i + 1
    while j <= high:                     #当叶节点没到最后一个元素,一直循环
        if j + 1 <= high and li[j] < li[j+1]:
            j = j + 1                    #保证拿最大叶节点和根节点比较大小
        if li[j] > tmp:                  #如果叶节点大于根节点,大的上移,将根节点下移到叶节点位置,循环比较
            li[i] = li[j]
            i = j
            j = 2*i + 1
        else:
            li[i] = tmp                 #当不符合循环条件,说明堆已经有序,将tmp放在此时的根节点位置上
            break
    else:
        li[i] = tmp                     #当跳出循环时,后面没有元素,将其放在此时的叶节点位置上
def heap_sort(li):
    n = len(li)
    for i in range(n-2//2,-1,-1):     #循环跟节点,根节点从下向上,对每个根节点进行向下调整,达到建堆目的
        shift(li,i,n-1)               #向下调整,起点为当前根节点
    for i in range(n-1,-1,-1):        #循环拿出堆的最后一个元素,将其并入有序列表
        li[0],li[i] = li[i],li[0]
        shift(li,0,i-1)               #每次拿出一个元素,对剩余的其他元素进行建堆,其余元素有序,只需调整一次

import random
li = list(range(19))
random.shuffle(li)
print(li)
heap_sort(li)
print(li)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值