【C】对快速排序与归并排序的一些感悟

深入理解快速排序与归并排序

前言

学过算法与数据结构的人都知道,几乎所有教程都会讲排序,然而实际编程中并不会真正的手写排序算法,慢慢的大家是否会产生疑问,是不是只要了解各种排序算法的特点就好,不必过分执着于代码,然而最近,我对此有了更深刻的认识。
各种排序算法,实际深层次代表了不同的编程思想,并且好的实现方式,还运用了一些有用的编程技巧,这才是实际学习过程中真正需要掌握的东西,比如二分、递归等等。
细细把玩之后,会产生一种看山是山 看山不是山 看山还是山的感觉。

首先,对于各种排序算法,网上有非常多的教程,在此我就不多说了,没有看过的同学可以看下【十大经典排序算法】
下面我主要讲下我对快速排序与递归排序的一些感悟。

快速排序

这里用了一种递归的实现方式,关键点都在注释里了。

void swap(int *x, int *y) {
    int t = *x;
    *x = *y;
    *y = t;
}
void QuickSort(int *arr, int start, int end) 
{
    if (start >= end) {		// 一半递归的退出条件可以放在最后写,好的退出条件可以简化代码,但是可能会多一次递归调用,个中细节,自己写下就知道。
        return;
    }
    int left = start;
    int right = end - 1;
    int privot = arr[end];	// 此处选最后一个数作为分隔点,实际privot的选取有很多种方法,好的方案能产生一定优化作用。
    while (left < right) {	// 经典双指针循环
        while (left < right && arr[left] < privot)
            left++;
        while (left < right && arr[right] >= privot)
            right--;
        swap(&arr[left], &arr[right]);
    }
    // 此处对循环跳出后做处理,处理一些边界情况,必要时可以在循环中加flag 
    if (arr[left] >= privot) {          // 调整privot的位置,只要保证小于privot的在同一边,大于的在另一边即可
        swap(&arr[left], &arr[end]);
    } else {
        left++;                         // 此处对应left 一直左移到right,且当前left小于privot,则令left指向end
    }
    QuickSort(arr, start, left-1);	// 递归调用,一般写到这,递归头部的退出条件便水到渠成
    QuickSort(arr, left + 1, end);
}
// 借用力扣 912 题做验证 
// https://leetcode-cn.com/problems/sort-an-array/
int* sortArray(int* nums, int numsSize, int* returnSize){
    *returnSize = numsSize;
    int *relt = (int *)malloc(sizeof(int) * numsSize);
    for (int i = 0; i < numsSize; i++) {
        relt[i] = nums[i];
    }
    QuickSort(relt, 0, numsSize-1);
    return relt;
}

归并排序

void Merge(int *arr, int start, int mid, int end)
{
    int *tmpArr = (int *)malloc(sizeof(int) * (end - start + 1));
    int ptr1 = start;
    int ptr2 = mid + 1;
    int ptr = 0;
    while (ptr1 <= mid && ptr2 <= end){
        if (arr[ptr1] > arr[ptr2]) {
            tmpArr[ptr++] = arr[ptr2];
            ptr2++;
        } else if (arr[ptr1] <= arr[ptr2]) {
            tmpArr[ptr++] = arr[ptr1];
            ptr1++;
        }
    }
    while (ptr1 <= mid) {		// 处理上面循环的尾巴
        tmpArr[ptr++] = arr[ptr1++];
    }
    while (ptr2 <= end) {
        tmpArr[ptr++] = arr[ptr2++];
    }
    for (int i = start; i <= end; i++) {
        arr[i] = tmpArr[i - start];
    }
    return;
}

void MergeSort(int *arr, int start, int end)
{
    if (start >= end) {
        return;
    }
    // 分
    int mid = (start + end) / 2;
    MergeSort(arr, start, mid);
    MergeSort(arr, mid + 1, end);
    // 如果解决一个问题,使用两个有序序列可以很快解决,那么,可以在此加入处理代码
    // 合
    Merge(arr, start, mid, end);
}
int* sortArray(int* nums, int numsSize, int* returnSize){
    *returnSize = numsSize;
    int *relt = (int *)malloc(sizeof(int) * numsSize);
    for (int i = 0; i < numsSize; i++) {
        relt[i] = nums[i];
    }
    MergeSort(relt, 0, numsSize-1);
    return relt;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值