直接插入排序

时间:2022-04-10 12:25:05

欢迎Java爱好者品读其他算法详解:

简单比较排序:http://blog.csdn.net/ysjian_pingcx/article/details/8652091

冒泡排序:        http://blog.csdn.net/ysjian_pingcx/article/details/8653732

选择排序:        http://blog.csdn.net/ysjian_pingcx/article/details/8656048

快速排序:        http://blog.csdn.net/ysjian_pingcx/article/details/8687444

快速排序优化:http://blog.csdn.net/ysjian_pingcx/article/details/8687444


直接插入排序<详解> 这几天为了工作和毕业设计的事,折腾的,感觉挺累,而且很乱,好几天没有写博客了,有几天没有静下来做我喜欢做的事情了:写代码。今天给自己一点时间,让自己静一静,接着以前的路程,将排序法写下去。前面写了比较排序,冒泡排序,选择排序加上今天的直接插入排序,这四个排序都属于简单的排序,时间复杂度都是O(n²)。 不懂得直接插入排序的人应该打过牌,在揭牌的时候,我们会将5插入到3和6之间,后面揭到4就会好像无意识的插入到3和5之间,比如下面的几张牌: 直接插入排序
@此时我们会将2放到3的左边,然后将4插入到3和5之间,这样就有序了。 直接插入排序
@就以上面的简单的理牌为例,分析插入排序的过程: 第一轮:从下标为一的记录开始,就是5,此时先将5出列,并记录空缺的位置,再将5与之前的每一个元素进行比较,比较5>3,是正序,就不用移动,比较完毕,5回归到空缺的位置,进入下一轮; 第二轮:从下标为二的记录开始,就是4,此时先将4出列,并记录空缺的位置,再将4与之前的每一个元素进行比较,比较4<5,是反序,就将5后移,空缺位置变为之前5所在的位置,然后比较4>3正序,不用移动,比较完毕,将4置于新的空缺位置。 ......
直接插入排序:将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录增加1的有序表。
大学军训: 刚来大学时,大家都是从五湖四海过来,兴奋激动不已,军训第一天,都满怀期待来到操场集合,都想站前排展现一下下自己,于是乎一开始大家就先来先到,一个挨着一个站着,参差不齐,甚是难看,结果教官来了,看后有点生气,然后急中生智,就雷厉风行:“第二个,王小二,你要是比前面的同学矮点就站出来,王小二前面的同学,如果王小二站出来了,自己就看看,如果比王小二高就往后一步走(假设一个人刚好占据了一步的距离空间),结果王小二一看,比最前面的白大褂高一点就没有站出来了。然后,从王小二后面的每一位同学,依次看看,如果比前面的同学矮点就出列,出列同学前面的同学好好看看,如果比出列同学高的同学,自觉往后移动一步,然后出列的同学站到最后空缺的位置...”不到十分钟,一个由低到高的队形出来了,这个教官将直接插入排序法灵活地运用到了生活中,真是妙啊~ ~

编程世界与现实生活的结合,我相信直接插入排序法的精髓和灵魂不难理解了,那么看看代码是怎么实现的,下面就以上面的理牌说,说说真个理牌的过程,下面列出前两轮排序 直接插入排序
@在第一轮中,5>3,5不用出列,直接进入下一轮。 @在第二轮中,4<5,4出列,当前空缺位置为int  vacancy = 2。 @比较5>4,5后移一位,vacancy = 1。 @比较3<4,不用移动,然后将出列的4放到空缺位置。

回到编程世界,菜鸟开始写代码: 看看核心的代码:
/**
* 直接插入排序的核心程序
* @param array
*/
public void insertSort(int... array) {
int length = array.length;
// 此循环从1开始,就是将0下标的元素当做一个参照
for (int i = 1; i < length; i++) {
if (array[i] < array[i - 1]) { // 将当前下标的值与参照元素比较,如果小于就进入里面
int vacancy = i; // 用于记录比较过程中那个空缺出来的位置
int sentry = array[i]; // 设置哨兵,将当前下标对应的值赋给哨兵
// 这个循环很关键,从当前下标之前一个元素开始倒序遍历,比较结果如果比当前大的,就后移
for (int j = i - 1; j >= 0 && array[j] > sentry; j--) {
vacancy = j;
array[j + 1] = array[j]; // 后移比当前元素大的元素
}
array[vacancy] = sentry; // 将哨兵,也就是当前下标对应的值置入空缺出来的位置
}
}
}
@外部循环的开始条件是int i = 1,里面有个if(array[i] > array[i - 1]),也就是如果当前记录比前面的记录小的时候才出列,出列后用sentry = array[i],记录下这个记录,并用vacancy = i,记录下空缺位置。
for (int i = 1; i < length; i++) {
if (array[i] < array[i - 1]) { // 将当前下标的值与参照元素比较,如果小于就进入里面
int vacancy = i; // 用于记录比较过程中那个空缺出来的位置
int sentry = array[i]; // 设置哨兵,将当前下标对应的值赋给哨兵
@如果出列了,注意内部循环的条件,是从当前记录的前一个开始的,然后倒序遍历,条件是如果遍历过程中有大于sentry的记录,就后移记录array[j + 1]  = array[j],然后将空缺位置变为j。
for (int j = i - 1; j >= 0 && array[j] > sentry; j--) {
vacancy = j;
array[j + 1] = array[j]; // 后移比当前元素大的元素
}
@比较完毕之后,array[vacancy] = sentry,是将出列的位置放到空缺位置。
array[vacancy] = sentry; // 将哨兵,也就是当前下标对应的值置入空缺出来的位置


我想,这个过程已经将直接插入排序说的不能再往下说了,至少我已经不能说下去了,下面提供完整的代码:
/**
* 直接插入排序算法
* @author PingCX
*
*/
public class InsertSort {

public static void main(String[] args) {
InsertSort insertSort = new InsertSort();
int[] array = { 3, 5, 4, 2, 6};
System.out.println(Arrays.toString(array));
insertSort.insertSort(array);// 调用快速排序的方法
System.out.println(Arrays.toString(array));// 打印排序后的数组元素
}

/**
* 直接插入排序的核心程序
* @param array
*/
public void insertSort(int... array) {
int length = array.length;
// 此循环从1开始,就是将0下标的元素当做一个参照
for (int i = 1; i < length; i++) {
if (array[i] < array[i - 1]) { // 将当前下标的值与参照元素比较,如果小于就进入里面
int vacancy = i; // 用于记录比较过程中那个空缺出来的位置
int sentry = array[i]; // 设置哨兵,将当前下标对应的值赋给哨兵
// 这个循环很关键,从当前下标之前一个元素开始倒序遍历,比较结果如果比当前大的,就后移
for (int j = i - 1; j >= 0 && array[j] > sentry; j--) {
vacancy = j;
array[j + 1] = array[j]; // 后移比当前元素大的元素
}
array[vacancy] = sentry; // 将哨兵,也就是当前下标对应的值置入空缺出来的位置
}
}
}
}


下面是用于面向对象语言中可比较的任意类型的直接插入排序:
/**
* 任何可以比较的类型的直接插入排序算法
*
* @author PingCX
*
*/
public class InsertSortT {

public static void main(String[] args) {
InsertSortT insertSort = new InsertSortT();
Integer[] array = { 3, 5, 4, 2, 6 };
System.out.println(Arrays.toString(array));
insertSort.insertSort(array);// 调用快速排序的方法
System.out.println(Arrays.toString(array));// 打印排序后的数组元素
}

/**
* 直接插入排序的核心程序
*
* @param array
*/
public <T extends Comparable<T>> void insertSort(T[] array) {
int length = array.length;
// 此循环从1开始,就是将0下标的元素当做一个参照
for (int i = 1; i < length; i++) {
if (array[i].compareTo(array[i - 1]) < 0) { // 将当前下标的值与参照元素比较,如果小于就进入里面
T sentry = array[i]; // 设置哨兵,将当前下标对应的值赋给哨兵
int vacancy = i; // 用于记录比较过程中那个空缺出来的位置
// 这个循环很关键,从当前下标之前一个元素开始倒序遍历,比较结果如果比当前大的,就后移
for (int j = i - 1; j >= 0 && array[j].compareTo(sentry) > 0; j--) {
vacancy = j;
array[j + 1] = array[j]; // 后移比当前元素大的元素
}
array[vacancy] = sentry; // 将哨兵,也就是当前下标对应的值置入空缺出来的位置
}
}
}
}


尾声: 生活中不要循规蹈矩,特别是作为一名程序员,要想有所成就,就必须灵活变通,哪里有机会就往哪里插,把握机会,当然也要一步一个脚印,踏踏实实地走好每一步。 食得菜根,可做百事~


欢迎Java爱好者品读其他算法详解:

简单比较排序:http://blog.csdn.net/ysjian_pingcx/article/details/8652091

冒泡排序:        http://blog.csdn.net/ysjian_pingcx/article/details/8653732

选择排序:        http://blog.csdn.net/ysjian_pingcx/article/details/8656048

快速排序:        http://blog.csdn.net/ysjian_pingcx/article/details/8687444

快速排序优化:http://blog.csdn.net/ysjian_pingcx/article/details/8687444