python实现各种排序算法

常见的排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。

 
在这里插入图片描述
 

稳定性:
  • 排序后 2 个相等键值的顺序和排序之前它们的顺序相同

  • 稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序。

  • 不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序。
     

测试:
单位(s)10000数据100000数据1000000
冒泡排序21.00//
选择排序8.02//
插入排序8.00//
堆排序0.0961.09416.209
归并排序0.0871.01713.214
快速排序0.030.6147.659
sorted()0.000.3120.752

 
 

1.冒泡排序:核心思想就是每次比较两个相邻的数,把数大的放后面,每循环一次找出一个最大的数放到要排序的列表的最后面,然后循环排序,直到没有任何一对数字需要比较,要排序的列表就排好序了。

 

def bubbleSort(arr):
    for i in range(1,len(arr)):
         for j in range(0,len(arr)-i):
             if arr[j]>arr[j+1]:
                 arr[j],arr[j+1]=arr[j+1],arr[j]

(2).动图演示:
在这里插入图片描述
 
 

2.选择排序:核心思想就是找到要排序列表中最小的那个数,把它放到第一位,然后再动列表中找到最小的数把它放到已排好序的列表后面,依次排完。选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间。
#找到最小值的下标
def get_min_pos(arr):
    min_pos = 0
    for i in range(1,len(arr)):
        if arr[i] < arr[min_pos]:
            min_pos = i
    return min_pos

def select_sort(arr):
    for i in range(len(arr)-1):
        min_pos = i
        for j in range(i+1,len(arr)):
            if arr[j] < arr[min_pos]:
                min_pos = j
        arr[i],arr[min_pos] = arr[min_pos],arr[i]

(2):动图演示:
在这里插入图片描述
 
 

3.插入排序:插入排序就像我们打扑克牌一样,你先接一张拿到手里,再接一张,如果比手里的大,放到右边,如果比手里小,放在左边,把每张牌插入到它应该在的位置上。手里的牌是排好序的,未接的牌是未排序的,直到牌接完就排序好了。
def insert_sort(arr):
    for i in range(1,len(arr)):
        # 拿到的第一张牌
        tmp = arr[i]
        j = i - 1
        while j >= 0 and arr[j] > tmp:  #只要往后挪就循环 2个条件都得满足
            arr[j+1] = arr[j]                                #如果j =-1 停止挪 如果arr[j]小了,停止挪
            j -= 1
        arr[j+1] = tmp

(2):动图演示:
在这里插入图片描述
 
 

4.快速排序:快排的思想就是拿到要排序列表的第一个元素,经过算法找到它在列表中的排序好后的位置,然后将列表分成左右两个列表,左右两个列表再递归的排序。递归结束条件就是要排序的这个列表只剩1个元素,或0个元素就结束了。left是列表中第一个元素的小标,right是列表中最后一个元素的下标left = 0 right = len(arr-1)。

代码:

def quick_sort(arr,left,right):
    if left <right: #待排序的区域至少有两个元素
        mid = partition(arr,left,right)
        quick_sort(arr,left,mid-1)
        quick_sort(arr,mid+1,right)
    return arr
def partition(arr,left,right):
    tmp = arr[left] #把要排序列表的第一个数存起来
    while left < right:
        while  left < right and arr[right] >= tmp:
            right -= 1
        arr[left] = arr[right]
        while left < right and arr[left] <= tmp:
            left += 1
        arr[right]=arr[left]
    arr[left] =tmp
    return left

(2):动图演示:
在这里插入图片描述
 
 

5.堆排序:

堆的性质:堆分为大根堆和小根堆,堆是一个完全二叉树。

  • 大根堆:一颗完全二叉树,满足任意节点都比其孩子节点大。大根堆排序出来是升序的。
  • 小根堆:一颗完全二叉树,满足任意节点都比其孩子节点小。小根堆排序出来是降序的。
  • 核心思想就是每次把堆顶最大的元素拿下来(d大根堆),把子节点最小元素放到堆顶(拿到最小元素后堆依然是完全二叉树),然后再依次调整堆,让它满足堆的性质,然后再取下堆顶最大元素,依次排完。
#low是树的根的位置下标,high是树最后一个元素的下标
def sift(arr,low,high):
    tmp = arr[low]
    # i指向空位置,j指向两个孩子
    i = low
    j = 2*i + 1
    #循环对出的第二种情况,j>high,说明位置i是叶子节点
    while j <= high:
        #如果右孩子存在并且比左孩子大,指向右孩子
        if j+1 <= high and arr[j] < arr[j+1]:
            j += 1
        if arr[j] > tmp:
            arr[i] = arr[j]
            i = j
            j = 2 * i +1
        #循环退出的第一种情况:j位置的值比tmp小,说明两个孩子都比tmp小
        else:
            break
    arr[i] = tmp

def heap_sort(arr):
    n = len(arr)
    #构造堆
    for low in range(n//2-1,-1,-1):
        sift(arr,low,n-1)
    #挨个出数
    for high in range(n-1,-1,-1):
        arr[0],arr[high] = arr[high],arr[0]
        sift(arr,0,high-1)

(2):动图演示:
在这里插入图片描述
 
 

6.归并排序:核心思想就是将要排序的序列递归分成最小的序列(序列中只剩两个元素或1个元素),然后比较最小序列中的两个数,小的放左边,大的放右边,最小序列就拍好序了,然后再递归往上,两个排序好的最小序列再比较其中元素大小,拍好序之后再递归往上比较。直到递归结束完成排序。
def merge_sort(arr):
    if len(arr) <= 1:
        return arr
    num = len(arr)//2
    left = merge_sort(arr[:num])
    right = merge_sort(arr[num:])
    return _sort(left,right)

def _sort(left,right):
    l,r = 0,0
    result = []
    while l < len(left) and r < len(right):
        if left[l] < right[r]:
            result.append(left[l])
            l += 1
        else:
            result.append(right[r])
            r += 1
    result +=left[l:]
    result +=right[r:]
    return result

(2):动图演示:
在这里插入图片描述

 
 

7.希尔排序:核心思想就是先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
def insert_sort_gro(arr,d):
    for i in range(d,len(arr)):
        # 拿到的第一张牌
        tmp = arr[i]
        j = i - d
        while j >= 0 and arr[j] > tmp:  #只要往后挪就循环 2个条件都得满足
            arr[j+d] = arr[j]                                #如果j =-1 停止挪 如果arr[j]小了,停止挪
            j -= d
        arr[j+d] = tmp

def shell_sort(arr):
    d = len(arr)  // 2
    while d>0:
        insert_sort_gro(arr,d)
        d = d // 2

 
 

8.计数排序:核心思想就是将输入的数据值转化为键存储在额外开辟的数组空间中。然后遍历要排序的列表,记录每个元素出现的次数,最后根据记录的次数依次打印列表。计数排序时间复杂度是n,很快,但是它有个缺陷,就是要排序的列表中的元素必须是一个区间的数,而这个区间跨度不能很大,比如[1,20000000,3,6,3,45,6],对于种列表,计数排序就跪下了。
def count_sort(arr,max_num):
    count = [0 for _ in range(max_num + 1)]
    for val in arr:
        count[val] += 1
    arr.clear()
    for i,v in enumerate(count):
        for _ in range(v):
            arr.append(i)

(2):动图演示:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值