計數排序的描述
計數排序是一種高效的線性排序,它通過計算一個集合中元素出現的次數來確定集合如何排列。不同於之前介紹的一些算法是基於比較的,計數排序不需要進行元素比較,而且它的運行效率要比效率我O(nlg n)比較排序高。
計數排序有一定的侷限性。其中最大的侷限就是它只能用於整型或者那些可以用整型來表示的數據集合。這是因爲計數排序利用一個數組的索引來記錄元素出現的次數。例如,如果整數3出現過4次,那麼4將存儲到數組索引爲3的位置上。同時,我們還需要知道集合中最大整數的值,以便於爲數組分配足夠的空間。
除了速度之外,計數排序的另一個優點就是非常穩定。穩定的排序能使具有相同數值的元素有相同的順序,就像它們在原始集合中表現出來的一樣。
計數排序首先計算集合中每個元素出現的次數,並將這些結果存儲到計數數組(count)中,數組的索引值就是元素本身。當所有元素次數都統計出來後,就調整計數值,使元素在進入有序集合之前,確認自己的插入位置。用元素本身的次數加上它前一個元素的次數,此時,count中每個元素的次數計數就是這個元素在有序集合中的偏移量。要完成排序,必須按照元素的便宜量放置元素,放置一次,對應元素的計數要減1。
算法:
CountingSort(A[0...n-1], k)
//該算法用計數排序對給定的數組排序
//輸入:一個可排序的數組A[0...n-1],k爲數組中最大元素值加1
//輸出:非降序排列的數組A[0...n-1]
for j <- 0 to k-1 do D[j] <- 0 //初始化頻率數組
for i <- 0 to n-1 do D[A[i]] <- D[A[i]]+1 //計算頻率值
for j <- 1 to k-1 do D[j] <- D[j]+D[j-1] //調整計數值
for i <- n-1 to 0 do
j <- D[A[i]]
S[j-1] <- A[i] //數組下標從0開始
D[A[i]] <- D[A[i]]-1
cpy S to A
計數排序的實現
// CountingSort.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "typedef.h"
/*
*函數名:CountingSort
*參數:pData 待排序數組數據的首地址
* uiSize 數據的元素個數
* uiMax 數組中最大元素值加1
*功能:對數組進行計數排序
*返回值:無
*作者:AlbertoNo1
*日期:2016-03-28
*/
VOID CountingSort(VOID *pData, UINT32 uiSize, UINT32 uiMax)
{
INT32 i = 0;
INT32 j = 0;
UINT32 uiIndex = 0; //元素在有序數組中的偏移值
UINT32 *puiData = NULL;
UINT32 *puiTemp = NULL;
UINT32 *puiCount = NULL;
if (uiSize <= 1)
{/*不用排序*/
return ;
}
/*申請用於存放排序元素的內存*/
puiTemp = (UINT32*)malloc(uiSize*sizeof(UINT32));
if (NULL == puiTemp)
{
return ;
}
/*申請用於存放元素計數數組的內存*/
puiCount = (UINT32*)malloc(uiMax*sizeof(UINT32));
if (NULL == puiCount)
{
free(puiTemp);
return ;
}
puiData = (UINT32*)pData;
/*初始化計數頻率數組*/
for (j = 0; j < uiMax; j++)
{
puiCount[j] = 0;
}
/*統計每個元素出現的頻率*/
for (i = 0; i < uiSize; i++)
{
puiCount[puiData[i]] += 1;
}
/*調整計數值*/
for (j = 1; j < uiMax; j++)
{
puiCount[j] = puiCount[j] + puiCount[j-1];
}
/*排序, 從後往前進行排序,保證了排序的穩定性*/
for (i = uiSize-1; i >= 0; i--)
{
uiIndex = puiCount[puiData[i]];
memcpy(&puiTemp[uiIndex-1], &puiData[i], sizeof(UINT32));
puiCount[puiData[i]] -= 1;
}
memcpy(puiData, puiTemp, uiSize*sizeof(UINT32));
free(puiTemp);
free(puiCount);
return ;
}
int _tmain(int argc, _TCHAR* argv[])
{
INT32 iRet = 0;
UINT32 uiLoop = 0;
//UINT32 auiData[] = {10,15,15,18,20,20,20,36,48,51,51,77,77};
//UINT32 auiData[] = {77,77,51,51,48,36,20,20,20,18,15,15,10};
UINT32 auiData[] = {77,15,20,18,51,51,36,10,77,15,20,20,48};
//UINT32 auiData[] = {77,77};
//UINT32 auiData[] = {77};
CountingSort(auiData, sizeof(auiData)/sizeof(auiData[0]), auiData[0]+1);
printf("Counting Sort Success.\n");
printf("Result:\n");
for (uiLoop = 0; uiLoop < sizeof(auiData)/sizeof(auiData[0]); uiLoop++)
{
printf("%d ", auiData[uiLoop]);
}
getchar();
return 0;
}