排序算法 Day08

快速排序 

选定一个值作为pivot,用于比较数组中的值,比pivot小放在左边,大在右边,一般pivot选数组中间的一个数。

主要分为两部分,一部分是选取pivot值 进行比较和排序。在这一部分需要注意的是:开始时将pivot和nums【0】的值交换,便于遍历。结尾需要换回来;第二点是partition的返回值是pivot对应的下标,用于递归调用。

第二部分是递归,终止条件是quicksort的参数low=high。

class Solution:
    def partition(self,nums:list[int],low:int,high:int)->int:
        i = (high-low)//2+low
        nums[i],nums[low]=nums[low],nums[i]
        pivot=nums[low]
        i,j=low,high
        while i <j:
            while i<j and nums[j]>=pivot:
                j-=1
            while i<j and nums[i]<=pivot:
                i+=1
            nums[i],nums[j]=nums[j],nums[i]
        nums[low],nums[i]=nums[i],nums[low]
        return i
        
    def quicksort(self,nums:list[int],low:int,high:int)->list[int]:
        if low<high :
            pivot_i=self.partition(self,nums,low,high)
            self.quicksort(self,nums,low,pivot_i-1)
            self.quicksort(self,nums,pivot_i,high)

            return nums
        
score=[4,3,76,86,42,45,9,0,1]
a=Solution
print(a.quicksort(a,score,0,len(score)-1))

堆排序:

需要先明确一下定义:

堆(Heap):一种满足以下两个条件之一的完全二叉树:

        大顶堆(MaxHeap):任意节点值≥其子节点值。 

        小顶堆(MinHeap):任意节点值≤其子节点值。

堆结构是一棵完全二叉树,

如果某二叉树节点(非叶子节点)的下标为𝑖,那么其左孩子节点下标为2×𝑖+1,右孩子节点 下标为2×𝑖+2。

• 如果某二叉树节点(非根结点)的下标为𝑖,那么其根节点下标为⌊𝑖−1 2 ⌋(向下取整)。

关于堆排序的理解:第一步遍历一趟非叶节点保证父节点大于子节点,构建大顶堆。

第二步:交换堆顶和堆底元素,堆长度减一,重新堆化

def heapify(arr:list[int],n:int,i:int):
    #传入数组arr,n为数组长度,i为当前堆化的非叶节点对应的下标
    maxi=i
    l=2*i+1
    r=2*i+2
    
    if l<n and arr[l]>arr[maxi]:
        maxi=l
    if r<n and arr[r]>arr[maxi]:
        maxi=r
    if  maxi!=i:
        arr[i],arr[maxi]=arr[maxi],arr[i]
        heapify(arr,n,maxi)
def heap_sort(arr:list[int])->list[int]:
    n=len(arr)
    for i in range((n-2)//2,-1,-1):
        heapify(arr,n,i)
    for i in range(n-1,0,-1):
        arr[i],arr[0]=arr[0],arr[i]
        heapify(arr,i,0)
    return arr

print(heap_sort([1,4,32,43,7,9,66,62,11]))

计数排序:使用count记录每个值出现的次数,进行排序,比较巧妙的是最后给结果数组赋值的写法。

    for num in arr:
        output[count[num - min_val] - 1] = num
        count[num - min_val] -= 1

def counting_sort(arr):
    if not arr:  # 处理输入数组为空的情况
        return []
    max_val = max(arr)  # 找到数组中的最大值
    min_val = min(arr)  # 找到数组中的最小值
    range_of_elements = max_val - min_val + 1  # 计算元素范围
    count = [0] * range_of_elements  # 初始化计数数组,存储每个元素出现的次数
    output = [0] * len(arr)  # 存储排序结果的数组
    # 统计每个元素出现的次数
    for num in arr:
        count[num - min_val] += 1
    # 计算累计计数,用于确定元素在排序数组中的位置
    for i in range(1, range_of_elements):
        count[i] += count[i - 1]
    # 将元素放到输出数组的正确位置
    for num in arr:
        output[count[num - min_val] - 1] = num
        count[num - min_val] -= 1

    return output

# 示例
if __name__ == "__main__":
    arr = [4, 2, 2, 8, 3, 3, 1]
    print(counting_sort(arr))

 基数排序:依次从低到高对每一位遍历,进行排序。

其中的buckets 是十个数组,每个数组对应当前为0-9的位。

如果想看基数排序的具体过程可以参考这篇博客,gif很具体了:超详细八大排序+基数排序(图文并茂+动图演示+C语言代码演示)_基数排序例子-优快云博客

class Solution:
    def radixSort(self,nums:list[int])->list[int]:
        size=len(str(max(nums)))

        #逐位遍历
        for i in range(size):
            buckets=[[] for _ in range(10)]
            for num in nums:
                buckets[num//(10**i)%10].append(num)
            nums.clear()

            for bucket in buckets:
                for num in bucket:
                    nums.append(num)
        return nums
    
a=[231,464,123,543,901,800,644,299]
b=Solution
b.radixSort(b,a)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值