Java温故而知新-插入排序
插入排序
插入排序的基本思想是将待排序的元素依次插入序列合适的位置,然后将这个位置后面的元素依次向后移动一位
位置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温故而知新-插入排序的更多相关文章
- Java温故而知新-杨辉三角形
Java温故而知新-杨辉三角形 一. 先说需求 需求 打印输出杨辉三角形,行数可变,支持50行内的任意数. 预期结果如图所示 1 这是第几行呢,是第1 1 1 这是第几行呢,是第2 1 2 1 这是第 ...
- 疯狂的Java算法——插入排序,归并排序以及并行归并排序
从古至今的难题 在IT届有一道百算不厌其烦的题,俗称排序.不管是你参加BAT等高端笔试,亦或是藏匿于街头小巷的草根笔试,都会经常见到这样一道百年难得一解的问题. 今天LZ有幸与各位分享一下算法届的草根 ...
- JAVA排序--[插入排序]
package com.array; public class Sort_Insert { /* * 项目名称:插入排序 ; * 项目要求:用JAVA对数组进行排序,并运用插入排序算法; * 作者:S ...
- Java直接插入排序
插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入. 算法步骤: 1)将第一待排序序列第一个元素看做一个有序序列,把第二 ...
- 【Java SE】如何用Java实现插入排序
摘要:前面三期分别写了三篇简单排序的算法,今天来讲一点稍微难一点的排序算法-----插入排序. 基本思想: 设n个数据已经按照顺序排列好(假定从小排到大). 输入一个数据x,将其放在恰当的位置,使其顺 ...
- JAVA数据结构--插入排序
插入排序(英语:Insertion Sort)是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上,通常采用in- ...
- Java实现插入排序
package Sort; import java.util.Arrays; public class InsertionSort { public static int[] sort(int[] l ...
- java 用插入排序思想,对不规则数组排序。
知道插入排序后,无意中发现,用插入排序思想,对不规则数组排序的排序 发现和许多大神写的不一样,大神写的简洁多了.--------
- Java算法-插入排序
插入排序的基本思想是在遍历数组的过程中,假设在序号 i 之前的元素即 [0..i-1] 都已经排好序,本趟需要找到 i 对应的元素 x 的正确位置 k ,并且在寻找这个位置 k 的过程中逐个将比较过的 ...
随机推荐
- centos中-hadoop单机安装及伪分布式运行实例
创建用户并加入授权 1,创建hadoop用户 sudo useradd -m hadoop -s /bin/bash 2,修改sudo的配置文件,位于/etc/sudoers,需要root权限才可以读 ...
- 用Collections.synchronizedCollection创建线程安全的集合、列表。。。
Collection c=Collections.synchronizedCollection(new ArrayList()); List list=Collections.synchronized ...
- Java IO(一):IO和File
一.IO 大多数的应用程序都要与外部设备进行数据交换,最常见的外部设备包含磁盘和网络.IO就是指应用程序对这些设备的数据输入与输出,Java语言定义了许多类专门负责各种方式的输入.输出,这些类都被放在 ...
- Android开发之监听器
一直都想进行安卓开发,最近上手了Android.刚开始学习一些基本控件,学习Android就如同进入一个新的世界,印象最深的是这个世界的规则. 最近学习了监听器,对于这个我的一点理解是监听键盘活动 B ...
- 微信小程序-滚动消息通知效果
这次我主要想总结一下微信小程序实现上下滚动消息提醒,主要是利用swiper组件来实现,swiper组件在小程序中是滑块视图容器. 我们通过vertical属性(默认为false,实现默认左右滚动)设置 ...
- year:2017 month:07 day:31
2017-07-31 JAVA se 1:基础 控制语句:continue语句:退出本次循环 break语句:退出当前循环 循环语句:for(初始化:条件表达式:循环体){循环语句} 先初始化,再执行 ...
- 走过夏天,我的H5旅程,一路慢行
<!DOCTYPE html> <!-- 文档类型声明:让浏览器,按照html5的标准对代码进行解释和执行. 文档类型声明必不可少,而且,必须放在文档最上方. 如果不写文档类型声明, ...
- nginx实现wap移动端和PC端业务分离
随着移动互联网时代的来临,很多WEB网站都已经推出了基于手机,Ipad等移动客户端的页面访问,这里介绍一下如何利用用户UA实现用户不同终端下的用户访问: $http_user_agent 为ngin ...
- CI框架主题切换的功能
CI框架主题切换的功能 本人接触到这个框架不就,属于菜鸟 , 公司现在用CI框架做项目 ,老大要做一个主题切换的功能,说明功能的要求我的脑子里瞬间有几个想法. 脑子里最简单的就是设置全局变量 如 : ...
- NYOJ--19--next_permutation()--擅长排列的小明
/* Name: NYOJ--19--擅长排列的小明 Date: 20/04/17 11:06 Description: 这道题可以DFS,然而用next_permutation更简单些 主要是全排列 ...