您的位置:首页 > 编程语言 > Java开发

java算法之四希尔排序(插入排序)

2016-01-26 11:39 639 查看
希尔排序:

* 基本思想: 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。

* 所有距离为dl的倍数的记录放在同一个组中。

* 先在各组内进行直接插人排序;然后,取第二个增量d2<d1重复上述的分组和排序,

* 直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。

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

演示地址:http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/shell.htm

自己的code:

import java.util.ArrayList;

public class shellSort {

private static int[] array ={49,38,65,97,76,13,27,49,55,04};

public static void main(String[] args) {
int[] splitNum = {5,3,1};

for(int i=0;i<splitNum.length;i++){
shellsort(array, splitNum[i]);
for(int j=0;j<array.length;j++) {
System.out.print(array[j]+",");
}
System.out.println("");
}

}

//直接插入排序
public static int[] insertSorts(int[] array) {
if(array == null || array.length < 2){
return array;
}
for(int i=1;i<array.length;i++) {
int currentValue = array[i];
int position = i;
for(int j=i-1;j>=0;j--) {
if(array[j]>currentValue){
array[j+1] = array[j];
--position;
} else {
break;
}
}

array[position] = currentValue;
}

return array;
}

//希尔排序
public static void shellsort(int[] array, int splitNum) {
if(array == null || array.length < 2){
return;
}
//分组排序
for(int k=0;k<splitNum;k++){
//将分组的数字合成一个新数组,并排序
ArrayList<Integer> tempArrayList = new ArrayList<Integer>();
for(int i=0;i<((array.length/(double)splitNum));i++) {
if(i*splitNum+k < array.length){ //避免越界
tempArrayList.add(array[i*splitNum+k]);
}
}
Integer[] tempArray = new Integer[tempArrayList.size()];
tempArray = tempArrayList.toArray(tempArray);
//将排好序的新数组重新赋值给原先分组对应的位置
int[] tempArrayInt = toIntArray(tempArray);
for(int i=0;i<tempArrayList.size();i++){
int[] arr = insertSorts(tempArrayInt);
array[i*splitNum+k] = arr[i];
}
}
}

//将Integer数组 转成 int数组
public static int[] toIntArray(Integer[] arr){
int n=arr.length;
int[] iarr=new int
;
for(int i=0;i<n;i++){
iarr[i] = arr[i].intValue();
}
return iarr;
}
}


网上版本的code:

public class ShellSort
{
private int[]    intArray;            // 待排序的数组

private int        nItems;                // 数组内元素个数

private int        maxItems;            // 数组大小

private int[]    intervalSequence;    // 增量数组序列

// 构造函数

public ShellSort( int maxItems, int[] intervalSequence )
{
this.intArray = new int[maxItems];
this.maxItems = maxItems;
this.nItems = 0;// 还没有元素

this.intervalSequence = intervalSequence;
}

/**
* 49 38 65 97 76 13 27 49 55 4
*
* 希尔排序算法,从小到大
*/
public void shellSortMethod()
{
int h = 0;//为增量

for ( int iIntervalLength = 0; iIntervalLength < intervalSequence.length; iIntervalLength++ )//最外层循环,由增量序列元素个数决定

{
h = intervalSequence[iIntervalLength];//h为index增量

int sizeInterArray;//每次内部插入排序的元素个数

if ( 0 == nItems % h )
{
sizeInterArray = nItems/h;
} else
{
sizeInterArray = nItems/h + 1;
}
for ( int jZeroToH = 0; jZeroToH < h; jZeroToH++ )//index从 0->h-1 共h-1次循环

{
int temp = 0;
int out = 0,in = 0;

/**
* 例如:
* 当h=3,intArray.lenght=10时,sizeInterArray初始化为4,
* 当jZeroToH=1,此时的内部插入排序元素index=1,4,7,为3个元素,
* 所以应该进行判断,以适应内部插入排序元素减少的情况
*/
if ( jZeroToH+(sizeInterArray-1)*h >= nItems )
{
sizeInterArray--;
}

// 内部用插入排序

// 最大有sizeInterArray个元素有待排序

for ( int i = 1; i < sizeInterArray; i++ )// 总共有sizeInterArray个元素有待排序,所以循环sizeInterArray次

{
out = jZeroToH + i * h;
temp = intArray[out];
in = out;
while ( in > h-1 && intArray[in - h] > temp )
{
intArray[in] = intArray[in-h];
in = in - h;
}
intArray[in] = temp;
}
}
System.out.print(iIntervalLength + " : h=" + h + " ");
this.displayArray();
}
}

// 插入一个元素到待排序数组

public void insert( int value )
{
if ( nItems < maxItems )
{
intArray[nItems] = value;
nItems++ ;
} else
{
System.out.println( "The array is full!" );
}
}

//初始化待排序数组

public void initArray( int[] array )
{
for ( int i = 0; i < array.length; i++ )
{
intArray[i] = array[i];
}
nItems = array.length;
}

//用随机数初始化

public void initRandom()
{
nItems = 0;
for ( int i = 0; i < maxItems; i++ )
{
int n = (int) ( java.lang.Math.random( ) * maxItems );
insert( n );
}
}

// 显示数组内容

public void displayArray()
{
System.out.print( "\t" );
for ( int i = 0; i < nItems; i++ )
{
System.out.print( intArray[i] + " " );
}
System.out.println( "" );
}

}
测试程序:
package zieckey.datastructure.study.sort;

public class ShellSortApp
{

/**
* @param args
*/
public static void main( String[] args )
{
int[] intervalSequence = { 5, 3, 1 };
int[] array = { 49, 38, 65, 97, 76, 13, 27, 49, 55, 04 };
ShellSort ss = new ShellSort( array.length, intervalSequence );
ss.initArray( array );//初始化待排序数组

System.out.print("Init array: ");
ss.displayArray();
ss.shellSortMethod();//排序

System.out.print("Sorted array: ");
ss.displayArray();
}

}


运行测试结果:
13,27,49,55,4,49,38,65,97,76,
13,4,49,38,27,49,55,65,97,76,
4,13,27,38,49,49,55,65,76,97,


希尔排序(缩小增量法)
属于插入类排序,是将整个无序列分割成若干小的子序列分别进行插入排序。希尔排序并不稳定,O(1)的额外空间,时间复杂度为O(N*(logN)^2)。最坏的情况下的执行效率和在平均情况下的执行效率相比相差不多。且较依赖分割值。(splitNum)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: