排序之希尔排序

从刚开始本科学习数据结构的时候,对希尔排序就一直稀里糊涂的,弄不清到底怎么回事,重温知识,对此才稍加了解,希尔排序就是插入排序,不过它对插入排序进行了一些优化,我们之道,插入排序的性能与初始序列的排序状况有关,假设需要的排序效果是从小到达,如果给定的序列原本就是有序的,那么排序的时候只需遍历一遍数组就可以了;但是,如果给定的序列原本是逆序的,必须 5 4 3 2 1,那么对数组的中的数据(注意,这里是数据,而非数组)扫描的次数大约是(5+4+3+2+1)次,也就是说如果给定n个数据,排序的时间复杂度是O(n^2),所以,插入排序对于具有“良好有序性”的序列(也就是说序列不是逆序的)来说,其排序效果还是不错的;但是对于纯逆序的序列来说,排序效果就不是那么好了,这时候,希尔排序的优化效果就体现出来了,它的思想是这样的:先对局部序列进行数次插入排序,这样可以使整体序列趋于有序,最后对整体序列进行插入排序,就可以得到有序的序列。下面用一张图进行说明:

图中,相同颜色的数据组成一个子序列,子序列进行插入排序。这里增量step采用减半的形式求解,也就是对于长度为10的序列,step的取值为5、2、1,从图中可以看出,当step=1的时候,是对整个序列进行插入排序,这时候整个序列已经“整体有序”,所以利用插入排序对数据的访问此次不回很多。具体代码如下:

public class Test{
    public static void main(String[] args)throws InterruptedException{
        int[] array={32,56,34,23,43,45,23,54,56,31,322};
        printArray(array);
        int temp=0,x=0,i=0,j=0;
        int step=array.length;
        while(true){
            step=step/2;            
            for(x=0;x<step;x++){
                //子序列利用插入排序                
                for(i=x+step;i<array.length;i+=step){
                    temp=array[i];                    
                    for(j=i-step;j>=0 && array[j]>temp;j-=step){
                        array[j+step]=array[j];
                    }
                    array[j+step]=temp;
                }
            }
            if(step==1){
                break;                
            }
        }
        printArray(array);
    }    
    static void printArray(int[] array){
        for(int val:array){
            System.out.print(val+" ");
        }
        System.out.println();
    }
}

算法分析:希尔排序是一种不稳定的算法,单纯的插入排序是稳定的,希尔排序的空间复杂度为O(1),但是其时间复杂度:平均情况O(n^1.3)、最好情况O(n)、最坏情况难说,人们发明很多递增序列(也就是step取值)来渐进改进最坏情况下的比较次数(n^4/3,n^5/4,n^6/5......),这也说明,一个算法的出现,一定会有相应的优化策略。希尔排序和插入排序一样,同属初级排序算法。

原文地址:https://www.cnblogs.com/codeMedita/p/7424109.html