第八章——线性时间排序

     这章刚开始证明了基于比较的排序的算法在最坏情况下,都需要做nlgn次比较。

由此可以推出合并排序快速排序都是渐进最优的比较排序算法。


线性时间排序:

1.计数排序

计数排序假设N个输入元素中的每一个都是介于0~k之间的整数,此处K为某个整数。当k=O(n)时,计数排序的运行时间为O(n)。

计数排序的思想是对每个元素x找出小于x的元素个数,有了这个信息最后把它直接插入到最终输出数组相应的位置即可。比如比它大的有三个则它就应该在第四个位置。


实现代码:

void count_sort(int a[],int b[],int k)
{
	int c[MAX]={0};
	for(int j=0;j<MAX-1;j++)
		c[a[j]]=c[a[j]]+1;//得到每个元素个个数
	for(int i=0;i<MAX-2;i++)
		c[i+1]=c[i+1]+c[i];//得到小于等于元素的个数
	for(int j=MAX-1;j>=0;j--)
	{
		b[c[a[j]]]=a[j];
		c[a[j]]=c[a[j]]-1;
	}

}

最后需要说明的是计数排序牺牲了空间换取了时间,计数排序是稳定的。


2.基数排序

算法是根据这张图来排序的,关于为什么要从最低位开始排序而不是从最高位开始,主要是因为如果从最高位开始的话,每次比较的话都要对前面的位的数字进行记录这样会产生很多中间数组,然而从最低位开始话,直接就可以排好所有的不用额外操作。能这样排序的前提建立在每一位的排序都必须是稳定的。

代码实现:


// radix_sort.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <cmath>
#define MAX 7
void count_sort(int m[],int a[],int b[],int k)
{
	//m[]要排序的的数组
	//a[]每个数相同位组成的数组
	//b[]得到的排序结果
	int c[10]={0};
	for(int j=0;j<MAX;j++)
		c[a[j]]=c[a[j]]+1;//得到每个元素的个数
	for(int i=0;i<10-1;i++)
		c[i+1]=c[i+1]+c[i];//得到小于等于元素的个数
	for(int j=MAX-1;j>=0;j--)
	{
		b[c[a[j]]-1]=m[j];
		c[a[j]]=c[a[j]]-1;
	}
}
int min_10(int m,int n)
{
	if(0 == n)
	return 1;
	for(int i=1;i<n;i++)
		m=m*m;
	return m;
}
void radix_sort(int m[],int d)
{
	int a[MAX];
	int b[MAX];

	for(int j=0;j<d;j++)
    {
	  for(int i=0;i<=MAX;i++)
		  a[i]=m[i]/min_10(10,j)%10;   
	  count_sort(m,a,b,MAX);
	  for(int i=0;i<MAX;i++)
		  m[i]=b[i];
	}
	for(int i=0;i<MAX;i++)
		printf("%d\t",m[i]);
	getchar();
}
int _tmain(int argc, _TCHAR* argv[])
{
	int a[MAX]={329,457,657,839,436,720,355};
	radix_sort(a,3);
	return 0;
}

代码还是主要基于基数排序实现每一位的排序,然后依次排完每一位。时间复杂度为计数排序时间复杂度O(n)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值