计数排序-很有意思的一种排序方法

首先,让我们了解什么是计数排序。
计数排序:
计数排序的基本思想是对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数(此处并非比较各元素的大小,而是通过对元素值的计数和计数值的累加来确定)。一旦有了这个信息,就可以将x直接存放到最终的输出序列的正确位置上。例如,如果输入序列中只有17个元素的值小于x的值,则x可以直接存放在输出序列的第18个位置上。当然,如果有多个元素具有相同的值时,我们不能将这些元素放在输出序列的同一个位置上,因此,上述方案还要作适当的修改。

排序过程:
假设输入的线性表L的长度为n,L=L1,L2,…,Ln;线性表的元素属于有限偏序集S,|S|=k且k=O(n),S={S1,S2,…Sk};则计数排序可以描述如下:

1、扫描整个集合S,对每一个Si∈S,找到在线性表L中小于等于Si的元素的个数T(Si);
2、扫描整个线性表L,对L中的每一个元素Li,将Li放在输出线性表的第T(Li)个位置上,并将T(Li)减1。

简单理解:
一个序列中有n个元素,通过序列中每一个元素小于其的元素的个数来确定另一个序列的下标,然后这个元素就是该下标上的值。当然这种情况下,你要考虑当这个序列有相同的元素应该怎么办?

好了,了解了以上内容来看看我写的代码吧!

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

#define DATASIZE 10

//要注意当有数据相等时,该函数会有问题!如何解决?
void CountSort(int arr1[],int arr2[])
{
    int count;
    int i,j;
    int temp = 0;
    int repe;

    while(temp < DATASIZE)
    {
        count = 0;
        repe = -1; 
        for(i = 0; i < DATASIZE; i++)
        {
            if(arr1[i] < arr1[temp])
            {
                count++;
            }
            //1.记录出现重复数字的次数,因当前循环会与自己比较。所以至少会有1次重复
            //要排除这种情况
            if(arr1[i] == arr1[temp])//记住要用==,而不是=,不要问我为什么知道的☹
            {
                repe++;
            }
        }
        // printf("调试:%d ",repe);

        if(repe > 0)//2.若出现重复数字,直接把下标count到count+repe数据替换为当前的数字
        {
            for(j = count; j <= count + repe; j++)
            {
                arr2[j] = arr1[temp];
            }               
        }else 
            arr2[count] = arr1[temp];
        temp++;       
    }

    for(i = 0; i < DATASIZE; i++ )
    {
        printf("%-2d ",arr2[i]);
    }
}

int main()
{
    srand(time(NULL));
    int arr1[DATASIZE];
    int arr2[DATASIZE];
    
    printf("未排序之前的数列:");
    for (int i = 0; i < DATASIZE; i++)
    {
        arr1[i] = rand()%100;
        printf("%-2d ",arr1[i]);
    }
    printf("\n");
    printf("已排序之后的数列:");
    CountSort(arr1,arr2);
    printf("\n");

    return 0;    

}

百度代码:

#include<stdio.h>
#include<stdlib.h>
 
#define MAXNUM 10
 
void main()
{
    void CountSort(int data[],int n);
    int i,data[MAXNUM];
    for(i=0;i<MAXNUM;i++)
        scanf("%d",&data[i]);
    CountSort(data,MAXNUM);
    for(i=0;i<MAXNUM;i++)
        printf("%d ",data[i]);
    printf("\n");
}
 
void CountSort(int data[],int n)
{
    int i,j,count,*data_p,temp;
    data_p=(int*)malloc(sizeof(int)*n);
    for(i=0;i<n;i++)//初始化data_p
        data_p[i]=0;
    for(i=0;i<n;i++)
    {
        count=0;
        for(j=0;j<n;j++)//扫描待排序数组
            if(data[j]<data[i])//统计比data[i]值小的值的个数
                count++;
        while(data_p[count]!=0)//对于相等非0的数据,应向后措一位。数据为0时,因数组data_p被初始化为0,故不受影响。
        /* 注意此处应使用while循环进行判断,若用if条件则超过三个重复值后有0出现 */    
                count++;
        data_p[count]=data[i];//存放到data_p中的对应位置
    }
        //用于检查当有多个数相同时的情况
    i=0,j=n;
    while(i<j)
        {
        if(data_p[i]==0)
                {
            temp=i-1;
            data_p[i]=data_p[temp];
        }//of if
        i++;
    }//of  while
    for(i=0;i<n;i++)//把排序完的数据复制到data中
        data[i]=data_p[i];
    free(data_p);//释放data_p
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

obsidianer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值