《算法导论》笔记·第八章 线性时间排序/计数排序、基数排序和桶排序

#---2020.5.3
#---第八章·线性时间排序

  

计数排序

/*
 *	计数排序
 *	时间复杂度为O(n+k)
 *	使用计数排序须要在全部元素都在一个小的范围内,即k远小于n
 *	在k=O(n)时。时间复杂度为O(n)
 */

  

// COUNTING-SORT
int* countingSort(int *arr, int len, int k)
{
	int *numCount = new int[k]();
	int *result = new int[len];
	
	// now C[i] contains the number of elements equal to i
	for (int i=0; i<len; i++)
	{
		numCount[arr[i]]++;
	}
 
	// now C[i] contains the number of elements less than or equal to i
	for (int i=1; i<k; i++)
	{
		numCount[i] += numCount[i-1];
	}
 
	for (int i=len-1; i>=0; i--)
	{
		result[numCount[arr[i]]-1] = arr[i];
		numCount[arr[i]]--;
	}
 
	delete[] numCount;
	return result;
}

  

基数排序

/*
 *	基数排序
 *	是建立在计数排序的基础之上的,计数排序的稳定性非常重要
 *	否则基数排序就会出错,比如数组[27, 15, 43, 42],假设子排序过程不稳定
 *	则结果就为[15, 27, 43, 42]
 *	时间复杂度为O(d*(n+k)),在d为常数,k=O(n)时,时间复杂度为O(n)
 */

  

// RADIX-SORT
int* radixSort(int *arr, int len, int d)
{
	int *A = new int[len];
	for (int i=0; i<len; i++)
		A[i] = arr[i];
	for (int j=0; j<d; j++)
	{
		int k = 10;
		int *numCount = new int[k]();
		int *result = new int[len];
 
		//numCount中存储等于i的元素个数
		for (int i=0; i<len; i++)
		{
			numCount[getDigit(A[i], j)]++;
		}
 
		//numCount中存储小于等于i的元素个数
		for (int i=1; i<k; i++)
		{
			numCount[i] += numCount[i-1];
		}
 
		//从后至前依次对元素进行排序。保证稳定性,也能够从前往后,可是排序就不稳定了
		for (int i=len-1; i>=0; i--)
		{
			result[numCount[getDigit(A[i], j)]-1] = A[i];
			numCount[getDigit(A[i], j)]--;
		}
		delete[] A;
		delete[] numCount;
		A = result;
	}
	return A;
}
int getDigit(int num, int d)
{
	return (num % (int)pow(10.0, d+1)) / pow(10.0, d);
}

  

桶排序

/*
 *	桶排序
 *	在输入符合均匀分布时,桶排序的效果较好
 *	将各个元素分布在n个桶中。每一个桶内再使用插入排序
 *	仅仅要各个桶的尺寸的平方和与总的元素数呈线性关系
 *	则其时间复杂度就为O(n)
 */

  

// BUCKET-SORT
int* bucketSort(int *arr, int len, int maxNum)
{
	//建立n个桶
	vector<int> *result = new vector<int>[len];
	//将各个元素分布到各个桶内
	for (int i=0; i<len; i++)
	{
		result[(int)((arr[i]/(double)maxNum)*len)].push_back(arr[i]);
	}
 
	for (int i=0; i<len; i++)
	{
		int n = result[i].size();
		//插入排序
		for (int j=1; j<n; j++)
		{
			int k = j - 1;
			int key = result[i][j];
			while (k>=0 && result[i][k]>key)
			{
				result[i][k+1] = result[i][k];
				k--;
			}
			result[i][k+1] = key;
		}
	}
	//合并各个桶中的元素
	for (int i=0, j=0; j<len; j++)
	{
		int length = result[j].size();
		for (int k=0; k<length; k++)
		{
			arr[i++] = result[j][k];
		}
	}
 
	delete[] result;
	return arr;
}

  

猜你喜欢

转载自www.cnblogs.com/jaszzz/p/12821132.html