数据结构练习 14- 线性时间排序

线性时间排序,我们主要分析三类排序:基数排序,计数排序和桶排序

一,桶排序。桶排序跟hash的思想如出一辙。桶排序的意思就是造桶,桶的意思其实就是开辟一个新的数组空间。核心思想是:把数值映射成数组的坐标值。

大概原理如下:

假如存在如下序列:

1  3   5   6   4

则开辟一个大小为7(0-6)的空间。然后把1存在新开辟数组的位置1处,表格2所示,取出表格2里的数据我们发现为:1,3,4,5,6,已经排好序了。


 

         这是简单的情形,复杂的形式,是新开辟的一维数组无法容下原数组,这是我们用一个二维数组来处理,跟hash冲突处理的链表法类似。但是桶的映射函数为:区间划分。

分析其复杂度:映射过程为O(N),我们对不同区间的数据可以采用堆,快排,归并等,其复杂度为:O(NlgN/M)。所以总的排序时间为:O(N+NlgN/M),,当N=M时,复杂度为O(N).稳定的排序。

具体为什么是线性的看《算法导论》P104。

二,基数排序

基数排序是在桶排序的基础上进行的,针对的是一组正整数,比如:32,45,12,76。

      桶排序是针对一个key的,而基数排序是几个key的。如:先按个位排序:32 12 45 76,再按十位排序:12 32 45 76。稳定的排序。

      具体原理见,动画效果:链接地址  时间复杂度为O(N*M),N为数据的个数,M为最大数据的字符的个数,如:32 为2个,455 为 3个。

    代码来自:百度百科

#include <stdio.h>
#include <stdlib.h>
int main(){
int data[10]={73,22,93,43,55,14,28,65,39,81};
int temp[10][10]={0};//映射后存储,因为可能存在冲突,所以开辟二维的,如73,93,
  //基数排序算法
int order[10]={0};
int i,j,k,n,lsd;
k=0;n=1;
printf("\n排序前: ");
for (i=0;i<10;i++) printf("%d ",data[i]);
putchar('\n');
while (n<=10){
for (i=0;i<10;i++){
lsd=((data[i]/n)%10);//获取个位或是十位的数字
temp[lsd][order[lsd]]=data[i];
order[lsd]++;
}
printf("\n重新排列: ");
for (i=0;i<10;i++){
if(order[i]!=0)
for (j=0;j<order[i];j++){
data[k]=temp[i][j];
printf("%d ",data[k]);
k++;
}
order[i]=0;//十位重新利用
}
n*=10;
k=0;
}
putchar('\n');
printf("\n排序后: ");
for (i=0;i<10;i++) printf("%d ",data[i]);
return 0;
}
三,计数排序

” 计数排序“
“计数排序“ 顾名思义,有个计数的过程,我们的思想是记录一系列小于某个数的个数。这样的好处是,可以直接把这个数填入对应的位置,但是缺点是此种方法只能针对整数和整个数组的大小在已知的情况下。

     代码:

*
  Coder Information:
                   email:shenganbeiyang@163.com
				   QQ:501968942
*/
#include<iostream>
using namespace std;
//开辟一个数组A,用于计数,数组B用于导出排序后的数组,ninputDataD 的大小,k数组里最大的数据
void CountNumSort(int *inputData,int n,int k)
{
	//初始化两个数组
	int A[8]={0};
	int B[6]={-1};
    for(int i=0;i<n;++i)
		cout<<inputData[i]<<"  ";
    cout<<endl;
     
    for(int i=0;i<n;++i)// 此时计算了n次,复杂度为O(n)
	{                   //
		//计数过程      //
	 A[inputData[i]]++; //
	
	}
	
    for(int i=1;i<k;++i)//累积过程,时间复杂度O(k)
	{
	 A[i]+=A[i-1];
	
	}
	//导出到数组B中
	for(int i=n-1;i>=0;--i)//时间复杂度O(n)
	{
	 B[A[inputData[i]]-1]=inputData[i];
	 A[inputData[i]]--;//稳定的原因
	}
	for(int i=0;i<n;++i)
		cout<<B[i]<<"  ";
}
int main()
{
	int a[6]={1,3,2,7,4,2};

CountNumSort(a,6,8);

return 0;
}

时间复杂度为O(n+k),如上分析。稳定的排序,至于为什么?结合代码可知 A[inputData[i]]-- 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值