堆排序,归并排序和快速排序

一,堆排序,可以用来解决优先队列,topk等问题

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        def heapsort(nums):
            len_nums = len(nums)
            # 建堆过程,也可以理解为向上调整的过程
            for i in range(len_nums//2-1, -1, -1):
                adjust_heap(nums, i, len_nums)
            # 向下调整的过程
            for j in range(len_nums-1, 0, -1):
                nums[0], nums[j] = nums[j], nums[0]
                adjust_heap(nums, 0, j)    

        def adjust_heap(target_list, target_i, target_len):
            # 获取左孩子结点索引
            k = 2*target_i + 1
            tmp = nums[target_i]
            while k < target_len:
                # 如果右孩子大,则变到右孩子处,保证最后放到i位置的是三者最大
                if k+1 < target_len and nums[k+1] > nums[k]:
                    k += 1
                if tmp <target_list[k]:
                    target_list[target_i] = target_list[k]
                    target_i = k
                else:
                    break
                k = 2*k +1
            target_list[target_i] = tmp

        heapsort(nums)
        return nums

二,归并排序 = 归并排序左半边+归并排序右半边+合并两边

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        def mergesort(nums):
            len_nums = len(nums)
            if len_nums <= 1:
                return nums
            mid = len_nums//2
            A = mergesort(nums[:mid])
            B = mergesort(nums[mid:])
            return merge(A, B)
        def merge(A, B):
            C = []
            while A and B:
                if A[0] < B[0]:
                    C.append(A.pop(0))
                else:
                    C.append(B.pop(0))
            while A:
                C.append(A.pop(0))
            while B:
                C.append(B.pop(0))
            return C
        return mergesort(nums)

三,快速排序 = partition分割两边 + 快速排序左半边 + 快速排序右半边

partition思路,设置“小于等于区域”,初始时设置此区域指针i为low-1,基准值为high上的元素,遍历low到high索引上的值,遍历指针j对应的元素小于等于基准值时,区域指针加1,然后交换二者,否则继续遍历。

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        def partition(nums, low, high):
            i = low - 1
            pivot = nums[high]
            for j in range(low, high+1):
                if nums[j] <= pivot:
                    i += 1
                    nums[i], nums[j] = nums[j], nums[i]
            return i

        def quicksort(nums, low, high):
            if low < high:
                pi = partition(nums, low, high)
                quicksort(nums, low, pi-1)
                quicksort(nums, pi+1, high)
        len_nums = len(nums)
        if len_nums <= 1:
            return nums
        quicksort(nums, 0, len(nums)-1)
        return nums
        

 

四,随机快速排序,每次基准值由random决定,摇出随机索引后与最后一个元素交换

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        def partition(nums, low, high, pivot):
            l = low - 1
            r = high + 1
            h = low
            while h < r:
                if nums[h] < pivot:
                    l += 1
                    nums[l], nums[h] = nums[h], nums[l]
                    h += 1
                elif nums[h] == pivot:
                    h += 1
                else:
                    r -= 1
                    nums[r], nums[h] = nums[h], nums[r]
            return l+1,r-1

        def quicksort(nums, low, high):
            if low < high:
                pivot = random.randint(low,high)
                pi_l, pi_r = partition(nums, low, high, nums[pivot])
                quicksort(nums, low, pi_l-1)
                quicksort(nums, pi_r+1, high)
        len_nums = len(nums)
        if len_nums <= 1:
            return nums
        quicksort(nums, 0, len(nums)-1)
        return nums

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您解答这个问题。 首先,堆排序快速排序归并排序和计数排序都是常见的排序算法,它们的实现方式各不相同。下面分别介绍它们的C++实现。 1. 堆排序(Heap Sort) 堆排序是一种选择排序,它利用堆的性质进行排序。堆是一个完全二叉树,其中每个节点的值都大于或等于其子节点的值(最大堆),或者小于或等于其子节点的值(最小堆)。在堆排序中,我们将待排序数组构建成一个最大堆,然后将堆顶元素(即最大值)与数组最后一个元素交换,然后重新调整堆,重复执行此操作,直到整个数组有序。 下面是堆排序的C++实现: ```c++ void heapify(int arr[], int n, int i) { int largest = i; // 初始化最大值为根节点 int l = 2 * i + 1; // 左子节点索引 int r = 2 * i + 2; // 右子节点索引 // 如果左子节点比最大值大,则更新最大值索引 if (l < n && arr[l] > arr[largest]) largest = l; // 如果右子节点比最大值大,则更新最大值索引 if (r < n && arr[r] > arr[largest]) largest = r; // 如果最大值不是根节点,则交换根节点和最大值,然后递归调整堆 if (largest != i) { swap(arr[i], arr[largest]); heapify(arr, n, largest); } } void heapSort(int arr[], int n) { // 构建最大堆 for (int i = n / 2 - 1; i >= 0; i--) heapify(arr, n, i); // 依次取出堆顶元素,放到数组末尾,并重新调整堆 for (int i = n - 1; i >= 0; i--) { swap(arr[0], arr[i]); heapify(arr, i, 0); } } ``` 2. 快速排序(Quick Sort) 快速排序是一种分治排序,它利用分治的思想将大问题分解成小问题,然后递归地解决小问题。在快速排序中,我们选择一个枢轴元素(一般选择第一个元素),将数组分为两个部分,左边部分的元素均小于枢轴元素,右边部分的元素均大于枢轴元素。然后分别对左右两部分递归执行此操作,直到整个数组有序。 下面是快速排序的C++实现: ```c++ int partition(int arr[], int low, int high) { int pivot = arr[low]; // 枢轴元素 int i = low, j = high; while (i < j) { // 从右往左找第一个小于枢轴元素的位置 while (i < j && arr[j] >= pivot) j--; // 从左往右找第一个大于枢轴元素的位置 while (i < j && arr[i] <= pivot) i++; // 交换左右两个元素 if (i < j) swap(arr[i], arr[j]); } // 将枢轴元素放到正确的位置上 arr[low] = arr[i]; arr[i] = pivot; return i; } void quickSort(int arr[], int low, int high) { if (low < high) { int pivot = partition(arr, low, high); quickSort(arr, low, pivot - 1); quickSort(arr, pivot + 1, high); } } ``` 3. 归并排序(Merge Sort) 归并排序也是一种分治排序,它将待排序数组分成两部分,分别排序,然后合并成一个有序数组。在归并排序中,我们先将数组分为两半,分别对左半部分和右半部分递归执行归并排序,然后将两个有序子数组合并成一个有序数组。 下面是归并排序的C++实现: ```c++ void merge(int arr[], int l, int m, int r) { int n1 = m - l + 1; int n2 = r - m; // 创建临时数组 int L[n1], R[n2]; // 将左半部分复制到临时数组 L for (int i = 0; i < n1; i++) L[i] = arr[l + i]; // 将右半部分复制到临时数组 R for (int i = 0; i < n2; i++) R[i] = arr[m + 1 + i]; // 合并左右两个有序子数组 int i = 0, j = 0, k = l; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } // 将剩余的元素复制到数组中 while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } } void mergeSort(int arr[], int l, int r) { if (l < r) { int m = l + (r - l) / 2; mergeSort(arr, l, m); mergeSort(arr, m + 1, r); merge(arr, l, m, r); } } ``` 4. 计数排序(Counting Sort) 计数排序是一种非比较排序,它利用元素出现的次数来确定每个元素在有序数组中的位置。在计数排序中,我们先统计每个元素出现的次数,然后计算每个元素在有序数组中的位置,最后将元素放到正确的位置上。 下面是计数排序的C++实现: ```c++ void countingSort(int arr[], int n) { int max_val = 0; for (int i = 0; i < n; i++) { if (arr[i] > max_val) max_val = arr[i]; } // 创建计数数组 int count[max_val + 1] = {0}; // 统计每个元素出现的次数 for (int i = 0; i < n; i++) count[arr[i]]++; // 计算每个元素在有序数组中的位置 for (int i = 1; i <= max_val; i++) count[i] += count[i - 1]; // 将元素放到正确的位置上 int output[n]; for (int i = n - 1; i >= 0; i--) { output[count[arr[i]] - 1] = arr[i]; count[arr[i]]--; } // 将有序数组复制到原数组中 for (int i = 0; i < n; i++) arr[i] = output[i]; } ``` 以上就是堆排序快速排序归并排序和计数排序的C++实现,希望能对您有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值