《排序算法》——希尔排序,桶式排序(Java)

简介: 一:希尔排序        也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。        希尔排序是非稳定排序算法,先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。

一:希尔排序

       也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。

       希尔排序是非稳定排序算法,先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中,先在各组内进行直接插入排序

      然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量
=1(
<
…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。

      该方法实质上是一种分组插入方法

      比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。
算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。

      一般的初次取序列的一半为增量,以后每次减半,直到增量为1。

      给定实例的shell排序的排序过程
      假设待排序文件有10个记录,其关键字分别是:
      49,38,65,97,76,13,27,49,55,04。      
      增量序列的取值依次为:
      5,2,1
           

          代码如下:
<span style="font-size:14px;">package sort;

import java.util.Arrays;

public class shellSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {49,38,65,97,76,13,27,49,78,34,12,64,1};
		System.out.println("排序之前:");
		System.out.println(Arrays.toString(a));
		
		//希尔排序
		int len = a.length;
		while(true)
		{
			for(int i=0; i< len; i++)
				for(int j=i ; j+len < a.length; j +=len)
				{
					int temp;
					if(a[j] > a[j+len])   //大于,则交换
					{
						temp = a[j];
						a[j] = a[j+len];
						a[j+len] = temp;
					}
				}
			if(len==1)
				break;
			len--;
		}
		System.out.println("排序之后:");
		System.out.println(Arrays.toString(a));
	}

}
</span>


二:桶式排序

     该部分转载自:http://blog.csdn.net/apei830/article/details/6596057

   

       桶式排序不再是一种基于比较的排序方法,它是一种比较巧妙的排序方式,但这种排序方式需要待排序的序列满足以下两个特征:

       1:待排序列所有的值处于一个可枚举的范围之类;

       2:待排序列所在的这个可枚举的范围不应该太大,否则排序开销太大。

      排序的具体步骤如下:

     (1)对于这个可枚举范围构建一个buckets数组,用于记录“落入”每个桶中元素的个数;

    (2)将(1)中得到的buckets数组重新进行计算,按如下公式重新计算:

               buckets[i] = buckets[i] +buckets[i-1] (其中1<=i<buckets.length); 

      桶式排序是一种非常优秀的排序算法,时间效率极高,它只要通过2轮遍历:第1轮遍历待排数据,统计每个待排数据“落入”各桶中的个数,第2轮遍历buckets用于重新计算buckets中元素的值,2轮遍历后就可以得到每个待排数据在有序序列中的位置,然后将各个数据项依次放入指定位置即可。

       桶式排序的空间开销较大,它需要两个数组,第1个buckets数组用于记录“落入”各桶中元素的个数,进而保存各元素在有序序列中的位置,第2个数组用于缓存待排数据。

       桶式排序是稳定的。如果待排序数据的范围在0~k之间,那么它的时间复杂度是O(k+n)的, 桶式排序算法速度很快,因为它的时间复杂度是O(k+n),而基于交换的排序时间上限是nlg n。

      但是它的限制多,比如它只能排整形数组。而且当k较大,而数组长度n较小,即k>>n时,辅助数组C[k+1]的空间消耗较大, 当数组为整形,且k和n接近时, 可以用此方法排序。(有的文章也称这种排序算法为“计数排序”)


代码实现:

  1. public class BucketSortTest {  
  2.     public static int count = 0;  
  3.   
  4.     public static void main(String[] args) {  
  5.   
  6.         int[] data = new int[] { 536219487 };  
  7.         print(data);  
  8.         bucketSort(data, 010);  
  9.         print(data);  
  10.   
  11.     }  
  12.   
  13.     public static void bucketSort(int[] data, int min, int max) {  
  14.         // 缓存数组  
  15.         int[] tmp = new int[data.length];  
  16.         // buckets用于记录待排序元素的信息  
  17.         // buckets数组定义了max-min个桶  
  18.         int[] buckets = new int[max - min];  
  19.         // 计算每个元素在序列出现的次数  
  20.         for (int i = 0; i < data.length; i++) {  
  21.             buckets[data[i] - min]++;  
  22.         }  
  23.         // 计算“落入”各桶内的元素在有序序列中的位置  
  24.         for (int i = 1; i < max - min; i++) {  
  25.             buckets[i] = buckets[i] + buckets[i - 1];  
  26.         }  
  27.         // 将data中的元素完全复制到tmp数组中  
  28.         System.arraycopy(data, 0, tmp, 0, data.length);  
  29.         // 根据buckets数组中的信息将待排序列的各元素放入相应位置  
  30.         for (int k = data.length - 1; k >= 0; k--) {  
  31.             data[--buckets[tmp[k] - min]] = tmp[k];  
  32.         }  
  33.     }  
  34.   
  35.     public static void print(int[] data) {  
  36.         for (int i = 0; i < data.length; i++) {  
  37.             System.out.print(data[i] + "\t");  
  38.         }  
  39.         System.out.println();  
  40.     }  
  41.   
  42. }  


运行结果:

  1. 5   3   6   2   1   9   4   8   7     
  2. 1   2   3   4   5   6   7   8   9    

至此排序算法我已经总结的不少了,所谓是各有千秋吧,当然还有许多排序的算法我没有进行总结和实现(说不到哪天脑子发热了就会续着总结完吧),比如说:
外部排序(针对大文件)
间接排序(针对复杂的数据结构)
冒泡排序(最经典的也是最简单的)
计数排序
基数排序

排序算法之快速排序
排序算法之堆排序
排序算法之归并排序,插入排序
排序算法之希尔排序,桶式排序

相关文章
|
1月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
66 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
3月前
|
搜索推荐 算法 Java
手写快排:教你用Java写出高效排序算法!
快速排序(QuickSort)是经典的排序算法之一,基于分治思想,平均时间复杂度为O(n log n),广泛应用于各种场合。在这篇文章中,我们将手写一个Java版本的快速排序,从基础实现到优化策略,并逐步解析代码背后的逻辑。
142 1
|
1月前
|
算法 搜索推荐 Shell
数据结构与算法学习十二:希尔排序、快速排序(递归、好理解)、归并排序(递归、难理解)
这篇文章介绍了希尔排序、快速排序和归并排序三种排序算法的基本概念、实现思路、代码实现及其测试结果。
20 1
|
1月前
|
存储 搜索推荐 算法
【用Java学习数据结构系列】七大排序要悄咪咪的学(直接插入,希尔,归并,选择,堆排,冒泡,快排)以及计数排序(非比较排序)
【用Java学习数据结构系列】七大排序要悄咪咪的学(直接插入,希尔,归并,选择,堆排,冒泡,快排)以及计数排序(非比较排序)
22 1
|
1月前
|
算法 Java 数据中心
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
67 2
|
3月前
|
存储 Java
Java中ArrayList 元素的排序
本文提供了Java中根据`ArrayList`元素的某个属性进行排序的示例代码,包括实现`Comparable`接口和重载`compareTo`方法,然后使用`Collections.sort`方法进行排序。
|
3月前
|
存储 Java API
【Java高手必备】揭秘!如何优雅地对List进行排序?掌握这几种技巧,让你的代码瞬间高大上!
【8月更文挑战第23天】本文深入探讨了Java中对List集合进行排序的各种方法,包括使用Collections.sort()、自定义Comparator以及Java 8的Stream API。通过示例代码展示了不同情况下如何选择合适的方法:从简单的整数排序到自定义类对象的排序,再到利用Comparator指定特殊排序规则,最后介绍了Stream API在排序操作中的简洁应用。理解这些技术的区别与应用场景有助于提高编程效率。
70 4
|
3月前
|
存储 Java
|
3月前
|
搜索推荐 算法 Java
堆排序实战:轻松实现高效排序,附详细Java代码
嗨,大家好!我是小米,一名热爱技术分享的程序员。今天要带大家了解堆排序——一种基于二叉堆的数据结构,具有O(n log n)时间复杂度的选择排序算法。堆排序分为构建大顶堆和排序两个阶段:先建堆使根节点为最大值,再通过交换根节点与末尾节点并调整堆来逐步排序。它稳定高效,空间复杂度仅O(1),适合对稳定性要求高的场合。虽然不如快速排序快,但在避免递归和节省空间方面有优势。一起动手实现吧!如果有任何疑问,欢迎留言交流!
91 2
|
3月前
|
存储 Java