C语言实现快排算法

5 篇文章 0 订阅

写在前面

       快速排序在排序算法中算是效率较高的算法之一,快排也经常被采用,在工作面试、考研都有可能会遇到。我在初学快排的时候基本是复制粘贴别人的代码,不能理解快排是怎么实现的,最近重新看了看快排算法的思想,尝试写了快排算法,虽然碰到几个问题,但是最后基本能写出来了。在这里把我碰到的问题和我的想法写一写。

快排基本思想

       快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。

该方法的基本思想是:

  1. 先从数列中取出一个数作为基准数。

  2. 分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。

  3. 再对左右区间重复第二步,直到各区间只有一个数。

快排算法实现

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAXSIZE 100

void quicksort(int *, int, int);

int main()
{
    int data[MAXSIZE];
    time_t t;
    srand((unsigned)time(&t));
    // 随机生成20个数
    for(int i=1;i<=20;i++)
    {
        data[i] = rand() % 100;
    }
    for(int i=1;i<=20;i++)
    {
        printf("%d ", data[i]);
    }
    printf("\n");
    // 快排
    quicksort(data, 1, 20);
    for(int i=1;i<=20;i++)
    {
        printf("%d ", data[i]);
    }
    printf("\n");
    return 0;
}

void quicksort(int *data, int start, int end)
{
    // 其实快排中不必要每次取start和end的中间值,这样做增加理解难度,而且容易忘掉data[mid] = data[start];这句代码
    int mid = (start + end) / 2;
    int temp = data[mid]; // 如果比较的基准值使用数组中间位置的数,那么必须要有下面的一句
    data[mid] = data[start]; // 没有这一句会出现数组中数值错乱
    int i = start, j = end;
    while(i < j)
    {
        // 下面的data[j]必须要写成>=temp,不能写成>,如果写>会发生死循环,会出现在data[j]==temp时
        // >=也是导致快排不稳定的原因
        while(i < j && data[j] >= temp)
            j--;
        data[i] = data[j];
        while(i < j && data[i] <= temp)
            i ++;
        data[j] = data[i];
    }
    data[i] = temp;
    if(start < i - 1)
        quicksort(data, start, i-1);
    if (i + 1 < end)
        quicksort(data, i+1, end);
}

碰到的问题和我的一些想法

  1. 我设置了基准值为start和end的中点的数据,但是在排完序之后出现很多数据被替换掉。对应的错误写法。
void quicksort(int *data, int start, int end)
{
    int mid = (start + end) / 2;
    int temp = data[mid]; // 如果比较的基准值使用数组中间位置的数,那么必须要有下面的一句
    int i = start, j = end;
    while(i < j)
    {
        // 下面的data[j]必须要写成>=temp,不能写成>,如果写>会发生死循环,会出现在data[j]==temp时
        // >=也是导致快排不稳定的原因
        while(i < j && data[j] >= temp)
            j--;
        data[mid] = data[j];
        while(i < j && data[i] <= temp)
            i ++;
        data[j] = data[i];
    }
    data[i] = temp;
    if(start < i - 1)
        quicksort(data, start, i-1);
    if (i + 1 < end)
        quicksort(data, i+1, end);
}

       首先,代码12行就会造成数据丢失。循环里面每次都会修改data[mid]的值,而没有保存data[mid]的数据,导致出现丢失。实际应该做的是每次修改的都是下标为 i 和 j 位置的值,除了第一次修改data[i],每次修改data[i]时,data[j]会保存住data[i]的值,同理修改data[j]的值时,data[i]会保存住data[j]的值。

  1. 虽然设置了基准值为start和end的中点的数据,while循环内的复制也只涉及到data[i]和data[j],但是会造成数据丢失。错误写法为:
void quicksort(int *data, int start, int end)
{
    int mid = (start + end) / 2;
    int temp = data[mid]; // 如果比较的基准值使用数组中间位置的数,那么必须要有下面的一句
    int i = start, j = end;
    while(i < j)
    {
        // 下面的data[j]必须要写成>=temp,不能写成>,如果写>会发生死循环,会出现在data[j]==temp时
        // >=也是导致快排不稳定的原因
        while(i < j && data[j] >= temp)
            j--;
        data[i] = data[j];
        while(i < j && data[i] <= temp)
            i ++;
        data[j] = data[i];
    }
    data[i] = temp;
    if(start < i - 1)
        quicksort(data, start, i-1);
    if (i + 1 < end)
        quicksort(data, i+1, end);
}

       还是第12行导致的错误。每次调用quicksort函数的时候,第一次要修改的data[i]的值没有保存住,都会丢失。

文中都是我个人的理解,如有错误的地方欢迎下方评论告诉我,我及时更正,大家共同进步

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值