计数排序(C语言版)

先说说计数排序的思想

计数排序假定待排序的所有元素都是介于0到K之间的整数;计数排序使用一个额外的数组countArray,其中第i个元素是待排序数组array中值等于i的元素的个数。然后根据数组countArray来将array中的元素排到正确的位置。

算法的步骤如下:

  1. 找出待排序的数组中最大和最小的元素
  2. 统计数组中每个值为i的元素出现的次数,存入数组countArray的第i
  3. 对所有的计数累加(从countArray中的第一个元素开始,每一项和前一项相加)
  4. 反向填充目标数组:将每个元素i放在新数组的第countArray[i]项,每放一个元素就将countArray[i]减去1

稳定性和复杂度:

计数排序是稳定的排序算法;平局时间复杂度、最优时间复杂度和最差时间复杂度都为O(n+k),空间复杂度为O(n+k),其中,n为待排元素个数,k为待排元素的范围(0~k)。

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

#define RANDMAX 10000

void getRandArray(int array[], int size);
void countSort(int array[], int size);
void isSorted(int array[], int size);

int main(int argc, char const *argv[])
{
    int size = 0;
    scanf("%d", &size);
    assert(size > 0);

    int *array = (int *)calloc(size, sizeof(int));
    getRandArray(array, size);

    clock_t begin;
    clock_t end;

    begin = clock();
    countSort(array, size);
    end = clock();
    //打印排序所花费的时间,在linux下单位为ms
    printf("%ld\n", (end - begin) / 1000);

    isSorted(array, size);
    free(array);

    return 0;
}

//利用伪随机数填充数组array
void getRandArray(int array[], int size)
{
    assert(array != NULL && size > 0);

    srand((unsigned) time(NULL));
    int i = 0;
    for (i = 0; i < size; ++i) {
        //产生RANDMAX以内的伪随机数
        array[i] = rand() % RANDMAX;
    }
}

//从小到大进行排序
void countSort(int array[], int size)
{
    assert(array != NULL && size > 0);

    //计数数组,用于统计数组array中各个不同数出现的次数
    //由于数组array中的数属于0...RANDMAX-1之间,所以countArray的大小要够容纳RANDMAX个int型的值
    int *countArray = (int *) calloc(RANDMAX, sizeof(int));
    //用于存放已经有序的数列
    int *sortedArray = (int *) calloc(size, sizeof(int));

    //统计数组array中各个不同数出现的次数,循环结束后countArray[i]表示数值i在array中出现的次数
    int index = 0;
    for (index = 0; index < size; ++index) {
        countArray[array[index]]++;
    }

    //统计数值比index小的数的个数,循环结束之后countArray[i]表示array中小于等于数值i的元素个数
    for (index = 1; index < RANDMAX; ++index) {
        countArray[index] += countArray[index - 1];
    }

    for (index = size - 1; index >= 0; --index) {
        //因为数组的起始下标为0,所以要减一
        sortedArray[countArray[array[index]] - 1] = array[index];
        //这里减一是为了保证当有多个值为array[index]的元素时,后出现的值为array[index]的元素
        //放在后面,也就是为了保证排序的稳定性
        --countArray[array[index]];
    }

    memcpy(array, sortedArray, size * sizeof(int));
    free(sortedArray);
    free(countArray);
}

//判断数组array是否已经是有序的
void isSorted(int array[], int size)
{
    assert(array != NULL && size > 0);

    int unsorted = 0;
    int i = 0;
    for (i = 1; i < size; ++i) {
        if (array[i] < array[i - 1]) {
            unsorted = 1;
            break;
        }
    }

    if (unsorted) {
        printf("the array is unsorted!\n");
    } else {
        printf("the array is sorted!\n");
    }
}

计数排序是非比较的排序算法,据说其排序速度要快于任何的比较排序算法(我还未验证,但是在排序100000000个10000以内的数时花费为606毫秒,而C语言的qsort函数则为10802毫秒,由此可见一斑),由于计数排序需要一个计数数组以及一个存放有序数列的数组,故计数排序对内存的要求比较高。

时间: 2024-10-25 17:37:19

计数排序(C语言版)的相关文章

计数排序C语言实现

计数排序是稳定排序,而且是线性时间内的排序算法,时间复杂度是O(n + k)其中k是待排序数组的范围.计数排序不是原址排序,空间复杂度是O(n + k) //k是指A中的数组范围是0~k 包括0和k void count_sort(int A[], int B[], int n, int k) { int *C = (int *)malloc(sizeof(int) * (k + 1)); int i; for(i = 0; i <= k; i++) { C[i] = 0; } for(i =

常见的9种内部排序(C语言实现)

现在已经把常见的9种内部排序算法都用C语言实现了,为了方便自己和大家查看,就弄了这么一个类似于导航目录的东西. 一.冒泡排序 冒泡排序(C语言版) 二.选择排序 选择排序(C语言版) 三.直接插入排序 直接插入排序(C语言版) 四.希尔排序 希尔排序(C语言版) 五.归并排序 归并排序(C语言版) 六.基数排序 基数排序(C语言版) 七.快速排序 快速排序(C语言版) 八.计数排序 计数排序(C语言版) 九.堆排序 堆排序(C语言版) 介绍完这九个常用的排序算法,怎么能没有一个比较呢?下面是我对

排序算法总结(C语言版)

1.    插入排序 1.1     直接插入排序 1.2     Shell排序 2.    交换排序 2.1     冒泡排序 2.2     快速排序 3.    选择排序 3.1     直接选择排序 3.2     堆排序 4.    归并排序 4.1     二路归并排序 4.2     自然合并排序 5.    分布排序 5.1     基数排序 1.插入排序 1.1      直接插入排序 将已排好序的部分num[0]~num[i]后的一个元素num[i+1]插入到之前已排好序的

3203 数组做函数参数----排序函数--C语言版

3203: 数组做函数参数----排序函数--C语言版 时间限制: 1 Sec  内存限制: 128 MB提交: 253  解决: 151[提交][状态][讨论版][命题人:smallgyy] 题目描述 定义一个函数来完成对参数数组中元素的排序工作,函数声明如下: void sort(int array[ ]);//该函数完成对array数组的排序工作 在以下程序的基础上,完成对sort函数的定义,提交时,只提交sort函数的定义即可. #include <stdio.h> void sort

计数排序及C语言实现

之前讨论的插入排序.归并排序.堆排序和快速排序都是基于比较的排序算法,对于所有的比较排序算法,其复杂度最优也要O(nlgn).证明过程请参考算法导论第八章第一节. 今天介绍一种非比较排序,名为计数排序. 基本思想是:对于每一个元素,确定小于该元素的个数,就可以将该元素排在正确的位置.该算法能达到线性时间复杂度,也就是O(n). 程序中,数组a为输入数组(未排序数组),b为输出数组,c为中间数组.20的意思是假设数组中每个元素均为小于20的非负整数.

计数排序算法——时间复杂度O(n+k)

计数排序 计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出.它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法. 算法思想 计数排序对输入的数据有附加的限制条件: 1.输入的线性表的元素属于有限偏序集S: 2.设输入的线性表的长度为n,|S|=k(表示集合S中元素的总数目为k),则k=O(n). 在这两个条件下,计数排序的复杂性为O(n). 计数排序的基本思想是对于给定的输入序列中的每一个元

什么是计数排序?[转]

来源https://www.cnblogs.com/kyoner/p/10604781.html 有这样一道排序题:数组里有20个随机数,取值范围为从0到10,要求用最快的速度把这20个整数从小到大进行排序. 第一时间你可能会想使用快速排序,因为快排的时间复杂度只有O(nlogn).但是这种方法还是不够快,有没有比O(nlogn)更快的排序方法呢?你可能会有疑问:O(nlogn)已经是最快的排序算法了,怎么可能还有更快的排序方法? 让我们先来回顾一下经典的排序算法,无论是归并排序,冒泡排序还是快

人事管理系统 c语言版

int menu(){ printf("请按提示输入完成操作!\n"); printf("1.查询员工信息\n"); printf("2.统计员工数量\n"); printf("3.录入员工信息\n"); printf("4.删除员工信息\n"); printf("5.按id排序所有员工\n"); printf("6.打印所有员工信息\n"); printf(&quo

计数排序的理解和代码实现

由决策树模型可知,比较排序最坏情况的下届要比较nlgn次,不是线性排序的.所以,在算法导论中提出了几种线性排序,其中计数排序就是一种.下面总结一下计数排序的原理: 假设n个输入元素中的每一个元素都是在[0,..,k]内的整数.设输入数组为A[n]:输出数组为B[n]:临时存储数组为C[k].算法如下: 1.把C[k]中的元素全部置0. 2.统计A中含有元素i的个数(i={0,...,k-1}),并存储在C[i]中. 3.统计A中小于等于i的元素的个数(i={0,...,k-1}),并存储在C[i