RUN__IT # 常见的几种排序python版(冒泡,选择,插入,希尔,快速,归并)

效率和稳定性

在这里插入图片描述

冒泡排序

冒泡排序就是前一个和后一个比较,把最大的数往后沉

def bubble1_sort(li):
    """冒泡排序"""
    n = len(li)
    count = 0
    # 控制循环次数
    for i in range(n-1):
        for j in range(n-1-i):
            # 若当前元素比后一个大,就交换位置
            # 一直和后一个元素比较,把最大的往后沉
            if li[j] > li[j+1]:
                li[j+1],li[j]  = li[j],li[j+1]
                count += 1
        # 如果没有进行交换,则说名是有序的,直接结束循环
        if count == 0:
            break


if __name__ == '__main__':
    list1 = [17,14,12,5,11,24,2,6,15,19,8,3,9]
    bubble1_sort(list1)
    print(list1)

选择排序

def choose_sort(li):
    """选择排序"""
    n = len(li)
    # 控制循环次数
    for j in range(0,n-1):
        min_index = j
        # j之前是有序的,之后是无序的
        for i in range(j+1,n):
            # 如果是有比j小的元素就把这个元素的索引赋值给j
            if li[i] < li[j]:
                j = i
        # 如果进行了比较并改变了j就进行交换元素,若没有变化,说明是对应的位置,不进行交换减小时间复杂度
        # 把索引是j的元素换到min_index这个位置
        if min_index != j:
            li[j],li[min_index] = li[min_index],li[j]


if __name__ == '__main__':
    list1 = [17,14,12,5,11,24,2,6,15,19,8,3,9]    
    choose_sort(list1)
    print(list1)

插入排序

def insert_sort(li):
    """插入排序"""
    n = len(li)
    # 取出元素j
    for j in range(1,n):
        # j前面的元素是有序的
        # 当前元素和前一个比较
        for i in range(j,0,-1):
            if li[i] < li[i-1]:
                # 比前一个小进行交换
                li[i],li[i-1] = li[i-1],li[i]
            else:
                # 如果条件不满足说明这个元素比前面的元素都大,放在当前位置结束当前循环
                break


if __name__ == '__main__':
    list1 = [17,14,12,5,11,24,2,6,15,19,8,3,9]    
    insert_sort(list1)
    print(list1)

希尔排序

希尔排序就是分组后进行插入排序

def shell_sort1(li):
    """希尔排序第一次练习"""
    n = len(li)
    # 分组
    gap = n // 2
    # 只要步长大于等于1,就继续进行插入排序,继续分组
    while gap >= 1:
        # 每次从第二组开始,也就是第一个步长开始,和前一个步长的元素比较
        for j in range(gap,n):
            while (j-gap) >= 0:
                # 当前元素小的话就往前交换,直到合适位置
                if li[j] < li[j-gap]:
                    li[j],li[j-gap] = li[j-gap],li[j]
                else:
                    # 如果条件不满足,则说明当前元素大,不用往前交换,结束当前循环
                    break
                # 控制循环,不断往前交换
                j -= gap
        # 不断分组,进行插入
        gap //= 2


if __name__ == '__main__':
    list1 = [17, 14, 12, 5, 11, 24, 2, 6, 15, 19, 8, 3, 9]
    shell_sort1(list1)
    print(list1)

快速排序

快速排序的特点就是取出一个元素,然后用两个游标,从右左依次取出元素和这个元素比较,小的往左,大的往右交换,这两个游标重合时,就找到了这个元素的位置。然后序列分两部分,分别重复刚才的过程(递归)。
在这里插入图片描述

def quick_sort(li,start,end):
   """快速排序"""
   # 当序列只有一个元素时,就返回
   if start >= end:
       return
   # 创建2个游标
   left = start
   right = end
   # 取出第一个元素
   mid = li[start]
   while left < right:
       # 拿右边元素逐一和mid进行比较
       while left < right and li[right] >= mid:
           right -= 1
       # 退出循环时,说明比mid小,把元素放到左游标的位置
       li[left] = li[right]
       # 然后左游标进行比较移动
       while left < right and li[left] < mid:
           left += 1
       # 左边大于mid的往右游标位置放
       li[right] = li[left]
   # 当游标重合时,则说明移动结束,把mid放到游标重合处,左边是比它小的,右边是比它大的
   li[left] = mid
   
   # 递归调用
   quick_sort(li,start,left-1)
   quick_sort(li,left+1,end)


if __name__ == '__main__':
    list1 = [17, 14, 12, 5, 11, 24, 2, 6, 15, 19, 8, 3, 9]
    quick_sort(list1,0,len(list1)-1)
    print(list1)

归并排序

归并排序就是先分组,递归分组,把序列分成一个一个元素的序列,然后再合并这些有序的序列。

def merge_sort(li):
    """归并排序"""
    n = len(li)
    if n <= 1:
        return li
    # 拆分
    mid = n // 2
    # 递归拆分
    left_li = merge_sort(li[:mid])
    right_li = merge_sort(li[mid:])
    
    # 合并,每个序列是有序的
    left,right = 0,0
    merge = list()
    left_n = len(left_li)
    right_n = len(left_li)
    while left < left_n and right < right_n:
        # 两个有序序列中的第一个元素谁小谁添加到列表中
        if left_li[left] < right_li[right]:
            merge.append(left_li[left])
            left += 1
        else:
            merge.append(right_li[right])
            right += 1
    # 退出循环后,把剩余的元素追加到列表中
    merge += left_li[left:]
    merge += right_li[gight:]
    # 返回排好序的新列表
    return merge
    

if __name__ == '__main__':
    list1 = [17, 14, 12, 5, 11, 24, 2, 6, 15, 19, 8, 3, 9]
    print(merge_sort(list1))

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值