基本排序系列之计数排序

Posted yxysuanfa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基本排序系列之计数排序相关的知识,希望对你有一定的参考价值。

                                                        简述计数排序

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


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

         设被排序的数组为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中的元素。然后仅仅要输出记录了这些的下标就好了。

假设针对没有反复的序列,我们非常easy能够得到这种排好序的序列如:a[5]={2,4,6,7,9,0}

下标 0 1 2 3 4 5 6 7 8 9
数组c 1 0 1 0 1 0 1 1 0 1
取下标排序后 0
2
4
6 7
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;
}
以上代码经验证。


以上是关于基本排序系列之计数排序的主要内容,如果未能解决你的问题,请参考以下文章

经典算法之计数排序

数据结构从青铜到王者第九篇:数据结构之排序

《C#零基础入门之百识百例》(二十二)数组排序 -- 冒泡排序

《C#零基础入门之百识百例》(二十四)数组排序 -- 插入排序

算法之排序算法——桶排序

算法排序算法之桶排序