大一计算机的自学总结:基数排序

前言

之前的所有排序都是基于“比较”这一过程的,而计数排序和基数排序则是不使用比较的排序。时间复杂度方面,基数排序和计数排序都是O(n),比之前的排序算法都要优秀,但对数据有很大要求。

一、计数排序

#include
using namespace std;

//全局变量
#define n 10
int arr[n]; 
int help[20]={0};

//计数排序
void countSort()
{
	for(int i=0;i0)
		{
			arr[i]=j;
			help[j]--;
			i++;
		}	
	} 
} 

int main()
{
	cout<<"[0,20):"<>arr[i];
	}
	
	//计数排序 
	countSort();
	
	cout<<"Sorted:"<

 计数排序非常简单,但必须知道待排数据的范围。

首先,生成一个对应待排数据范围大小的辅助数据,之后在对应下标位置记录每个数出现次数,然后根据这个刷回原数组即可。

二、基数排序

#include
using namespace std;

//全局变量
#define n 10
int arr[n];
int help[n]; 

//基数排序
void radixSort(int bits)
{
	for(int offset=1;bits>0;offset*=10,bits--)
	{
		int cnts[10]={0}; 
		for(int i=0;i=0;i--)
		{
			help[--cnts[arr[i]/offset%10]]=arr[i];
		}
		
		//刷回原数组 
		for(int i=0;i>bits;
	
	for(int i=0;i>arr[i];
	}
	
	//基数排序 
	radixSort(bits);
	
	cout<<"Sorted:"<

 基数排序就要稍微复杂一点,但仍需要知道最大数的数位。

基数排序的原理就是从个位开始,每次根据数位上的数排序,中间再结合计数排序的原理,设置cnts数组记录每个数字出现次数。之后构建前缀和数组,即cnts从记录该数字出现次数改为记录小于等于该数字的个数。有了这个前缀和数组,就可以得知填入辅助数组的位置。

例如,[3,0,3,2,1,3,0,0,1,2,2]这个数组,小于等于0的数有3个,小于等于1的数有5个,小于等于2的数有8个,小于等于3的个数有11个。所以,填入辅助数组时,0就填入3-1=2位置,然后让cnts--;3就填入11-1=10位置,直到cnts数组全为零。

最后再把辅助数组刷回原数组,接着去往下一个数位即可。

三、排序算法稳定性

排序算法的稳定性就是指,相等的数在排序后,是否仍保持原有次序。

回顾之前排序算法的过程,可以发现:

选择排序:无

冒泡排序:有

插入排序:有

归并排序:有

随机快速排序:无

堆排序:无

计数排序:有

基数排序:有

总结

计数排序和基数排序在原理上还是比其他排序简单暴力很多的,就是用得很少。

END

你可能感兴趣的:(算法,排序算法,数据结构,c++)