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

希尔排序:

* 基本思想: 先取一个小于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[n]; 
		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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值