数据结构与算法(1)插入排序

插入排序,字面意思可以理解为:利用插入元素的手法将乱的数组按顺序排序。插入的手法指的是在一个已经排序好的元素中插入元素,多次重复插入达到排序的效果。

简单的总结为:在不打乱排序好的数组中,循环插入到排序好的数组中。

比如:现在有数组[2,3,4,5,3,4,1]需要从小到大进行排序,在数组中[2,3,4,5]是已经排好序的元素。在不打乱顺序的情况下,将第5个元素3插入排序好的元素中。多次重复操作将整个数组排序完成。

如何执行插入的操作呢?

我们可以想象成,3把位置空出来,在排序好的元素[2,3,4,5]中找到进行比较,找到位置,将比3大的都往后挪一个位置。

image-20201027204401705.png

以此类推,重复插入步骤,实现排序。

如何用代码实现呢?

人思考的时候和代码会有一定差别。比如,把3的位置空出来,挪动位置,大脑可以记住位置上原来是3,电脑却记不住,挪动位置后3就会被覆盖掉。因此我们需要将3赋值给一个变量保证3不会被覆盖掉。

public static void main(String[] args) {

        int[] arrNum = {2, 3, 4, 5, 3};


        /*
         * 步骤1:空出位置
         * */

//    将3赋值给一个变量,保证挪动位置不会被覆盖掉,
        int currentNum = arrNum[4];


        /*
         * 步骤 2:进行比较,查找位置
         *
         * */

//    排序好的最大下标为3
        int i = 3;
//    从后往前遍历排序好的数组
//    当第一次遇到比3小的时候,3的位置就在这个位置的后一个。如果第i个元素大于currentNum继续执行循环
        while (i >= 0 && arrNum[i] > currentNum) {

            i--;
        }
        System.out.println("3的需要放的位置是" + (i + 1));

        /*
         *  步骤3:挪动位置
         *     将3需要放置的位置到排序好的最后一个位置进行往后挪一个位置,
         *     由于从前往后,会覆盖掉后面的数,需要在定义一个变量,才能实现,
         *     而3的位置空出,因此采用从后往前挪的方式进行挪动。
         * */

        for (int j = 3; j >= i + 1; j--) {
            arrNum[j + 1] = arrNum[j];
        }
//    将空出的位置用-1代替方便观察
        arrNum[i + 1] = -1;
        System.out.print("挪动位置:");
        for (int item : arrNum) {
            System.out.print(item + ",");
        }
        System.out.println();

//    将3放入位置
        arrNum[i + 1] = currentNum;
        System.out.print("放入:");
        for (int item : arrNum) {
            System.out.print(item + ",");
        }


    }

运行效果如下:

image-20201028090050794.png

我们可以将代码中的几个定量修改为变量,就可以实现n个元素数组的一次排序,但数组是有条件的:数组需要满足前n-1个元素是从小到大排序的。

public static void main(String[] args) {

      int[] arrNum = {2, 3, 4, 5, 3};
      sort(arrNum);
      int[] arrNum2 = {6, 7, 8, 8, 11, 20, 4};
      sort(arrNum2);

   }

   private static void sort(int[] arrNum) {


      /*
       * 步骤1:空出位置
       * */

//    将3赋值给一个变量,保证挪动位置不会被覆盖掉,
//    !!!!!改动
      int currentNum = arrNum[arrNum.length - 1];

      /*
       * 步骤 2:进行比较,查找位置
       *
       * */

//    排序好的最大下标为3
      //    !!!!改动
      int i = arrNum.length - 2;
//    从后往前遍历排序好的数组
      while (i >= 0 && arrNum[i] > currentNum) {
//       当第一次遇到比3小的时候,3的位置就在这个位置的后一个。

         i--;
      }
//    !!!!!改动
      System.out.println(currentNum+ "的需要放的位置是" + (i + 1));

      /*
       *  步骤3:挪动位置
       *     将3需要放置的位置到排序好的最后一个位置进行往后挪一个位置,
       *     由于从前往后,会覆盖掉后面的数,需要在定义一个变量,才能实现,
       *     而3的位置空出,因此采用从后往前挪的方式进行挪动。
       * */

//    改动
      for (int j = arrNum.length - 2; j >= i + 1; j--) {
         arrNum[j + 1] = arrNum[j];
      }
//    将空出的位置用-1代替方便观察
      arrNum[i + 1] = -1;
      System.out.print("挪动位置:");
      for (int item : arrNum) {
         System.out.print(item + ",");
      }
      System.out.println();

//    将3放入位置
      arrNum[i + 1] = currentNum;
      System.out.print("放入:");
      for (int item : arrNum) {
         System.out.print(item + ",");
      }
      System.out.println();
   }

效果如下图:

image-20201028091345570.png

由小推大:我们把一个乱序的数组拆解多次重复上述操作。那么数组的条件怎么满足呢。我们可以先把第一个元素看成是一个有序的数组,因为只有一个元素所以无论如何都是有序的,这样就从前两个开始进行上述操作直至最后一个。这样就排好序了。

public static void main(String[] args) {

      int[] arrNum = {2, 3, 4, 5, 3,2,47,5,753,3};
      sort(arrNum);
      int[] arrNum2 = {6, 7, 8, 8, 11, 20, 4};
//    sort(arrNum2);

   }

   private static void sort(int[] arrNum) {


      for (int n = 1; n < arrNum.length; n++) {
         /*
          * 步骤1:空出位置
          * */

//    将3赋值给一个变量,保证挪动位置不会被覆盖掉,
//    改动
         int currentNum = arrNum[n];

         /*
          * 步骤 2:进行比较,查找位置
          *
          * */

//    排序好的最大下标为3
         //    改动
         int i = n-1;
//    从后往前遍历排序好的数组
         while (i >= 0 && arrNum[i] > currentNum) {
//       当第一次遇到比3小的时候,3的位置就在这个位置的后一个。

            i--;
         }
//    改动
         System.out.println(currentNum + "的需要放的位置是" + (i + 1));

         /*
          *  步骤3:挪动位置
          *     将3需要放置的位置到排序好的最后一个位置进行往后挪一个位置,
          *     由于从前往后,会覆盖掉后面的数,需要在定义一个变量,才能实现,
          *     而3的位置空出,因此采用从后往前挪的方式进行挪动。
          * */

//    改动
         for (int j = n-1; j >= i + 1; j--) {
            arrNum[j + 1] = arrNum[j];
         }
//    将空出的位置用-1代替方便观察
         arrNum[i + 1] = -1;
         System.out.print("挪动位置:");
         for (int item : arrNum) {
            System.out.print(item + ",");
         }
         System.out.println();

//    将3放入位置
         arrNum[i + 1] = currentNum;
         System.out.print("放入:");
         for (int item : arrNum) {
            System.out.print(item + ",");
         }
         System.out.println();
      }


   }

运行效果如下:

image-20201028093640570.png

优化

现在效果已经实现了,但是代码可以繁琐,我们可以进行优化。我们在进行找位置后进行挪位置。那么我们在找位置的时候,可以 一边找位置一遍进行挪位置吗?答案是可以的,我们可以在找位置的时候,当前元素和排序好的数组元素进行比较时,如果当前的元素比较小那我们是不是可以把他们的位置进行互换挪位置,这样当我们找到位置时,比当前元素大的元素都已近在找位置比较时进行过位置的移动了。后面的挪动位置和放入元素我们就合并在一起操作了。

image-20201028094754191.png

代码如下:

    public static void main(String[] args) {

      int[] arrNum = {2, 3, 4, 5, 3, 2, 47, 5, 753, 3};
      sort2(arrNum);
      int[] arrNum2 = {6, 7, 8, 8, 11, 20, 4};
//    sort(arrNum2);

   }

   

   private static void sort2(int[] arrNum) {
      for (int i = 0; i < arrNum.length; i++) {
//       1.空出位置
         int currentNum = arrNum[i];
//       2.找位置的同时进行互换挪位置
         int j = i - 1;
         while (j >= 0 && arrNum[j] > currentNum) {
//          互换挪位置
            arrNum[j + 1] = arrNum[j];
            j--;
         }
//       放入
         arrNum[j + 1] = currentNum;
      }

      for (int i : arrNum) {
         System.out.print(i + ",");
      }
   }
image-20201028095507632.png

举一反三

对于排序我们不仅需要会从小到大,我们还可以从大到小、通过找出中间数,以中间数为中心,一边从大到小,一边从小到大等等一系列排序。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343