几个基础排序算法 学习笔记

这两天把几个基础排序算法捋了捋,做个记录。
堆排序是不稳定的,其他取决于判断条件有无 =

冒泡

def maopao(nums): #冒泡,时间O(n^2),空间O(1)
    def help(start, end):
        for i in range(end, start,-1):
            if lst[i] < lst[i - 1]:
                #print(lst[i - 1], lst[i])
                # 交换位置 ( 严格小于才交换位置,稳定的)
                lst[i - 1], lst[i] = lst[i], lst[i - 1]
                #print(lst[i - 1], lst[i])
    for i in range(len(nums) - 1):
        help(i, len(nums) - 1)
    return nums

选择

def select(nums): #选择排序,时间O(n^2),空间O(1)
    for i in range(len(nums)-1):
        min_ = i
        for j in range(i+1,len(nums)):
            if nums[j]<nums[min_]: #稳定的
                min_=j
        nums[i], nums[min_] = nums[min_],nums[i]
    return nums

插入

def insert(nums): #插入排序,时间O(N**2),空间(1)原地修改
    #最差的情况,第k轮需要比较k-1次,1+2+..+n-1 时间O(N**2)
    size =len(nums)
    for i in range(1,size):
        j = i#后面无序数组的start
        while j>0:
            if nums[j]<nums[j-1]: #前面为有序数组,稳定的
                nums[j],nums[j-1]= nums[j-1],nums[j]
            else:
                break
            j-=1
    return nums

折半插入排序

二分查找法,边界最容易错,最好把 tmp == nums[mid] 单独拿出来吧,不容易乱,
low<=high 和 low= mid+1,high = mid-1 必须匹配的,
如果 high=mid 或者 low = mid 就会陷入死循环

#插入排序+二分查找法,在有序序列中寻找插入位置时,使用二分查找
def binaryInsert(nums):
    size = len(nums)
    for i in range(1,size):
        tmp = nums[i]
        low = 0
        high = i-1
        while low<=high: 
            mid = low + (high-low)//2 #左中位数
            if tmp == nums[mid]:
                low = mid+1
                break
            if tmp>nums[mid]:
                low= mid+1
            else:
                high = mid-1
        for j in range(i,low,-1):
            nums[j] = nums[j-1]
        nums[low] = tmp #最终确定的位置在low
    return nums

希尔排序

#希尔排序: 做间隔插入排序, 间隔递减, 最后间隔为1, 不稳定的!
def shellSort(nums):
    size= len(nums)
    gap = size//2
    while gap:
        for i in range(size-1,gap-1,-1):
            tmp = nums[i]
            j = i
            while j-gap>=0 and nums[j-gap]>nums[j]:
                nums[j] = nums[j-gap]
                j-=gap
            nums[j] = tmp
        gap= gap//2
    return nums

堆排序

def heapSort(nums):
    def shiftDown(root,end):
        child = 2*root+1
        while child<=end:
            if child+1<=end and nums[child+1]> nums[child]:
                child+=1
            if nums[child]> nums[root]:
                nums[root],nums[child] = nums[child],nums[root]
            else:
                break
            root = child
            child = 2 * root+1
    size = len(nums)
    start = size//2-1
    # 构建
    for i in range(start,-1,-1):
        shiftDown(i, size-1)
    #递增 排序
    for i in range(size-1,0,-1):
        nums[i],nums[0] = nums[0],nums[i]
        shiftDown(0,i-1)
    return nums

归并

def merge(left_arr,right_arr):
    result = []
    l,r = 0,0
    while l<len(left_arr) and r<len(right_arr):
        if left_arr[l]<=right_arr[r]: #这里加上=是稳定的,不加是不稳定的
            result.append(left_arr[l])
            l+=1
        else:
            result.append(right_arr[r])
            r+=1
    if l==len(left_arr): result+=right_arr[r:]
    else: result+= left_arr[l:]
    return result
def mergeSort(nums): #空间O(N),未必稳定,时间O(nlogn),递推写法
    step = 1
    size = len(nums)
    while step*2 <=size:
        for i in range(0,size,2*step):
            if i+2*step < size:
                nums[i:i+2*step] = merge(nums[i:i+step],nums[i+step:i+2*step])
        if i+step<size: 
            nums[i:]= merge(nums[i:i+step],nums[i+step:])
        step *= 2
    if step <size:
        return merge(nums[:step],nums[step:])
    else:
        return nums
    #递归,递推
def mergeSort2(nums): #空间O(N),未必稳定,时间O(nlogn),  递归写法
    if len(nums)<2: #递归边界
        return nums
    mid = len(nums)//2 #右中位数
    left = mergeSort2(nums[:mid])
    right = mergeSort2(nums[mid:])
    return merge(left,right)

快排

def quickSort(nums): #时间O(nlogn)空间? 不太清楚,递归栈应该会用
    #只能自顶向下,分治递归:递归式,停止条件
    def partition(left, right):
        mid = left + (right - left) // 2
        nums[mid], nums[right] = nums[right], nums[mid]
        store_index = left
        for i in range(left, right):
            if nums[i] < nums[right]: #没有=,是稳定的
                nums[i], nums[store_index] = nums[store_index], nums[i]
                store_index += 1
        nums[store_index], nums[right] = nums[right], nums[store_index]
        return store_index
    if len(nums)<2:
        return nums
    pivot = partition(0,len(nums)-1)
    nums[:pivot]= quickSort(nums[:pivot])
    nums[pivot+1:]= quickSort(nums[pivot+1:])
    return nums

如有错误,还请指正~

ps: 今天晚上看了切片,可是可劲用切片了…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值