线性时间排序

<span style="font-size:18px;">public void  radixSort(int a [][])
	{
		int keyNum=a[1].length;
		int count=a.length;
		for(int i=keyNum-1;i>=0;i--)
		{
			for(int j=1;j<count;j++)
			{
				int k=j-1;
				int key[]=a[j];
				while(k>=0&&a[k][i]>key[i])
				{
					a[k+1]=a[k];
					k--;
				}
				a[++k]=key;
			}
		}
	}</span>

     我们前面提到的方法,基本上都是比较排序,本篇介绍三种非比较类型的排序,计数排序、基数排序、桶排序,比较排序的最坏的情况都是经过nlgn的,线性排序的时间复杂度基本上都是线性关系。

1.计数排序

    计数排序不是通过元素之间的比较,而是采用辅助数组,C,长度为k,注意其存储方式并不是从0开始存储,这种存贮类似于哈希表的开放定址的方法,对A数组进行排序,遍历数组A,每一个元素都是在C中对应的C[A[i]]加1,因此数组C的j位置就是记录的A中值为j的元素出现的次数。然后C[j]=C[j-1]+C[j],每个C中元素为小于等于J的元素个数,也是在数组中的存储位置,然后遍历A,在C中寻找A[i]的位置,然后C[A[i]]-1,(小于等于他的数少了一),输出到B中排好序的数组。注意:遍历A的时候要从后向前遍历,因为,重复元素在C中提取出来的靠后边放置,要保证稳定性,两个重复元素在排序前后的相对位置不能改变。基数排序这种辅助数组的存储方式是关键使用计数排序的情况,数组A中的元素都是小区间的整数。时间复杂度:k+n;下面是代码:


/**
	 * @param a
	 * @param p
	 * @param r
	 * 计数排序并不是比较排序,其借助辅助数组c,存储方式类似于哈希表的开放定址法
	 * 下标i代表 a数组中的对应元素i的值
	 */
	public void countSort(int a[],int p,int r)
	{
		int len=r-p+1;
		int b[]=new int [r-p+1];//放置排好序的数组
		int c[]=new int[40];//计数使用的数组
		for(int i=p;i<=r;i++)
			c[a[i]]=c[a[i]]+1;//是几就存到c的相应位置c的长度为a数组中最大的数
		for(int j=1;j<c.length;j++)
			c[j]=c[j]+c[j-1];//这次循环结束之后每一个i位置上的c[i]都是小于等于i的个数
		for(int i=r;i>=p;i--)//这里从最后开始遍历是因为若有重复元素,重复元素在b中的相对位置要与a
		{                     //中的一致,因为这种方法先写的元素位置靠后,所以从后开始遍历
			b[c[a[i]]-1]=a[i];
            c[a[i]]=c[a[i]]-1;	//写完之后小于等于它的个数就减一了		
		}
		System.arraycopy(b,0, a, p, len);
        /*********计数排序的原址排序******/
       /* for(int i=0,n=p;i<40;i++)
                while(c[i]!=0)
                {
                    a[n++]=i;
                    c[i]-=1;
                }*/
 }
计数排序的稳定性只有当排序的数据还附带卫星数据时才比较重要。还有计数排序常用作基数排序的一个子过程。因为基数排序(多关键字的)需要对每一个关键字进行稳定排序。

2.基数排序

     基数排序也就是多关键字排序,是一种用在卡片排序机上的算法,先按照最低有效位进行排序,常用作扑克牌、日期的排序。如果使用计数排序时间复杂度为:d(n+k)


**链式基数排序是借助分配和收集两种操作对但逻辑关键字进行排序的一种内部排序方法,时间复杂度是:d(n+rd),rd为基数(即关键字的范围,辅助数组大小)。每一次分配收集都要借助两个辅助数组,长度为基数(关键字的取值范围)。每个数组元素存放排序元素的结构体所在下标,使用链表方式存储。其实质原来元素还是在原链表(数组)的位置,只是改变的next的值,这样就虚拟了一个链表。排序其实就是改变的每个节点next的值,表示在数组的哪一个位置。

   以上就是链表:一般来说总是想到链表就想到指针指向下一个链表,其实也可以用下标表示next,此时所有元素都是保存在数组中的。因此不用改变数组中元素位置,只是设置个头结点,让他next就是一下个元素。

3.桶排序

      桶排序假设输入的数据服从均匀分布,平均情况下的时间代价为:n;桶排序将[0,1)区间划分为n个相同大小的子区间,称为桶,然后将输入的n个元素分别放入n个桶中,因为数据均匀分布,所以不会出现许多数据出现在一个桶中,线先对每个桶进行排序,再遍历每个桶取出数据,这里桶中数据用链表存储。



总结:计数排序这中存储数组的规则很关键,特定元素值映射到特定的辅助数组的位置,直接计数。不用那种n的平方的时间复杂度。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值