基本排序算法的python实现

排序可以分为:

  • 内部排序:数据记录在内存中进行排序
  • 外部排序:因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。 

内部排序又可以分为:

  • 比较排序,时间复杂度O(nlogn) ~ O(n^2),主要有:冒泡排序,选择排序,插入排序,归并排序,快速排序,希尔排序,堆排序等。

  • 非比较排序,时间复杂度可以达到O(n),主要有:计数排序,基数排序,桶排序等


下面依次介绍每种排序算法

1冒泡排序bubble sort

基本思想:通过两两比较,每次确定一个最大的元素

def bubble_sort(nums):
    for i in range(len(nums)-1):
        for j in range(len(nums)-i-1):
            if nums[j]>nums[j+1]:
                nums[j+1],nums[j]=nums[j],nums[j+1]
    return nums

2选择排序select sort

基本思想:数组前段有序,后段无序;每次将后段中的最小元素选择出来,将其与后段的第一个元素交换位置

def select_sort(nums):
    for i in range(len(nums)):
        index=nums.index(min(nums[i:]))
        nums[i],nums[index]=nums[index],nums[i]
    return nums

3插入排序 insert sort

基本思想:数组前段有序,后段无序;每次将后段中的第一个元素插入到前段中合适的位置
def insert_sort(nums):
    for i in range(1,len(nums)):
        temp=nums[i]
        j=i-1
        while(j>=0)and nums[j]>temp :
            nums[j+1]=nums[j]
            j-=1
        nums[j+1]=temp
    return nums

4归并排序 merge sort

基本思想:

将原数组分成左右两个子序列,假如每个子序列是按升序排列的,依次比较它们的第一个元素,可以将其合并成一个更大的升序序列;用递归的方法处理子序列,直到子序列的长度为1或2,可以很容易地对其进行排序

def merge_sort(nums):
    if len(nums) <2: 
        return nums
    mid = int((len(nums) / 2))
    left = merge_sort(nums[:mid])
    right = merge_sort(nums[mid:len(nums)])
    result = []
    while len(left) > 0 and len(right) > 0:
        if (left[0] <= right[0]):
            result.append(left.pop(0))
        else:
            result.append(right.pop(0))
    if (len(left) > 0):
        result.extend(left)
    else:
        result.extend(right)
    return result

5快速排序 quick sort

基本思想:

将数组的第一个元素作为基准pivot,将剩余元素按照是否大于该基准分为两组:less和greater;如果这两组元素都是有序的,则最终的顺序为less+pivot+greater;递归地处理两个子分组,直到它们变成有序的为止

def quick_sort(nums):
    if len(nums) < 2:
        return nums
    else:
        pivot = nums[0]
        # sub-array of all the elements less than the pivot
        less = [i for i in nums[1:] if i <= pivot]
        # sub-array of all the elements greater than the pivot
        greater = [i for i in nums[1:] if i > pivot]
        return quick_sort(less) + [pivot] + quick_sort(greater)

6希尔排序shell sort

基本思想:缩减增量排序

先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。

def shell_sort(nums):
    gap=int(len(nums)/2) #排序的分组
    while gap>0:
        for i in range(gap,len(nums)):
            j=i-gap
            while nums[j]>nums[i] and j >=0:
                nums[j],nums[i]=nums[i],nums[j]
                j-=gap
                i-=gap
        gap=int(gap/2)
    return nums

7堆排序 heap sort 

基本思想:

堆排序是利用堆的特性对记录序列进行排序的一种排序方法。堆可以看做一个完全二叉树,同时该完全二叉树满足双亲结点大于等于孩子结点(大顶堆),或者双亲结点小于等于孩子结点(小顶堆)。 大顶堆产生顺序序列,小顶堆产生逆序序列。

N个元素建立二叉堆,将原来无序的序列(数组)插入到二叉树(线性二叉树),在插入的过程中不断调整二叉树为最小堆或者最大堆。 在全部插入完毕之后,此时并未排序完毕,但是已经建立起最小堆或者最大堆,堆中每一个根节点都是当前树或子树中的最小值或最大值,此时还需要进行进一步的调整来完成最终的排序。 

def heap_sort(nums):
    def sift_down(nums, start, end):
        root = start
        while True:
            # 从root开始对最大堆调整
            child = 2 * root + 1
            if child > end:
                break
            # 找出两个child中较大的一个
            if child + 1 <= end and nums[child] <nums[child + 1]:
                child += 1
            if nums[root] < nums[child]:
                # 最大堆小于较大的child, 交换顺序
                nums[root], nums[child] = nums[child], nums[root]
                # 正在调整的节点设置为root
                root = child
            else:
                # 无需调整的时候, 退出
                break
    # 从最后一个有子节点的节点开始调整最大堆
    first = len(nums) // 2 - 1
    for start in range(first, -1, -1):
        sift_down(nums, start, len(nums) - 1)
    # 将最大的放到堆的最后一个, 堆-1, 继续调整排序
    for end in range(len(nums) -1, 0, -1):
        nums[0], nums[end] = nums[end], nums[0]
        sift_down(nums, 0, end - 1)
    return nums

8桶排序

基本思想:

假设输入数据的范围确定,可以按照一定的跨度将该区间划分为若干个桶。把每一个输入数据放到相应的桶里,同时对每一个桶内部进行排序。最后再把桶合并。

def bucket_sort(nums):
    #设置桶的大小
    buckets = [0] * ((max(nums) - min(nums))+1)
    #设置桶中元素的值
    for i in range(len(nums)):
        buckets[nums[i]-min(nums)] += 1
    #将桶中元素存到B,此时B有序
    B=[]
    for i in range(len(buckets)):
        if buckets[i] != 0:
            B += [i+min(nums)]*buckets[i]
    return B

9计数排序

基本思想:

利用哈希的方法,将每个数据出现的次数都统计下来。哈希表是顺序的,所以我们统计完后直接遍历哈希表,将数据再重写回原数据空间就可以完成排序。

def count_sort(nums):
    #最终排好序的数组
    B=[0]*len(nums)
    #计算用来存储计数的数组C的长度
    maxNum=max(nums)
    minNum=min(nums)
    cLength=maxNum-minNum+1
    C=[0]*cLength
    #将原数组中数字出现的次数存储到C中
    for i in range(len(nums)):
        #datalist[i]-min表示datalist中下标为i的值应该放到C中哪个位置去
        C[nums[i]-minNum]+=1
    #将C中数组元素的值(每个值出现的次数)加上前一个数字出现的次数
    for i in range(1,cLength):
        C[i]+=C[i-1]
    #遍历A中元素,将它放入B中最终应该在的位置
    for i in range(len(nums)):
        #C[datalist[i]-minNum]表示截止datalist[i],小于等于datalist[i]的有多少
        B[C[nums[i]-minNum]-1]=nums[i]
        #c中记录的值得数量应该减1,因为那个对应的元素已经到B里面了
        C[nums[i]-minNum]-=1
    return B

10基数排序

基本思想:

按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。

def radix_sort(nums):
    bucket = [[], [], [], [], [], [], [], [], [], []] #can not use [[]]*10
    bucket1 = [[], [], [], [], [], [], [], [], [], []]
    for i in nums:
        bucket[i%10].append(i)
    lst1 = []
    for b in bucket:
        lst1.extend(b)
    for i in lst1:
        index=int(i/10%10)
        bucket1[index].append(i)
    lst2 = []
    for b in bucket1:
        lst2.extend(b)
    return lst2


一些参考链接:

排序可视化 https://visualgo.net/en/sorting

排序算法复杂度速查表 https://linux.cn/article-7480-1.html

常见排序算法的分析及实现 

https://blog.csdn.net/qq_33414271/article/details/78528891

https://blog.csdn.net/qq_33414271/article/details/79129353




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值