排序算法总结 (Python实现)

算法一:插入排序
算法思想:初始时(有序区)只有一张牌;每次(从无序区)拿出一张牌,插入到手里已有牌的正确位置

def insert_sort(li):
    for i in range(1,len(li)):   #表示摸到的牌的下标
        tmp = li[i]
        j = i -1  #j指的是手里的牌的下标
        while j >= 0 and li[j] > tmp:  #当手中的牌存在并且手中的牌的数字大于摸到的牌的数字
            li[i] = li[j]            #  把手中的牌的位置与摸到的牌的位置交换
            j -= 1                   #  手中牌的位置向左更新
        li[j+1] = tmp               # 当手中的牌小于摸到的牌的时候,把此时摸到的牌更新为手中的牌
li  = [1,2,3,4,8,6,7,7]
insert_sort(li)
print(li)

算法二:希尔排序(分组插入排序)
算法思想::先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
 

def insert_sort_gap(li,gap):   #类似插入排序
    for i in range(gap,len(li)):   #表示摸到的牌的下标
        tmp = li[i]
        j = i -gap  #j指的是手里的牌的下标
        while j >= 0 and li[j] > tmp:  #当手中的牌存在并且手中的牌的数字大于摸到的牌的数字
            li[j+gap] = li[j]            #  把手中的牌的位置与摸到的牌的位置交换
            j -= gap                   #  手中牌的位置向左更新
        li[j+gap] = tmp               # 当手中的牌小于摸到的牌的时候,把此时摸到的牌更新为手中的牌

def shell(li):
    d = len(li)
    while d>=1:
        insert_sort_gap(li,d)
        d //=2

算法三:冒泡排序

算法思想:比较相邻的元素。如果第一个比第二个大,就交换他们两个。一趟排序结束后,则无序区减少一个数,有序区增加一个数

注:(如果没有元素交换,则提前结束)

def rise_sort(li):
    for i in range(len(li)-1):   #第i趟
        exchanges = False      #此时的标志位为False
        for j in range(len(li)-i-1):
            if li[j] > li[j+1]:
                li[j],li[j+1]=li[j+1],li[j]
                exchanges = True     #此时的标志位为True
                print(li)
        if not exchanges:   #如果循环中没有exchange标志位,返回当前循环的值
            print("提前完成排序")
            return
li = [3,4,1,14]
rise_sort(li)
# print(li)

算法四:归并排序

算法思想:主要分为归并和排序

归并:假设现在的列表分两段有序,如何将其合并成一个有序列表

排序:采用递归调用的思想进行排序

#归并
def merge(li,low,mid,high):
    i = low
    j = mid+1
    ltmp = []
    while i<=mid and j<=high: #只要左右两边有数
        if li[i] < li[j]:
            ltmp.append(li[i])
            i +=1
        else:
            ltmp.append(li[j])
            j +=1
    #while执行完,肯定有一部分没数了
    while i<= mid:
        ltmp.append(li[i])
        i +=1
    while j<=high:
        ltmp.append(li[j])
        j +=1
    li[low:high+1] = ltmp
#排序
def merge_sort(li,low,high):
    if low<high:
        mid = (low+high)//2
        merge_sort(li,low,mid)
        merge_sort(li,mid+1,high)
        merge(li,low,mid,high)
import random
li = list(range(100))
random.shuffle(li)
print(li)
merge_sort(li,0,len(li)-1)
print(li)

算法五:堆排序

算法思想:1.建立堆。2,得到堆顶元素,为最大元素。3,去掉堆顶,将最后一个元素放到堆顶,此时可通过一次调整使堆重新有序。4,堆顶元素为第二大元素。5,重复步骤3,直到堆变空。

#向下调整
def sift(li,low,high):
    """
    :param li: 列表
    :param low: 堆的根节点位置
    :param high: 堆的最后一个元素的位置
    :return:
    """
    i = low    #i最开始指向根节点
    j = 2*i + 1   #j开始是左孩子
    tmp = li[low]  #把堆顶存起来
    while j <= high:  #只要j位置有数
        if j + 1 <= high and li[j+1]>li[j]:    #如果右孩子有且比较大
            j = j + 1         #j指向右孩子
        if li[j]>tmp:
            li[i] = li[j]     #把孩子结点的较大值放入父节点中
            i = j   #往下看一层
            j = 2*i + 1   #更新j为i的左孩子
        else:   #tmp更大的话,把tmp放到i的位置
            li[i] = tmp   #可有可无  //  把tmp放到某一级领导的位置
            break
    else:
        li[i] = tmp     #把tmp放到叶子节点上
def heap_sort(li):
    n = len(li)
    for i in range((n-2//2), -1,-1):#i代表建堆的时候调整的部分的根的下标
        sift(li,i,n-1)   #建堆完成了
    for i in range(n-1,-1,-1):  #i指向当前堆的最后一个元素   //  挨个出数
        li[0],li[i] = li[i],li[0]
        sift(li,0,i-1)      #i-1是新的high
import random
li = list(range(100))
random.shuffle(li)
print(li)
heap_sort(li)
print(li)


算法六:快速排序

算法思想:取一个元素p(第一个元素),使p归位;列表被分为两部分,左边比p小,右边比p大;递归完成排序

def left_right_exchange(li,left,right):
        temp = li[left]  #将目标值提出,此时原数组目标值的位置为空
        while left < right:
            while left < right and li[right] >= temp:  #如果右边的值大于目标值
                  right -= 1                           # 它的值不变,让它向左移动一位,继续判断
            li[left] = li[right]                        #跳出判断,即找到了小于目标值的数。把找到的那个值放入目标值的那个位置,完成交换
            while left < right and li[left] <= temp:
                  left += 1
            li[right] = li[left]
        li[left] = temp       #当两个指针指向同一个位置的时候,将目标值插入
        return left

def quickly_sort(li,left,right):
    if left < right:   #至少存在两个元素,即可以进行 left_right_exchange。
        quickly_sort(li,left,left_right_exchange(li,left,right)-1)     #使用迭代的方式
        quickly_sort(li, left_right_exchange(li, left, right)+1,right)
li = [8,2,3,12,7,89,5]

quickly_sort(li,0,len(li)-1)
print(li)

算法七:计数排序(时间复杂度为O(n))

基本思想:当列表中的元素在0-100之内时,记录列表中的每个元素出现的次数,再依次输出

def count_sort(li,max_count = 100):
    count = [0 for _ in range(max_count+1)]
    for val in li:
        count[val]+=1
    li.clear()
    for ind,val in enumerate(count):
        for i in range(val):
            li.append(ind)
import random
li = [random.randint(0,100) for _ in range(100)]
print(li)
count_sort(li)
print(li)


算法八:基数排序(多关键字排序)

基本思想:先从个位到高位进行排序

def radix_sort(li):
    max_num = max(li)
    it = 0
    while 10**it<=max_num:
        buckets = [[] for _ in range(10)]
        for var in li:
            dight = (var//10 **it) % 10
            buckets[dight].append(var)  #分桶完成
        li.clear()
        for bucket in buckets:
            li.extend(bucket)     #把数重新放回li中
        it +=1

import random
li = list(range(1000))
random.shuffle(li)
print(li)
radix_sort(li)
print(li)

算法九:桶排序

基本思想:首先将元素分布在不同的桶中,再对每个桶中的元素进行排序

def bucket_sort(li,n=100,max_num=10000):
    buckets = [[] for _ in range(n)]  #创建桶
    for var in li:
        i = min(var//(max_num//n),n-1)   #i表示取到第几个桶
        buckets[i].append(var)
        for j in range(len(buckets[i])-1,0,-1):
            if buckets[i][j]<buckets[i][j-1]:
                buckets[i][j], buckets[i][j-1]=buckets[i][j-1],buckets[i][j]
            else:
                break
    sort_li=[]
    for bucket in buckets:
        sort_li.extend(bucket)
    return sort_li

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值