0. 前言
本系列文章将介绍一些常用的排序算法。排序是一个非常常见的应用场景,也是开发岗位面试必问的一道面试题,有人说,如果一个企业招聘开发人员的题目中没有排序算法题,那说明这个企业不是一个“正规”的企业,哈哈,虽然有点戏谑,但是也从侧面证明了排序算法的重要性。
本文将介绍的是常见排序算法中的插入排序。
4 插入排序
4.1 基本思想
插入排序分为两种,一种是直接插入排序,一种是二分插入排序。
首先直接插入排序的基本思想是将序列分为排序好的部分和待排序部分,将待排序部分中的数据一个个的和前面已经排序好的部分比较(逐个从后到前顺序比较)并插入到该部分的合适位置,从而实现有序。而二分插入排序则是对直接插入排序法比较过程的一个优化,即从顺序比较变成了二分查找比较。
4.2 直接插入排序的代码实现
/*
*@content 直接插入排序
*@author Calvin
*@blog http://blog.csdn.net/seu_calvin/article/details/55653764
*@date 2017/02/18
*/
public class Order {
private int[] array;
public Order(int[] array){
this.array = array;
}
public void sort() {
if(array!=null && array.length > 0){
for(int i = 1; i <= array.length - 1; i++){
//本轮比较的主角
int temp = array[i];
//和前面的有序部分逐个比较
for(int j = i - 1; j >= 0 ; j--){
if(temp < array[j]){
array[j + 1] = array[j];
array[j] = temp;
}else break;
}
}
}
}
public void print() {
for(int i = 0; i < array.length; i++)
System.out.println(array[i]);
}
public static void main(String[] args) {
int[] array = new int[]{3,1,5,9,6,5,0};
Order order = new Order(array);
order.sort();
order.print();
}
}
输出结果略去。
4.3 二分插入排序的代码实现
/*
*@content 二分插入排序
*@author Calvin
*@blog http://blog.csdn.net/seu_calvin/article/details/55653764
*@data 2017/02/18
*/
public class Order {
private int[] array;
public Order(int[] array){
this.array = array;
}
public void sort() {
if(array!=null && array.length>0){
for(int i = 1; i<array.length; i++){
//本轮比较的主角
int temp = array[i];
//二分查找到要插入的位置
int position = binarySearch(i-1, temp);
//移动有序数列
if(i != position){
//排除不需要移动的情况
for(int j = i; j > position ; j--){
array[j] = array[j-1];
}
//最后在要插入的位置插入temp
array[position] = temp;
}
}
}
}
//参数1为要比较的最大边界
private int binarySearch(int maxIndex, int data) {
int start = 0;
int end = maxIndex;
int mid;
while(start <= end){
mid = (start+end)/2;
if(array[mid] > data){
end = mid - 1;
}else{
start = mid + 1;
}
}
return start;
}
public void print() {
for(int i = 0; i < array.length; i++)
System.out.println(array[i]);
}
public static void main(String[] args) {
int[] array = new int[]{3,1,5,9,6,5,0};
Order order = new Order(array);
order.sort();
order.print();
}
}
输出结果略去。
4.4 性能特点
直接插入排序的时间复杂度为O(n*n),空间复杂度为O(1),最好的时间复杂度很明显是数组原本有序的情况,即O(n)。该排序算法是稳定的,这无需所言。需要注意的是,如果数组本身有序度越高,那么插入排序的内层循环只需要比较、移动较少次,因此插入排序更适合数列近似有序的情况,但是由于其时间复杂度不太好,因此很少被单独使用。
而二分插入排序相对直接插入排序而言,减少了多余的比较。但是其时空复杂度稳定性和直接插入排序是一样的。
插入排序经常和快速排序结合使用,因为(1)快速排序在数据量较小时性能不一定好,(2)加上快排后期某个小区块内的数据相对有序,所以在快速排序的分区规模达到一定数值比如10时,改用插入排序对该“小区”内的数据进行排序。