插入排序

插入排序的基本思想是将待排序的元素依次插入序列合适的位置,然后将这个位置后面的元素依次向后移动一位
位置1 2 3 4 5 6
序列5 4 2 1 8 3
设第1位为最初始的基础元素,也就是5,待排元素就是4,此时逻辑顺序是5|4 2 1 8 3(用“|”来表示排序到哪个位置了)
那么第一趟排序下来后,
序列变成:45|2183。
待排元素就是2,第2趟后,245|183
待排元素就是1,第3趟后,1245|83
待排元素就是8,第4趟后,12458|3
待排元素就是3,第5趟后,123458|
这样就排序成功了。

上面就是插入排序,数学逻辑上非常清晰,序列可以分为两个区,有序区和混乱区。第一步,我们要做的就是每次从混乱区取出一个混乱元素插入到有序区的序列排布中,那么如何插入呢?就要看第二步的内容了。

第一步如何取出元素呢?显然是要将每个元素(除去预置的那个)都取出一遍,那么用个for循环遍历整个序列就行。

伪代码

        for(int i = 1;i < arr.length;i++){
            temp = arr[i];

        }

第二步,执行插入步骤,这一步需要做两个事情,1寻找合适的位置,2插入后将其他元素往后移动一位

(1)如何寻找合适的位置呢?

有序区的元素默认都是从小到大排列的,都是有顺序的,那么就好办了,只要找到合适的位置就行,然后移动后面元素的位置就行。

例如
序列 12458|3
3先和1比较,不合适;
3再和2比较,不合适;
3再和4比较,合适,找到位置了。
3再和2比较,2小,不符合要求,不挪动;
3再和1比较,1小,不符合要求,不挪动;

实现这个逻辑最简单就是用一个for循环,设置一个条件和边界,去遍历一遍。

(2)接下来处理一个问题就是讲元素往后挪动一位。

既然我们已经找到这个边界了,那么只需要把这个边界后面的元素依次往后挪动一位就可以了。

这里就又是一个for循环,边界是“合适位置+1”到“当前待排元素的位置”。

所以这个排序就是一个for循环里面嵌入两个for循环

下面是伪代码

for(){//处理所有元素的遍历
    temp = 待处理的元素
    for(){//这个循环用来寻找合适的位置
    }
    for(){//这个循环用来将那些元素依次向后挪动
    }
}

这样确实可以实现,算法时间复杂度可以算做O(n^2),但是用两个for循环在里面,写起来有些冗长有没有更好的解决办法呢?将编写的复杂度下降一些呢?


解决办法就是在寻找合适位置这一步时,从后往前遍历,每对比到一个不合适的元素,就把这个元素往后挪动一位。

例如
序列 12458|3
temp = 3;
3先和8比较,不合适,挪动后1245 8;
3再和2比较,不合适,挪动后124 58;
3再和4比较,合适,找到位置了,挪动后123458;
3再和2比较,2小,不符合要求,不挪动;
3再和1比较,1小,不符合要求,不挪动;

这样边比较边挪动的做法,可以将寻找位置和挪动元素的操作结合起来,放到一个遍历循环中。

下面就不赘述了,放源码。

package com.chapter.five;
/**
 * 需求 直接插入排序法
 * 思路 1将一个数组,分成两个区,一个是有序区,一个是无序区
 * 2每次取出无序区的一个元素,到有序区排序
 * 3排序的原则是待排元素依次与有序区元素进行比较,插入到合适地方
 * 4插入时,待排元素放在该位置,后面的元素依次向后移一位
 * 排成从小到大
 * @author huxingyue
 *
 */

class InsertSort {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        InsertSort insert = new InsertSort();
        int[] arr = new int[]{10,1,9,2,8,3,7,4,6,5};
        System.out.print("数组排序前是:");
        for(int i:arr){
            System.out.print(i+" ");
        }

//      insert.funLowToHigh(arr);
        insert.funHighToLow(arr);

        System.out.print("数组排序后是:");
        for(int i:arr){
            System.out.print(i+" ");
        }

    }
    void funLowToHigh(int[] arr){   //这个插入排序是从小到大的
        int temp;   //用于存放临时元素
        for(int i = 1;i < arr.length;i++){
            temp = arr[i];//设temp为取出的待排混乱元素
            int j =0;
            for(j = i-1 ; j >= 0 && temp < arr[j];j--){
                arr[j+1] = arr[j];  //如果临时值与对比元素相比,临时值小,那对比元素就往后移动一位
            }
            arr[j+1] = temp;    // 这一步j已经自减1了

        }
    }

    void funHighToLow(int[] arr){   //这个插入排序是从大到小的
        int temp;
        for(int i = 1;i < arr.length;i++){
            temp = arr[i];
            int j = 0;
            for(j = i-1;j >= 0 && temp > arr[j];j--){
                arr[j+1] = arr[j];  //如果临时值与对比元素相比,临时值大,那对比元素就往后移动一位
            }
            arr[j+1] = temp;    // 这一步j已经自减1了
        }

    }

}

写在最后,讲一讲个人对插入排序的理解。

本质上来讲,插入排序和冒泡排序都属于一类排序,即比较相邻两个数,然后操作相邻数的一个过程。

如果一个序列中有两个数,a1和a2,且a1>a2,则命名为一个比较对,插入排序的算法和比较对的数量有关系,因为仅仅存在一个比较对的时候,才会进行操作,数据向后移动,也就是说,忽略验证内层循环条件的时间,那么确定了比较对的数量,插入排序的时间复杂度变成了一个一元线性的函数,设序列中有9个比较对,序列长度为n,那么总时间就是9n,而不是我们通常意味的n*n。

关于上面的描述很潦草,具体权威的描述可以参考《数据结构与算法java版》作者Mark Allen Weiss中,关于插入排序的解读,醍醐灌顶值得一看。

如果想改善这种算法的性能几乎不大可能,因为他总是比较相邻的元素,如果想提高性能,就要比较相隔远一点的元素,然后再操作,可以参考希尔排序。或者使用全新的排序方法,例如快速排序。

Java温故而知新-插入排序的更多相关文章

  1. Java温故而知新-杨辉三角形

    Java温故而知新-杨辉三角形 一. 先说需求 需求 打印输出杨辉三角形,行数可变,支持50行内的任意数. 预期结果如图所示 1 这是第几行呢,是第1 1 1 这是第几行呢,是第2 1 2 1 这是第 ...

  2. 疯狂的Java算法——插入排序,归并排序以及并行归并排序

    从古至今的难题 在IT届有一道百算不厌其烦的题,俗称排序.不管是你参加BAT等高端笔试,亦或是藏匿于街头小巷的草根笔试,都会经常见到这样一道百年难得一解的问题. 今天LZ有幸与各位分享一下算法届的草根 ...

  3. JAVA排序--[插入排序]

    package com.array; public class Sort_Insert { /* * 项目名称:插入排序 ; * 项目要求:用JAVA对数组进行排序,并运用插入排序算法; * 作者:S ...

  4. Java直接插入排序

    插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入. 算法步骤: 1)将第一待排序序列第一个元素看做一个有序序列,把第二 ...

  5. 【Java SE】如何用Java实现插入排序

    摘要:前面三期分别写了三篇简单排序的算法,今天来讲一点稍微难一点的排序算法-----插入排序. 基本思想: 设n个数据已经按照顺序排列好(假定从小排到大). 输入一个数据x,将其放在恰当的位置,使其顺 ...

  6. JAVA数据结构--插入排序

    插入排序(英语:Insertion Sort)是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上,通常采用in- ...

  7. Java实现插入排序

    package Sort; import java.util.Arrays; public class InsertionSort { public static int[] sort(int[] l ...

  8. java 用插入排序思想,对不规则数组排序。

    知道插入排序后,无意中发现,用插入排序思想,对不规则数组排序的排序 发现和许多大神写的不一样,大神写的简洁多了.--------

  9. Java算法-插入排序

    插入排序的基本思想是在遍历数组的过程中,假设在序号 i 之前的元素即 [0..i-1] 都已经排好序,本趟需要找到 i 对应的元素 x 的正确位置 k ,并且在寻找这个位置 k 的过程中逐个将比较过的 ...

随机推荐

  1. win10下安装python2与python3以及pip共存

    一 分别安装python2和python3 注意: 安装时记得勾选 Add Python.exe to Path 二 安装pip Python3最新版本有pip,无需安装 Python2: 下载pip ...

  2. 初学安卓开发随笔之 Intent 用法

    首先,对于安卓开发,目前世界上流行的是使用的是Android studio 2.0 .(hh 学着来呗 书上说用这个,,) 今后就定一个计划 每天更新一个Android 随笔,增强一下自控力吧!!! ...

  3. 【css】盒子模型 之 弹性盒模型

    参考: http://caibaojian.com/flexbox-guide.html 待补充啊

  4. 老生常谈之SQL Server (行转列,列转行)

    Open the first article 在本文章中主要介绍以下内容: 1.静态行转列 2.静态列转行 3.动态行转列 4.动态列转行 1.静态行转列 --静态的行转列 --新建一个科目成绩表 - ...

  5. springboot用thymeleaf模板的paginate分页

    本文根据一个简单的user表为例,展示 springboot集成mybatis,再到前端分页完整代码(新手自学,不足之处欢迎纠正): 先看java部分 pom.xml 加入 <!--支持 Web ...

  6. Mybatis框架分析

    摘要 本篇文章只是个人阅读mybatis源码总结的经验或者个人理解mybatis的基本轮廓,作为抛砖引玉的功能,希望对你有帮助,如果需要深入了解细节还需亲自去阅读源码. mybatis基本架构 myb ...

  7. 一步一步学习Vue(十一)

    本篇继续学习vuex,还是以实例为主:我们以一步一步学Vue(四)中讲述的例子为基础,对其改造,基于vuex重构一遍,这是原始的代码: todolist.js ; (function () { var ...

  8. Linux(2)文件和权限

    用户目录 位于/home/user, 称为用户目录或家目录, 表示方法: /home/user ~ 相对路径和绝对路径 绝对路径 从 / 目录开始描述的路径外绝对路径 cd /home cd /usr ...

  9. 表达式求值(二叉树方法/C++语言描述)(四)

    代码清单 // binarytree.h #ifndef BINARYTREE_H #define BINARYTREE_H template <typename T> class Bin ...

  10. geotrellis使用(三十)使用geotrellis读取PostGIS空间数据

    前言 最近事情很多,各种你想不到的事情--such as singing and dancing--再加上最近又研究docker上瘾,所以geotrellis看上去似乎没有关注,其实我一直在脑中思考着 ...