基本排序方式——(二)插入排序和希尔排序

插入排序和希尔排序


1.插入排序
  • 算法思想(升序)

1.从第一个元素开始,一般默认第一个元素已经排好序列。
2.从第二个元素开始,从后向前扫描已经排好序的序列。
3.如果已排好序列的最后的一个元素大于当前元素,则插入到最后一个元素前面。
4.重复步骤3,直到找到已排好序的最后一个元素大于等于此元素或者这个元素前面没有比它大的时候停止。
5.重复2-5步骤

  • 举例说明:
  int arr[]={100, 25, 87, 2, 4, 90, 17, 69, 34, 19, 40}
  
 (1)25,100,87,2,4,90,17,69,34,19,40(25)
 (2)25,87,100,2,4,90,17,69,34,19,40(87)
 (3)25,87,100,2,4,90,17,69,34,19,40(100)
 (4)25,87,2,100,4,90,17,69,34,19,40(2)
      25,2,87,100,4,90,17,69,34,19,40
      2,25,87,100,4,90,17,69,34,19,40
      ......
  直到:2 4 17 19 25 34 40 69 87 90 100 
  • 算法设计(个人理解不一定正确)

(1) 很显然,需要用双层循环,外层循环负责编译整个数组(从第二个数开始),内层循环负责控制当前的数和已排好序列的数比较。
(2)外层初始值,循环终止条件都有,所以用for循环就可以;内层我觉得用while循环比较方便。所以我认为这道题的难点就是如何确定内层循环的终止条件以及当当前元素前方有多个元素符合条件时,如何处理。
(3)解决办法,用已排好序列的最后一个元素下标作为条件,满足条件时,减一,直到小于0;

package org.wetmo.demo1;
public class democharu {
    public static void main(String[] args) {
        int[] arr={100, 25, 87, 2, 4, 90, 17, 69, 34, 19, 40};
        show(arr);
    }
    public static void show(int[] a){
        for(int i=1;i<a.length;i++){
            int j=i-1;    //因为比较的是当前元素和前一个元素的大小,所以j这样定义
            while (j>=0){
                if(a[i]<a[j]){
                   int t=a[i];
                   a[i]=a[j];
                   a[j]=t;
                   i=j; //这也是一个难点,但是仔细观察他们之间的关系,以及代入具体的值进行演算,就能得出。
                   j--;
                }else{
                    break;
                }
            }
        }
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]+" ");
        }
    }

}

2.希尔排序

  • 基本思想
    希尔排序是插入排序的高效版,插入排序是比较相邻两个两个元素的大小,而希尔排序可以理解为大跨度的比较两个元素的位置。为乐更好的理解,我们用分组的形式(是为了增大数据比较的下表间隔跨度)来演示这个问题,注意,分组的紧急是为了理解希尔排序,代码中并没有真正意义上的分组,千万不要受这个分组的影响。
  • 举例
数组为 a[] ={100, 25, 87, 2, 4, 90, 17, 69, 34, 19, 40}
(1)第一次分组:n=a.length/2=5
   {100,90,40} {25,17} {87,69} {2,34} {4,19} 
   组内进行插入排序:{40,90,100} {17,25} {69,87} {2,34} {4,19}
   新数组为:{40,17,69,2,4,90,25,87,34,19,100}
(2)第二次分组:n=5/2=2
   {40,69,4,25,34,100} {17,2,90,87,19}
   组内进行插入排序:{4,25,34,40,69,100}  {2,17,19,87,90}
   新数组为:{4,2,25,17,34,19,40,87,69,90,100}
(3)第三次分组:n=2/2=1
   n=1所以不用再分,只需对上一步的新数组进行插入排序
   最终结果是{2,4,17,19,25,34,40,69,87,90,100}
  • 难点解析(完全个人理解不一定正确)

1.首先要明白这个算法的基本结构,与插入排序相比,希尔排序可以说新增加了一个增量,为了增大数据比较的下标间隔跨度,减少元素的移动次数,以提高排序效率,所以增量的变化就是最外层循环,然后再加个插入排序的算法就好了,一开始我受到前面的分组的影响,写了四重循环,后来才发现只需给插入排序加一个增量就好了,不需要写多余的东西。
2.既然我们都知道了希尔排序是为了增加数据比较的间隔跨度,所以再这个增量下,找到数据间隔跨度后插入排序时当前元素与要比较的元素的位置关系就是这个问题的关键。
3.通过举例子我们可以发现增量与元素位置的关系,i与(i+每次的增量值)就是插入排序中需要比较的两个元素。就是需要比较的两个元素位置之间差了一个增量。而插入排序中这个增量是固定的,是0;

package org.wetmo.demo1;
public class Demoxier {
    public static void main(String[] args) {
        int[] arr = {100, 25, 87, 2, 4, 90, 17, 69, 34, 19, 40};
        show(arr);
    }
    public static void show(int[] a) {
        int n = a.length;
        for (int i = n / 2; i>0; i = i / 2) {
                for (int k = i ; k < a.length; k = k + i) { //所以下一个k的取值就是k+i
                    int t = k-i;  //这个等式:因为k=i的,它要和前一个数进行比较,前一个数就是k-i(i就是每次的增量值)其他基本和插入排序一样
                    while (t >= 0){
                        if (a[k]<a[t]) {
                            int tmp = a[k];
                            a[k] = a[t];
                            a[t] = tmp;
                             k=t;
                            t = t - i;
                        }else{
                            break;
                        }
                    }
                }
        }
        for (int i= 0; i < a.length; i++) {
            System.out.print(a[i]+" ");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值