预备知识

排序算法从功能上是对一个数据元素集合或序列重新排列成一个按数据元素某个相知有序的序列。从内存空间使用简单上看分为内部排序和外部排序。

内部排序是数据记录在内存中进行排序,适合不太大的元素序列。而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。

排序算法稳定性是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。比如:Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前。

排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就 是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。另外,如果排序算法稳定,对基于比较的排序算法而言,元素交换 的次数可能会少一些。

插入排序—直接插入排序

基本算法:

每次从无序表中取出第一个元素,把它插入到前面已经排好序的子序列中的合适位置,使有序表仍然有序。即先将序列的第1个元素看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。

直接插入排序示例:

直接插入排序有二种实现方式,带哨兵与不带哨兵。

带哨兵的插入排序中的哨兵元素有两个作用:

1、暂时存放待插入的元素,相当于临时存储元素。

2、可以防止数组下标越界,当待插入的元素小于已排序的子数组中的最小元素时,j=-1,越界,而采用哨兵,arr[0]

带哨兵需要注意一个问题:有方法传进来的数组时原始数组,则插入第一个元素时,a[0]会被覆盖,造成最终排完序的数组缺少了原始数组的第一个元素(bug)。

解决办法:在调用此方法之前,将数组做下处理,使其右移一个元素的位置,空出来的第0个元素初始化为0(或不做初始化)。

/**

* 带哨所

*

* @param sortList

*/

public static void insertSort1(Integer[] sortList) {

int len = sortList.length;

for (int i = 2; i < len; i++) {

if (sortList[i] < sortList[i - 1]) {

int j = i - 1;

sortList[0] = sortList[i];// 设置哨所

while (sortList[0] < sortList[j]) {

sortList[j + 1] = sortList[j];

j--;

}

sortList[j + 1] = sortList[0];

}

}

}

/**

* 不带哨所

*

* @param sortList

*/

public static void insertSort2(Integer[] sortList) {

int len = sortList.length;

for (int i = 1; i < len; i++) {

if (sortList[i] < sortList[i - 1]) {

int j = i - 1;

int temp = sortList[i];

while (j >= 0 && temp < sortList[j]) {

sortList[j + 1] = sortList[j];

j--;

}

sortList[j + 1] = temp;

}

}

}

算法复杂度

1、时间复杂度:O(n^2)

直接插入排序耗时的操作有:比较+后移赋值。时间复杂度如下:

1)最好情况:序列是升序排列,在这种情况下,需要进行的比较操作需(n-1)次。后移赋值操作为0次。即O(n)。

2)最坏情况:序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。后移赋值操作是比较操作的次数加上 (n-1)次。即O(n^2)。

3)渐进时间复杂度(平均时间复杂度):O(n^2)。

2、空间复杂度:O(1)

直接插入排序是在原输入数组上进行后移赋值操作的(称“就地排序”),所需开辟的辅助空间跟输入数组规模无关,所以空间复杂度为:O(1)

稳定性

直接插入排序是稳定的,不会改变相同元素的相对顺序。

算法优化:

二分查找插入排序的原理:是直接插入排序的一个变种,在有序区中查找新元素插入位置时,为了减少元素比较次数提高效率,采用二分查找算法进行插入位置的确定。

/**

* 二分查找插入排序

* @param sortList

*/

public static void insertSort3(Integer[] sortList) {

int len = sortList.length;

for (int i = 1; i < len; i++) {

if (sortList[i] < sortList[i - 1]) {

//二分查找在有序区寻找插入的位置

int index = binarySearchIndex(sortList, i-1, sortList[i]);

if (i != index)

{

int temp = sortList[i];

// 后移元素,腾出arr[index]位置

for (int j = i - 1; j >= index; j--)

sortList[j + 1] = sortList[j];

// 将 arr[i] 放到正确位置上

sortList[index] = temp;

}

}

}

}

/**

* 二分查找要插入的位置得index

* @param sortList

* @param maxIndex

* @param data

* @return

*/

private static int binarySearchIndex(Integer[] sortList, int maxIndex, int data)

{

int iBegin = 0;

int iEnd = maxIndex;

int middle = -1;

while (iBegin <= iEnd)

{

middle = (iBegin + iEnd) / 2;

if (sortList[middle] > data)

{

iEnd = middle - 1;

}

else

{

iBegin = middle + 1;// 如果是相同元素,也是插入在后面的位置

}

}

return iBegin;

}

算法复杂度

1、时间复杂度:O(n^2)

二分查找插入位置,因为不是查找相等值,而是基于比较查插入合适的位置,所以必须查到最后一个元素才知道插入位置。

二分查找最坏时间复杂度:当2^X>=n时,查询结束,所以查询的次数就为x,而x等于log2n(以2为底,n的对数),即O(log2n)。所以,二分查找排序比较次数为:x=log2n。

二分查找插入排序耗时的操作有:比较 + 后移赋值。时间复杂度如下:

1)最好情况:查找的位置是有序区的最后一位后面一位,则无须进行后移赋值操作,其比较次数为:log2n ,即O(log2n)。

2)最坏情况:查找的位置是有序区的第一个位置,则需要的比较次数为:log2n,需要的赋值操作次数为n(n-1)/2加上 (n-1) 次,即O(n^2)。

3)渐进时间复杂度(平均时间复杂度):O(n^2)。

2、空间复杂度:O(1)

二分查找插入排序是在原输入数组上进行后移赋值操作的(称“就地排序”),所需开辟的辅助空间跟输入数组规模无关,所以空间复杂度为:O(1)。

稳定性

二分查找排序是稳定的,不会改变相同元素的相对顺序。

相关附件直接插入排序下载:

------------------------------------------分割线------------------------------------------

具体下载目录在 /2014年资料/12月/12日/经典(Java版)排序算法的分析及实现之一直接插入排序

------------------------------------------分割线------------------------------------------

java插入排序实现,经典(Java版)排序算法的分析及实现之一直接插入排序相关推荐

  1. 经典十大排序算法(含升序降序,基数排序含负数排序)【Java版完整代码】【建议收藏系列】

    经典十大排序算法[Java版完整代码] 写在前面的话 十大排序算法对比 冒泡排序 快速排序 直接选择排序 堆排序 归并排序 插入排序 希尔排序 计数排序 桶排序 基数排序 完整测试类 写在前面的话   ...

  2. java实现apriori算法_七大经典、常用排序算法的原理、Java 实现以及算法分析

    0. 前言 大家好,我是多选参数的程序员,一个正再 neng 操作系统.学数据结构和算法以及 Java 的硬核菜鸡.数据结构和算法是我准备新开的坑,主要是因为自己再这块确实很弱,需要大补(残废了一般) ...

  3. 我们一起来排序——使用Java语言优雅地实现常用排序算法

    破阵子·春景 燕子来时新社,梨花落后清明. 池上碧苔三四点,叶底黄鹂一两声.日长飞絮轻. 巧笑同桌伙伴,上学径里逢迎. 疑怪昨宵春梦好,元是今朝Offer拿.笑从双脸生. 排序算法--最基础的算法,互 ...

  4. java中常用的几种排序算法--常见笔试面试

    转载:http://blog.csdn.net/ygc87/article/details/7208082 以下列出Java中常用的几种排序算法,只是简单实现了排序的功能,还有待改进,望指教(以下均假 ...

  5. java实现apriori算法_各种排序算法的分析及java实现(一)

    阅读本文约需要7分钟 大家好,我是你们的导师,我每天都会在这里给大家分享一些干货内容(当然了,周末也要允许老师休息一下哈).上次老师跟大家分享了下用Navicat for Mysql导入.sql文件的 ...

  6. dv算法java实现_各种排序算法的分析及java实现(二)

    更多精彩,请点击上方蓝字关注我们! 上次跟大家分享了下各种排序算法的分析及java实现(一)的相关知识,今天跟大家分享各种排序算法的分析及java实现(二)的知识.昨天我们讲到了选择排序,今天我们继续 ...

  7. 经典的十种排序算法 C语言版

    经典的十种排序算法(C语言版) 1.冒牌排序 冒牌排序的特点 ​ 一趟一趟的比较待排序的数组,每趟比较中,从前往后,依次比较这个数和下一个数的大小,如果这个数比下一个数大,则交换这两个数,每趟比较后, ...

  8. 希尔排序算法(思路分析) [数据结构][Java]

    希尔排序算法(思路分析) 希尔排序也称之为: 缩小增量排序 希尔排序提出的背景: 因为简单插入排序中存在一些问题( 这里我们以升序排序为例 ): 当我们要待插入的数值比较小时后移的次数明显增多,对效率 ...

  9. 算法 经典的八大排序算法详解和代码实现

    算法 经典的八大排序算法详解和代码实现 排序算法的介绍 排序的分类 算法的时间复杂度 时间频度 示例 图表理解时间复杂度的特点 时间复杂度 常见的时间复杂度 空间复杂度 排序算法的时间复杂度 冒泡排序 ...

最新文章

  1. 分布式锁用Redis好?还是Zookeeper好?
  2. HTML 基础知识回顾
  3. 对软件体系结构的认识
  4. 常用PHP array数组函数
  5. Android之关于电话录音原理,目前的方法还是只能录MIC
  6. 给刚入行的存储工程师10+1点建议
  7. java网络通信:HTTP协议
  8. 吉林大学操作系统概论
  9. 隧道联系测量高程传递水准数据处理流程及说明
  10. 读书虽苦,却是最容易的那条!
  11. [案例4-4]学生和老师
  12. RabbitMQ学习笔记
  13. 2019Java视频教程-Spring Boot实战
  14. Oracle中Clob类型处理解析
  15. Word恢复文本转换器-修复损坏的WORD文件
  16. 留几手:互联网创业到底是咋回事(说得真经典,创业者不创业的都值得一看)
  17. 怎么把paper快快读了
  18. Java实现几分钟之后调度任务的定时器
  19. iOS- JSPatch 热更新
  20. syslog详解及配置远程发送日志和远程日志分类

热门文章

  1. 【mac】mac 安装nginx
  2. 95-10-080-启动-replicaManager副本管理器
  3. 40-10-010-运维-kafka-2.11-基本操作
  4. 【Windows】Windows 下 使用 nc 命令 开启socket
  5. 【Ranger】mac下Apache Ranger编译安装
  6. 21-win10下ElasticSearch.6.1.0安装SQL插件
  7. Builder内部类
  8. 面试经常被问到这 4 大开源框架,必须得好好研究一下了!
  9. springMVC数据格式转换的三种实现
  10. c++禁止进程被结束_第四章 进程管理