直接插入排序(Straight Insertion Sorting)的基本思想:在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

复杂度:时间复杂度  O(n2) ,空间复杂度O(1)

稳定性: 插入排序是稳定的,排序前后两个相等元素相对次序不变(能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前。)

结构的复杂性及适用情况:是一种简单的排序方法,不仅适用于顺序存储结构(数组),而且适用于链接存储结构,不过在链接存储结构上进行直接插入排序时,不用移动元素的位置,而是修改相应的指针。

哨兵的作用

 算法中引进的附加记录R[0]称监视哨或哨兵(Sentinel)。

  哨兵有两个作用:

① 进人查找(插入位置)循环之前,它保存了R[i]的副本,使不致于因记录后移而丢失R[i]的内容;

② 它的主要作用是:在查找循环中"监视"下标变量j是否越界。一旦越界(即j=0),因为R[0].key和自己比较,循环判定条件不成立使得查找循环结束,从而避免了在该循环内的每一次均要检测j是否越界(即省略了循环判定条件"j>=1")。

注意:

① 实际上,一切为简化边界条件而引入的附加结点(元素)均可称为哨兵。

【例】单链表中的头结点实际上是一个哨兵

② 引入哨兵后使得测试查找循环条件的时间大约减少了一半,所以对于记录数较大的文件节约的时间就相当可观。对于类似于排序这样使用频率非常高的算法,要尽可能地减少其运行时间。所以不能把上述算法中的哨兵视为雕虫小技,而应该深刻理解并掌握这种技巧。

 package lsg.ap.insert;
 /**
  * 插入排序算法
  *
  */
 public class InsertSort
 {
     public static void straightInsertionSort(int []array)
     {
         int sentinel , j;
         for (int i = 1; i < array.length; i++)
         {
             j = i - 1;
             sentinel = array[i];//哨兵位,作为单独的存储空间用于依次取出每一个i对应的
                                //元素,插入到前面已经排好顺序的 元素中 ,见VisualGo上的演示
                                //词句实际上是把j+1位置处的元素提前取出来了,这样往后移位就可
                                //以无数据丢失了
             while (j >= 0 && sentinel < array[j]) //升序或者降序直接修改此处的"<"为">"即可
             {
                 array[j+1] = array[j];//将大于sentinel的值整体后移一个单位
                                       //但与Sentinel的值已经排号顺序了,放心后移即可
                 j--;
             }
             array[j+1] = sentinel; //最后j指到该插入的位置,已经正好空出位置了,直接插入即可
         }
     }
     /**
      *
      * 输出相应数组的结果
      * @param array
      */
     private static void printArray(int[] array)
     {
        for(int value:array)
        {
            System.out.print(" "+value+" ");

        }
        System.out.println();
     }
     public static void main(String[] args)
     {
         // TODO Auto-generated method stub
         int[] array=new int[]{8,3,2,1,7,4,6,5};

          System.out.println("排序前数组元素为:");
          printArray(array);
          long dateStart=System.nanoTime();
          straightInsertionSort(array);
          long dateEnd=  System.nanoTime();
          long totalTime=dateEnd-dateStart;
          System.out.println("插入排序的时间复杂度为:");
          System.out.println(totalTime+"纳秒");
          System.out.println("排序后数组元素为:");
          printArray(array);
     }

 }

Java基础(47):插入排序的Java封装(含原理,可运行,哨兵位的理解见VisualGo上面的动态分析)的更多相关文章

  1. Java基础-面向对象第一特性之封装(Encapsulation)

    Java基础-面向对象第一特性之封装(Encapsulation) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.理解什么是面向过程和面向对象 面向过程与面向对象都是我们编程中 ...

  2. Java基础系列1:Java基本类型与封装类型

    Java基础系列1:Java基本类型与封装类型 当初学习计算机的时候,教科书中对程序的定义是:程序=数据结构+算法,Java基础系列第一篇就聊聊Java中的数据类型. 本篇聊Java数据类型主要包括两 ...

  3. 【Java基础】11、java方法中只有值传递,没有引用传递

    public class Example { String testString = new String("good"); char[] testCharArray = {'a' ...

  4. 【Java基础】4、java中的内部类

    内部类的分类:常规内部类.静态内部类.私有内部类.局部内部类.匿名内部类. 实例1:常规内部类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2 ...

  5. JAVA基础——面向对象三大特性:封装、继承、多态

    JAVA面向对象三大特性详解 一.封装 1.概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.好处: 只能通过规定的方法访问数据. ...

  6. Java基础语法05-面向对象-封装-包-构造器-初始化

    封装 面向对象三大特性:封装.继承.多态 封装的好处 1.调用者:方便使用/简化使用 2.设计者:安全,可控 隐藏对象内部的复杂性,只对外公开简单的接口.便于外界调用,从而提高系统的可扩展性.可维护性 ...

  7. 夯实Java基础系列5:Java文件和Java包结构

    目录 Java中的包概念 包的作用 package 的目录结构 设置 CLASSPATH 系统变量 常用jar包 java软件包的类型 dt.jar rt.jar *.java文件的奥秘 *.Java ...

  8. Java基础学习笔记八 Java基础语法之接口和多态

    接口 接口概念 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”.接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成.这样将功能的定义 ...

  9. 夯实Java基础系列1:Java面向对象三大特性(基础篇)

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 [https://github.com/h2pl/Java-Tutorial](https: ...

随机推荐

  1. php 分词 —— PHPAnalysis无组件分词系统

    分词,顾名思义就是把词语分开,从哪里分开?当然是一大堆词语里了,一大堆词语是什么?是废话或者名言.这在数据库搜索时非常有用. 官方网站 http://www.phpbone.com/phpanalys ...

  2. .Net搭建的WebService测试页使用TextArea大文本框方便调试

    用.Net搭建的WebService,系统默认提供了测试页,供大家输入参数进行测试.但因为参数输入框使用的是单行input控件,导致无法输入换行文本,使得有些参数(如换行的xml)无法输入,及其不便. ...

  3. BLE-NRF51822-实现简单扫描器

    在sdk目录 XXX:\Keil_v5\ARM\Pack\NordicSemiconductor\nRF_Examples\9.0.0\ble_central  下有官方提供的主从连接的demo. 官 ...

  4. js判断ie版本号

     jQuery 2.0 去除了对浏览器版本号的判断(它推荐特性检测),这里是一个老外写的原生判断方法,这段代码着实巧妙!既简介.有向后兼容!一般做法都是:正则搜索 USER_AGENT :但因为历史原 ...

  5. Delphi调用约定

    Register Calling Convention Ojbect Pascal的默认调用约定为register,寄存器调用约定会将前三个参数依次放入eax,edx,ecx,返回值是eax(根据类型 ...

  6. Suricata配置文件说明

    本系列文章是Suricata官方文档的翻译加上自己对其的理解,部分图片也是来自那篇文章,当然由于初学,很多方面的理解不够透彻,随着深入后面会对本文进行一定的修正和完善. Suricata使用Yaml作 ...

  7. [LeetCode]题解(python):048-Rotate Image

    题目来源 https://leetcode.com/problems/rotate-image/ You are given an n x n 2D matrix representing an im ...

  8. JS之tagNaem和nodeName

    nodeName是节点的属性,tagName是元素的属性.元素是节点的子集.不是任何节点都有tagName的,比如文本节点,仅有nodeName属性. 这个和css中的倾斜和斜体的关系是一样的.不是所 ...

  9. LeetCode Factorial Trailing Zeroes

    原题链接在这里:https://leetcode.com/problems/factorial-trailing-zeroes/ 求factorial后结尾有多少个0,就是求有多少个2和5的配对. 但 ...

  10. JQuery:JQuery删除元素

    JQuery:删除元素通过 jQuery,可以很容易地删除已有的 HTML 元素.删除元素/内容.如需删除元素和内容,一般可使用以下两个 jQuery 方法: remove() - 删除被选元素(及其 ...