计数排序、基数排序与桶排序

一、计数排序

稳定、 当输入的元素是n 个小区间(0到k)内整数时,它的运行时间是 O(n + k),空间复杂度是O(n)。

const int K = 100;
//计数排序:假设输入数据都属于一个小区间内的整数,可用于解决如年龄排序类的问题
//Input:A[0, ..., n-1], 0 <= A[i] < K
//Output:B[0, ..., n-1], sorting of A
//Aux storage C[0, ..., K)
void CountSort(int A[], int B[], int n)
{
	int *C = new int[K];
	int i, j;

	//初始化
	//memset(C, 0, sizeof(int)*K);

	//统计
	for (i = 0; i < n; i++)
		C[A[i]]++;	//C[i] = |{key=i}|

	for (i = 1; i < K; i++)
		C[i] += C[i - 1];	//C[i] = |{key <= i}|
	//分配
	for(j = n - 1; j >= 0; j--)
	//for(j = 0; j < n; j++)
	{
		//B[C[A[j]] - 1] = A[j];
		//C[A[j]]--;

		B[--C[A[j]]] = A[j];	 //对于每一个A[j]来说,C[A[j]]-1就是A[j]在输出数组中的最终位置,因为共有C[A[j]]个元素小于或等于A[j]
	}

	delete []C;
}

参考算法导论p108~110。

可以利用计数排序的思想,在O(1)的时间复杂度内计算介于0~k之间的n个整数中有多少个落在区间[a,b]内(算法导论p110题8.2-4):

int CountNumberBetweenAB(int L[], int n, int a, int b)
{
	const int K = 100;
	int *c = new int[K];
	int i;

	memset(c, 0, sizeof(int)*K);
	for (i = 0; i < n; i++)
		c[L[i]]++;
	for (i = 1; i < K; i++)
		c[i] += c[i - 1];

	int count = (a == 0 ? c[b] : c[b] - c[a - 1]);
	delete c;

	return count;
}

二、基数排序

稳定、按最低有效位到最高有效位进行排序(中间采用的是稳定呢的计数排序), 当输入的元素是n 个d位整数时,它的运行时间是 O(d(n + k)),k一般是10,空间复杂度是O(n)。

void RadixSort(int A[], int n, int d)
{
	const int K = 10;
	int i, j;
	int *digitI = new int[n], c[K];
	int *tmp = new int[n];//临时数组
	int base = 1;

	for (i = 0; i < d; i++)
	{
		memset(c, 0, sizeof(int)*K);
		for (j = 0; j < n; j++)
		{
			digitI[j] = (A[j] / base) % K;	  //从低位到高位取每一位
			c[digitI[j]]++;
			//printf("%3d ", digitI[j]);
		}
		//cout << endl;
		for (j = 1; j < K; j++)
			c[j] += c[j - 1];

		for (j = n - 1; j >= 0; j--)
			tmp[--c[digitI[j]]] = A[j];   // = digitI[j]]

		//for (j = 0; j < n; j++)
		//	printf("%03d ", tmp[j]);
		//cout << endl;

		memcpy(A, tmp, sizeof(int)*n);
		base *= 10;
	}
	memcpy(A, tmp, sizeof(int)*n);

	delete []tmp;
	delete []digitI;
}

参考算法导论p110~112

三、桶排序

桶排序假设输入是由一个随机过程产生,该过程将元素均匀、独立地分布在[0,1)区间上。桶排序是稳定的、期望时间复杂度是O(n),空间复杂度是O(k*n/k) = O(n);

/*initial arr*/
void InitialArr(double *arr,int n)
{
	srand((unsigned)time(NULL));
	for (int i = 0; i < n;i++)
	{
		arr[i] = rand() / double(RAND_MAX+1);   //[0.1)
	}
}
void BucketSort(double arr[], int n)
{
	const int K = 10;//桶的个数
	int i, j, k;  

	double *bucket[K];
	for (i = 0; i < K; i++)
		bucket[i] = new double[n];

	int count[K] = {0};//每一个桶中的元素个数

	for (i = 0; i < n; i++)
	{
		double tmp = arr[i];
		int digitI = (int)(tmp*10);	//digitI表示第i个元素的小数点第一位
						//小数点第一位(digitI)相同的元素放在同一个桶(bucket[digitI])中的第count[digitI]个位置上
		                                //通过插入排序将tmp插入到有序的bucket[digitI][0,...,count[digitI] - 1]
		for (j = count[digitI] - 1; j >= 0 && tmp < bucket[digitI][j]; j--)
			bucket[digitI][j + 1] = bucket[digitI][j];
		bucket[digitI][j + 1] = tmp;
		count[digitI]++;
	}

	//重新连接数据
	k = 0;
	for (i = 0; i < K; i++)
		for (j = 0; j < count[i]; j++)
			arr[k++] = bucket[i][j];

   for (i = 0; i < K; i++)
	   delete []bucket[i];
}

参考算法导论p112~114

计数排序、基数排序与桶排序

时间: 2024-12-30 00:15:20

计数排序、基数排序与桶排序的相关文章

线性排序之基数排序,桶排序,计数排序

基数排序 计数排序 桶排序 基数排序,桶排序,计数排序是三种线性排序方法,突破了比较排序的O(nlogn)的限制.但是只适用于特定的情况. 基数排序 以下为维基百科的描述: 基数排序 : 将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零.然后,从最低位开始,依次进行一次排序.这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列. 基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digit

基数排序与桶排序,计数排序【详解】

桶排序简单入门篇^-^ 在我们生活的这个世界中到处都是被排序过的东东.站队的时候会按照身高排序,考试的名次需要按照分数排序,网上购物的时候会按照价格排序,电子邮箱中的邮件按照时间排序……总之很多东东都需要排序,可以说排序是无处不在.现在我们举个具体的例子来介绍一下排序算法. 首先出场的是我们的主人公小哼,上面这个可爱的娃就是啦.期末考试完了老师要将同学们的分数按照从高到低排序.小哼的班上只有5个同学,这5个同学分别考了5分.3分.5分.2分和8分,哎,考得真是惨不忍睹(满分是10分).接下来将分

线性排序算法---- 计数排序, 基数排序, 桶排序

排序算法里,除了比较排序算法(堆排序,归并排序,快速排序),还有一类经典的排序算法-------线性时间排序算法.听名字就让人兴奋! 线性时间排序,顾名思义,算法复杂度为线性时间O(n) , 非常快,比快速排序还要快的存在,简直逆天.下面我们来仔细看看三种逆天的线性排序算法, 计数排序,基数排序和桶排序. 1计数排序  counting Sort 计数排序 假设 n个 输入元素中的每一个都是在 0 到 k 区间内的一个整数,当 k= O(N) 时,排序运行的时间为 O(N). 计数排序的基本思想

排序算法(七)非比较排序:计数排序、基数排序、桶排序

前面讲的是比较排序算法,主要有冒泡排序,选择排序,插入排序,归并排序,堆排序,快速排序等. 非比较排序算法:计数排序,基数排序,桶排序.在一定条件下,它们的时间复杂度可以达到O(n). 一,计数排序(Counting Sort) (1)算法简介 计数排序(Counting sort)是一种稳定的排序算法.计数排序使用一个额外的数组C,其中第i个元素是待排序数组A中值等于i的元素的个数.然后根据数组C来将A中的元素排到正确的位置.它只能对整数进行排序. (2)算法描述和实现 得到待排序数的范围(在

排序算法下——桶排序、计数排序和基数排序

桶排序.计数排序和基数排序这三种算法的时间复杂度都为 $O(n)$,因此,它们也被叫作线性排序(Linear Sort).之所以能做到线性,是因为这三个算法是非基于比较的排序算法,都不涉及元素之间的比较操作. 1. 桶排序(Bucket Sort)? 1.1. 桶排序原理 桶排序,顾名思义,要用到"桶".核心思想是将要排序的数据分到几个有序的桶里,每个桶的数据再单独进行排序.桶内排完序后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了. 1.2. 桶排序的时间复杂度分析 如

各种常见的排序,冒泡排序,选择排序,插入排序,希尔排序,堆排序,快速排序,基数排序,桶排序

各种常见的排序 要开始找工作了,把以前学的各种小知识复习一遍,以下是各种常见的排序的简单实现(冒泡排序,选择排序,插入排序,希尔排序,堆排序,快速排序,基数排序,桶排序),至于原理就不写出来了,代码比较简单,看一下就懂,再不行可以随意找本书或百度! #include <iostream> using namespace std; // 冒泡 void BubbleSort(int data[], int length) { if(data == NULL || length <= 0)

最快最简单的排序算法:桶排序

在我们生活的这个世界中到处都是被排序过的.站队的时候会按照身高排序,考试的名次需要按照分数排序,网上购物的时候会按照价格排序,电子邮箱中的邮件按照时间排序……总之很多东西都需要排序,可以说排序是无处不在.现在我们举个具体的例子来介绍一下排序算法. 首先出场的我们的主人公小哼,上面这个可爱的娃就是啦.期末考试完了老师要将同学们的分数按照从高到低排序.小哼的班上只有5个同学,这5个同学分别考了5分.3分.5分.2分和8分,哎考的真是惨不忍睹(满分是10分).接下来将分数进行从大到小排序,排序后是8

排序算法之——桶排序

这是本人的第一篇随笔,为的是分享学习经验,和大家讨论一些算法,以便取得些许进步,也是对学习的总结. 话不多说,下面我会用图文的方式向各位介绍桶排序. 1.主要思想: 桶排序的大体思路就是先将数组分到有限个桶中,再对每个桶中的数据进行排序,可以说是鸽巢排序的一种归纳结果(对每个桶中数据的排序可以是桶排序的递归,或其他算法,在桶中数据较少的时候用插入排序最为理想). 2.算法效率: 对N个数据进行桶排序的时间复杂度分为两部分: 1.对每一个数据进行映射函数的计算(映射函数确定了数据将被分到哪个桶),

算法导论-- 线性时间排序(计数排序、基数排序、桶排序)

线性时间排序 前面介绍的几种排序,都是能够在复杂度nlg(n)时间内排序n个数的算法,这些算法都是通过比较来决定它们的顺序,这类算法叫做比较排序 .下面介绍的几种算法用运算去排序,且它们的复杂度是线性时间. -------------------------------------- 1.计数排序 计数排序采用的方法是:对每个元素x,去确定小于x的元素的个数,从而就可以知道元素x在输出数组中的哪个位置了. 计数排序的一个重要性质是它是稳定的,即对于相同的两个数,排序后,还会保持它们在输入数组中的