常見排序算法之計數排序與基數排序

wKiom1e4daHCpR38AAEKCEW4XWs073.png

wKiom1e4daGj_cMNAAENhyAGQkY362.jpg


1.計數排序
git

顧名思義,是對待排序數組中的數據進行統計,而後根據統計的數據進行排序,例如:數組

待排序數組:ide

a[] = { 100, 123, 112, 123, 201, 123, 112, 156, 156, 178, 185, 156, 123, 112 }spa

首先取出數組中最大值與最小值(這個不用說了吧)3d

最大值:201  最小值:100orm

所以該數組的數值範圍爲 201 - 100 + 1 = 102blog

開闢一個大小爲102的數組 count[102] 並將全部元素初始化爲0排序

再次遍歷數組,以 a[ i - 100 ] 做爲數組count的下標,對該項進行加1it

獲得的count數組應該是(這裏count元素爲0的項就不出現了,太多了)io

count[ 0 ] = 1

count[ 12 ] = 3

count[ 23 ] = 4

count[ 56 ] = 3

count[ 78 ] = 1

count[ 85 ] = 1

count[ 101 ] = 1

其他的元素都爲0

此時遍歷count數組,將每一個元素對應寫回a數組,此時數組a應該爲

a = { 100,112,112,112,123,123,123,123,156,156,156,178,185,201 }

能夠看到,數組a已經排好了序。

代碼以下:

void CountSort(int* a, size_t n)  //計數排序
{
	assert(a);
	int min = a[0];
	int max = a[0];
	for (int i = 1; i < n; ++i)
	{
		if (a[i] > max)
			max = a[i];
		else if (a[i] < min)
			min = a[i];
	}

	int countNum = max - min + 1;
	int* countArray = new int[countNum];
	memset(countArray, 0, sizeof(int)*(countNum));
	for (int i = 0; i < n; ++i)
	{
		++countArray[a[i] - min];
	}

	int index = 0;
	for (int i = 0; i < countNum; ++i)  //寫回數組
	{
		while (countArray[i]--)
		{
			a[index++] = i + min;
		}
	}

	delete[] countArray;
}

能夠看到,計數排序有很大的侷限性,它適合對數據範圍相對比較集中的數據集合進行排序。

2.基數排序

咱們經過一個例子來看基數排序是怎樣進行排序的

設有一個初始序列爲: R {50, 123, 543, 187, 49, 30, 0, 2, 11, 100}

咱們知道,任何一個阿拉伯數,它的各個位數上的基數都是以0~9來表示的。

因此咱們不妨把0~9視爲10個桶。 

咱們先根據序列的個位數的數字來進行分類,將其分到指定的桶中。例如:R[0] = 50,個位數上是0,將這個數存入編號爲0的桶中。

wKioL1e4d6uRsTkEAAAwOTvd7Qw469.png


分類後,咱們在從各個桶中,將這些數按照從編號0到編號9的順序依次將全部數取出來。

這時,獲得的序列就是個位數上呈遞增趨勢的序列。 

按照個位數排序: {50, 30, 0, 100, 11, 2, 123, 543, 187, 49}

接着按照十位進行如上排序(注意:沒有十位的數按照十位爲0處理

wKiom1e4fEjwu8H9AAApjPX2jxY150.jpg

按照十位數排序: {0, 100, 2, 11, 123, 30, 543, 49, 50, 187}

接着按照百位進行如上排序(注意:沒有百位的數按照百位爲0處理

wKiom1e4fPvhUfdiAAAwuzti62Y012.jpg

按照百位數排序: {0, 2, 11, 30, 49, 50, 100, 123, 187, 543}

排序完成j_0058.gifj_0058.gifj_0058.gifj_0058.gifj_0058.gifj_0058.gif

代碼以下:

int GetMaxBit(int* a, size_t n)  //獲取數組中數字最多的位
{
	assert(a);

	int BitNum = 1;
	int tmpData = 10;
	for (int i = 0; i < n; ++i)
	{
		while (tmpData <= a[i])
		{
			++BitNum;
			tmpData *= 10;
		}
	}
	return BitNum;
}

void RadixSort(int* a, size_t n)  //基數排序
{
	assert(a);
	
	int maxBit = GetMaxBit(a, n);
	int digit = 1;
	int* tmp = new int[n];
	int countBit[10];  //計數
	int startBit[10];  //起始位置
	for (int i = 1; i <= maxBit; ++i)
	{
		memset(countBit, 0, sizeof(int)* 10);
		for (int i = 0; i < n; ++i)
		{
			int bit = (a[i]/digit)%10;  //先各位,在十位百位……
			++countBit[bit];
		}

		memset(startBit, 0, sizeof(int)* 10);
		startBit[0] = 0;
		for (int i = 1; i < 10; ++i)
		{
			startBit[i] = startBit[i - 1] + countBit[i - 1];
		}

		for (int i = 0; i < n; ++i)  //存入臨時數組
		{
			int index = startBit[(a[i]/digit)%10]++;
			tmp[index] = a[i];
		}

		for (int i = 0; i < n; ++i)  //寫回原數組
		{
			a[i] = tmp[i];
		}

		digit *= 10;
	}
	
	delete[] tmp;
}


j_0003.gifj_0003.gifj_0003.gifj_0003.gifj_0003.gifj_0003.gifj_0003.gifj_0003.gifj_0003.gifj_0003.gifj_0003.gifj_0003.gifj_0003.gif

相關文章
相關標籤/搜索