首页 > 代码库 > 基本排序系列之计数排序

基本排序系列之计数排序

                                                        简述计数排序

              看了好多别人写的计数排序,看了好久都没看懂,弄了好久最后发现这么简单居然花了几个小时,所以在这里写上,希望和我一样的初学者不会再绕弯路


一、简述计数排序的思想:

         设被排序的数组为A,排序后存储到B,C为临时数组。所谓计数,首先是通过一个数组C[i]计算大小等于i的元素个数,此过程只需要一次循环遍历就可以;在此基础上,计算小于或者等于i的元素个数,也是一重循环就完成。下一步是关键:逆序循环,从length[A]到1,将A[i]放到B中第C[A[i]]个位置上。原理是:C[A[i]]表示小于等于a[i]的元素个数,正好是A[i]排序后应该在的位置。而且从length[A]到1逆序循环,可以保证相同元素间的相对顺序不变,这也是计数排序稳定性的体现。在数组A有附件属性的时候,稳定性是非常重要的。


二、简述:

         事实上,计数排序要浪费大量的内存空间,而且对于负数的序列在此讨论的也是无法结决的问题而且排序的序列的书必须位于0-k之间,但其算法复杂度小O(n+k)即是它的算法复杂度,这个算法是一个稳定的算法。我们做排序有两种情况,一种是没有重复出现的数的排序,另一种则是有这种情况的。

         以上扯的让人看不懂,说普通点就是给你一个数组如a[10] = {2 ,2 ,3 ,4,5,6,7,9,0,6 }这个数组,我们创建一个临时数组来保存,也是这个算法的操作经典所在,即我们建立一个c[k]这样的一个数组,这里k 表示条件即要使用此算法必须满足的条件,那么就是数组a中的元素必须都在0-k之间。我们通过数组c下标来记录我们需要排序的数组a中的元素,然后只要输出记录了这些的下标就好了。如果针对没有重复的序列,我们很容易可以得到这样的排好序的序列如:a[5]={2,4,6,7,9,0}

下标0123456789
数组c1010101101
取下标排序后0
2
4
67
9
然后我们将排序后的数放入一个新的数b[5]={0,0,0,0,0,0}

得到:b[5]  ={0,2,4,6,7,9}这样我们就得到了这个序列。

如果针对有重复的情况:

我们只需要记录有几个重复的就好了,在上表中的第二行就是用来解决这个问题的,我们可用来记录有几次重复,从而达到彻底的解决这排序的问题。

这部分代码在此贴上:

     int j=0,temp;
     for(int i=0;i<=k;i++){//在此无重复的c[i]里面全是1
           temp=c[i];//默认为0
           while(temp-->0){//这里解决重复的问题
                  b[j++]=i;//i就是排序数据中的数
           }
	 }

我们通过c这个数组来记录相同,即重复出现的数。

贴上全部代码:

/**
*计数排序是一种非比较的稳定的高效的排序算法
*@author 菜鸟
*@version 2014.7.13
*/
#include <iostream>
#include <malloc.h>
#include <windows.h>
using namespace std;
//计数算法函数
/**
*@param int a[] 用来接收需要排序的序列
*@param int length_a 表示需要排序的序列的长度
*@param int b[] 用来保存排序好后的序列
*@param int k 表示需要排列的数必须处于0-k之间 
*@return 无
*/
void countSort(int a[],int length_a,int b[],int k){
     //接收到了传进的需要排序的数组,并且知道了其数值处于0-k之间
	 //此时我们需要建立一个数组用来临时保存数据
	 int *c =NULL;
	 int temp;
	 if(c!=NULL){
	     free(c);
	 }
	 c = (int *)malloc(sizeof(int)*k);
	 if(c != NULL){
	    cout<<"空间申请成功!"<<endl;
	 }
	 //此时首先得必须对数组c进行清零
	 for(int i = 0; i< k;i++){
	     c[i] = 0;
	 }
	 //统计排序个数,并放到对应值的位置处
	 for(int i = 0;i < length_a;i++){
	      temp = a[i];
		  c[temp]++; 
	 }
	 int j=0;
     for(int i=0;i<=k;i++){
           temp=c[i];
           while(temp-->0){
                  b[j++]=i;//i就是排序数据中的数
           }
	 }
	 free(c);
}
/**
*输出函数
*@param intarrayNum[] 表示接受需要输出的数组
*@param int length_num 表示需要输出的数组的长度
*@return 无
*/
void outPut(int arrayNum[],int length_num){
	for(int i =0; i< length_num;i++){
	      cout<<"第"<<i+1<<"个元素:"<<arrayNum[i]<<endl;
	}
	cout<<"输出完毕!"<<endl;
}
int main(){
	 //假设要排序的数组序列为
	 int a[10] = {1,3,4,5,2,5,2,7,9,0};
	 int b[10] = {0};
	 int k = 10;
	 cout<<"未经排序的数组序列:"<<endl;
	 outPut(a,10);
	 countSort(a,10,b,10);
	 cout<<"经排序后的数组序列:"<<endl;
	 outPut(b,10);
     system("PAUSE");
	 return  0;
}
以上代码经验证!