希尔排序(Shell Sort)



实例分析
以4为关键字进行分组
每组两个端点比较大小,头端点比尾端点大的话交换位置,否则不变
第一组【45,34,78,12,34】位置交换后变为:【34,34,78,12,45】
第二组【34,78,12,34,32】位置交换后变为:【32,78,12,34,34】
第三组【78,12,34,32,29】位置交换后变为:【29,12,34,32,78】
第四组【12,34,32,29,64】位置不变
第一轮分组后序列为
第二轮分组以2为关键字
每组两个端点比较大小,头端点比尾端点大的话交换位置,否则不变
第一组【34,32,29】位置交换后变为【29,32,34】
整体序列为 29, 32, 34, 12,45,34,78,64
第二组【32,34,12】位置交换后变为【12,34,32】
整体序列为 29, 12, 34, 32,45,34,78,64
第三组【34,32,45】保持不变
第四组【32,45,34】保持不变
第五组【45,34,78】保持不变
第六组【34,78,64】保持不变
即 29, 12, 34, 32,45,34,78,64
第三轮以1为关键字进行分组
【29,12】位置变换之后【12,29】
【29,34】位置不变
【34,32】位置变换之后【32,34】
【34,45】位置不变
【45,34】位置变化之后【34,45】
【45,78】位置不变
【78,64】位置变化之后【64,78】
最终序列为
12,29,32,34,34,45,64,78 至此排序完毕
java代码以【8,3,2,1,7,4,6,5】序列为例
package com.yonyou.test;
/**
* 内部排序算法之Shell排序
* 默认按照从小到大进行排序操作
*/
public class Test{
public static void main(String[] args) {
//需要进行排序的数组
int[] array=new int[]{8,3,2,1,7,4,6,5};
//输出原数组的内容
printResult(array);
//shell排序操作
shellSort(array);
//输出排序后的相关结果
printResult(array);
}
/**
* shell排序算法
* 增量h=(h*3)+1; 这个增量公式是由Knuth给出的
* @param array
*/
private static void shellSort(int[] array) {
//首先根据数组的长度确定增量的最大值
int h=1;
// 按h * 3 + 1得到增量序列的最大值
while(h <= array.length / 3)
{
h = h * 3 + 1;
}
//进行增量查找和排序
while(h>0)
{
for(int i=h;i<array.length;i++)
{
for(int k=i;k<array.length;k+=h)
{
//判断是否需要重新排序,如果小于k-h处的值,需要重新排序
if(array[k]<array[k-h])
{
int tempValue=array[k];
int j=k;
for(;j>=i&&tempValue<array[j-h];j-=h)
{
array[j]=array[j-h];
}
array[j]=tempValue;
}
}
printResult(array);
}
h=(h-1)/3;
}
}
/**
* 输出相应数组的结果
* @param array
*/
private static void printResult(int[] array) {
for(int value:array)
System.out.print(" "+value+" ");
System.out.println();
}
/**
* 交换数组中两个变量的值
* @param array
* @param i
* @param j
*/
private static void swap(int[] array,int i,int j){
int temp=array[i];
array[i]=array[j];
array[j]=temp;
}
}
- 1.不稳定
- 2.空间代价θ(1)
- 3.时间代价θ(n²)
- 4.选择适当的增量序列,可以使得时间代价解决θ(n)