数据结构之快速排序

本文详细介绍了快速排序算法的工作原理,包括其分组递归的过程,并通过示例代码展示了如何实现快速排序,同时给出了不同数据类型的排序示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面介绍了三种排序算法:冒泡排序,插入排序以及选择排序,这篇文章介绍最常用的排序算法,快速排序

快速排序即从待排序序列中任意选择一个元素,作为基准,然后将多有小于基准的元素放在基准之前,大于基准的元素放在基准之后,等于基准的元素随意,这个过程为分组,再以递归的方式分别对基准之前和基准之后的分组继续进行分组,直到每个分组内的元素个数不多于一个为止

下面给出一个快速排序的接口:

void qsort(int data[], int left, int right)
{
    int i;
    int j;
    int temp;
    int swap = 0;

    if(left > right)
    {
        return;
    }

    i = left;
    j = right;
    temp = data[left];
    while( i != j)
    {
        while(data[j] >= temp && i < j)
        {
            j--;
        }
        while(data[i] <= temp && i < j)
        {
            i++;
        }

        if(i < j)
        {
            swap = data[i];
            data[i] = data[j];
            data[j] = swap;
        }
    }

    data[left] = data[i];
    data[i] = temp;

    qsort(data, left, i - 1);
    qsort(data, i + 1, right);
}

平均时间复杂度:O(NlogN)
非稳定排序,如果每次都能均匀分组,则排序最快,而选择中间位置作为基准,产生均匀分组的概率最高。

快速排序在Linux下有一个封装好的函数:qsort

qsort(void* base, size_t nmemb, size_t size, int(*compar)(const void*, const void*))
参数:
1、任意类型数组的首地址
2、数组元素个数
3、数组元素字节数
4、比较函数指针

compar参数指向一个函数:
ex:int xxx(const void* a, const void* b);
if(a > b) return 正数
if(a < b) return 负数
if(a == b) return 0

值得一提的是这个函数可对任意事物进行排序,在比较字符串的时候需要使用strcmp函数。

下面给个用例:

/*********************************************************************************
 *      Copyright:  (C) 2017 tangyanjun<519656780@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  qsort.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(07/26/2017)
 *         Author:  tangyanjun <519656780@qq.com>
 *      ChangeLog:  1, Release initial version on "07/26/2017 07:40:40 PM"
 *                 
 ********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Student{
    char name[20];
    int age;
}STUDENT;

/* 自己写函数实现qsort */
void _myqsort(void* base, size_t left, size_t right, size_t size, int(*compar)(const void*, const void*))
{
    size_t p = (left + right) / 2;
    void* pivot = malloc(size);
    memcpy(pivot, base + p * size, size);
    size_t i = left;
    size_t j = right;
    while(i < j)
    {
        for(; !(i >= p || compar(pivot, base + i * size) < 0); ++i);
        if(i < p)
        {
            memcpy(base + p * size, base + i * size, size);  //内存拷贝
            p = i;
        }
        for(; !(j <= p || compar(base + j * size, pivot) < 0); --j);
        if(j > p)
        {
            memcpy(base + p * size, base + j * size, size);
            p = j;
        }
    }
    memcpy(base + p * size, pivot, size);
    free(pivot);
    if(p - left > 1)
    {
        _myqsort(base, left, p - 1, size, compar);
    }
    if(right - p > 1)
    {
        _myqsort(base, p + 1, right, size, compar);
    }
}

void myqsort(void* base, size_t nmemb, size_t size, int(*compar)(const void*, const void*))
{
    _myqsort(base, 0, nmemb - 1, size, compar);      
}

int stu_cmp(const void* a, const void* b)
{
    const STUDENT* pa = (const STUDENT*)a; 
    const STUDENT* pb = (const STUDENT*)b;
    int res = strcmp(pa->name, pb->name);  //先比较姓名大小
    if(!res)
    {
        return pa->age - pb->age;  //姓名大小一样,则按年龄升序
    }
    return -res;
}

int int_cmp(const void* a, const void* b)
{
    return *(const int*)b - *(const int*)a;
}

int str_cmp(const void* a, const void* b)   //字母的ASCII码值
{
    return strcmp(*(const char* const*)a, *(const char* const*)b);
}

int main(int argc, char **argv)
{
    int na[] = {55, 22, 33, 11, 44, 88, 99, 0, 77, 66};
    size_t size = sizeof(na[0]);
    size_t nmemb = sizeof(na) / size;
    qsort(na, nmemb, size, int_cmp);
    size_t i;
    for(i = 0; i < nmemb; ++i)
    {
        printf("%d ", na[i]);
    }
    printf("\n");

    const char* sa[] = {"beijing", "tianjin", "shanghai", "chongqing"};
    size = sizeof(sa[0]);
    nmemb = sizeof(sa) / size;
    qsort(sa, nmemb, size, str_cmp);
    for(i = 0; i < nmemb; ++i)
    {
        printf("%s ", sa[i]);
    }
    printf("\n");
    STUDENT ta[] = {
        {"zhangfei", 25},
        {"zhaoyun", 22},
        {"zhangfei", 20},
        {"zhaoyun", 23},
        {"guanyu", 50},
    };
    size = sizeof(ta[0]);
    nmemb = sizeof(ta) / size;
    qsort(ta, nmemb, size, stu_cmp);
    for(i = 0; i < nmemb; ++i)
    {
        printf("%s/%d ", ta[i].name, ta[i].age);
    }
    printf("\n");
    return 0;
}

结果:

[tangyanjun@VM_216_80_centos sort]$ gcc qsort.c 
[tangyanjun@VM_216_80_centos sort]$ a.out 
99 88 77 66 55 44 33 22 11 0 
beijing chongqing shanghai tianjin 
zhaoyun/22 zhaoyun/23 zhangfei/20 zhangfei/25 guanyu/50 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值