算法和数据结构-排序-希尔排序(Java)

来源:互联网 发布:淘宝首页大图存放在哪 编辑:程序博客网 时间:2024/06/16 02:41

接插入排序

在上一次的论述插入排序的时候,我形象的使用了推箱子这个概念,找一些图来帮助大家理解。
□□□□□□□□□□□□□□□□□□□□□■□□□□□□□□ 假设这些箱子中装着不同的double
我们假设从头到黑箱子之前的所有白箱子已经有序了,那么现在轮到黑箱子,首先我们将黑箱子取出来,那么队列变成了
□□□□□□□□□□□□□□□□□□□□□_□□□□□□□□,然后我们的指针从黑箱子开始往前比较,知道寻找到黑箱子的合适位置(即符合顺序的位置就停下来),每往前找一次,就要将前边的箱子往后推,如图
1。□□□□□□□□□□□□□□□□□□□□□_□□□□□□□□
2。□□□□□□□□□□□□□□□□□□□□_□□□□□□□□□
3。□□□□□□□□□□□□□□□□□□□_□□□□□□□□□□
4。□□□□□□□□□□□□□□□□□□_□□□□□□□□□□□
5。□□□□□□□□□□□□□□□□□_□□□□□□□□□□□□
我们假定刚好在这个地方黑箱子找到了自己的合适位置,那么就放在这里
□□□□□□□□□□□□□□□□□■□□□□□□□□□□□□
因为我们假定之前的队列在黑箱子之前是有序的,现在相当于扩展到包括原来黑箱子的那个位置的时候也是有序的,继续这个过程,知道队列的尾部,就能够使整个队列是有序的。
之所以使用这个例子是为了让大家更好的理解插入排序,然后就能够理解希尔排序的方法了。
直接上代码来解释

package com.baiguomin.csdn;public class ShellSort {    public static double[] arrs = new double[100000];    public static void main(String[] args) {        int n = arrs.length;        for(int index=0;index<n;index++){            arrs[index]= Math.random();        }        //希尔排序可以看做是插入排序的优化,因为在插入排序中,推箱子每次只往前推了一个,        //我们在线性代数中曾经有一个概念是逆序数,如果每次箱子只往前推了一个,那么逆序数只减少1        //如果存在比较大的逆序数,我们可以大胆的多推几次,尽管这样子不能保证箱子移动的范围内的数据是否有序        //但是能够将逆序数较快的递减,这样子就能够对插入排序的箱子的移动速度加大了很多        //这个步长的选取有很多方法,我们是用最简单的方法 n/2 ...1使用这个步长队列        for(int step= n/2;step>0;step/=2){//外部选取步长            //内部是一个改造版的升级推箱子插入排序            int j;            for(int index=step;index<n;index++){                double curr = arrs[index];                for(j=index;j >= step && arrs[j-step]>curr;j--){                    arrs[j] = arrs[j-step];                }                arrs[j] = curr;            }        }    }}

接着用箱子的理论来解释
□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
这个使我们的初始队列,当步长是n/2时,相当于我们把队列变成了
□□□□□□□□□□□□□□□□□□□□□
□□□□□□□□□□□□□□□□□□□□□
这样子每一竖列的两个元素他们之间的距离就是一个step,我们就比较他们两个之间的大小,
如果不符合既定顺序,就交换,我们发现,仅仅通过一次交换,就使得该队列的逆序数减少了step,
大幅度的较少了队列的逆序数,就能够很快的提高排序的性能。
当步长是1时,我们发现,队列变成了







这个时候大家就看明白了,这就是插入排序。
就这样子我们搞定了第二个排序方法,希尔排序,还是那句话,记住推箱子这个概念,你就会理解的很清楚,我这些代码都是根据自己的描述写出来的。

0 0