一.总述
······在研究排序算法时,插入排序往往被作为入门算法来学习,我们今天就来看一下插入排序。近期我们再来慢慢研究冒泡排序、选择排序、希尔排序、快速排序以及堆排序。话不多说,下面进入今天的主题。
首先我们要了解,插入排序算法又分成直接插入排序与折半插入排序两种,折半插入排序算法则是在直接插入排序的基础上加以了改进优化,我们先来看一下直接插入排序:
二.插入排序之直接插入排序
1.原理
插入排序的思想是将待排序数组分为有序区间以及无序区间,数组第一个元素为初始有序区间,其余为初始无序区间。然后,从无序区间中取第一位元素插入到有序区间内,按照“插入扑克牌”方式(习惯上从小到大)进行排序。以此方式,将所有无序区间元素插入到有序区间后,排序完成。
下面来举个栗子:
假设待排序的数据是数组A[0….n]。初始时,A[0]自成1个有序区,无序区为A[1….n]。在排序的过程中,依次将A[i] (i=1,2,….,n)从后往前插入到前面已排好序的子数组中的适当位置,当所有的A[i] 插入完毕,数组A中就包含了已排好序的输出序列。
A [5] = { 3,6,4,1,5 }
A[0] = 3 A[1] = 6 A[2] = 4 A[3] = 1 A[4] = 5
排序过程(不同于此的折半插入在确定插入位置时做出了二分法的实现要求):
第一趟排序后:[ 3 ] 6, 4, 1, 5
第二趟排序后:[ 3 , 6 ] 4, 1, 5
第三趟排序后:[ 3 , 4 , 6 ] 1, 5
第四趟排序后:[ 1 , 3 , 4 , 6 ] 5
第五趟排序后:[ 1 , 3 , 4 , 5 , 6 ]
最后排序结果:
1 3 4 5 6
2.代码实现
/**
*插入排序
*
*@author 夜雨声烦
*
*/
public class Insert {
// 传入参数为需要排序的随机数组
public static void insertionSort(int[] a) {
int t;// 临时变量
// 有序部分 增加
for (int i = 1; i < a.length; i++) {
// 将无序首元插入到有序数组中
for (int j = i; j > 0; j--) {
if (a[j] < a[j - 1]) {
t = a[j - 1];
a[j - 1] = a[j];
a[j] = t;
}
}
}
}
public static void main(String[] args) {
int[] a = { 49, 38, 65, 97, 76 };
insertionSort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
}
三.插入排序之折半插入排序((二分插入排序))
1.原理
折半插入排序是在直接插入的基础上加以改进,在将无序数据插入到有序区间时用采用二分法进行,所以又叫二分插入排序。用二分法确定应该插入的位置,每次取得有序区间中间位置的值进行比较,以此不断缩小范围,相比直接法寻找位置的次数少速度快,算法有一定的优化。
2.代码实现
/**
* 算法实现部分提取
*
* @param a
* 待排序的数组
*/
private void binaryInsertSort(int[] a) {
int n = a.length;
int i, j;
for (i = 1; i < n; i++) {
// temp为本次循环待插入有序列表中的数
int temp = a[i];
int low = 0;
int high = i - 1;
// 寻找temp插入有序列表的正确位置,使用二分查找法
// 每次缩减一半区间,较快寻找元素位置
while (low <= high) {
// 有序数组的中间坐标,此时用于二分查找,减少查找次数
int mid = (low + high) / 2;
// 若有序数组的中间元素大于待排序元素,则有序序列向中间元素之前搜索,否则向后搜索
if (a[mid] > temp) {
high = mid - 1;
} else {
low = mid + 1;
}
}
for (j = i - 1; j >= low; j--) {
// 元素后移,为插入temp做准备
a[j + 1] = a[j];
}
// 插入temp
a[low] = temp;
}
}
写在最后的话
由于最近才开始学习写博文(之前都是作为笔记随笔来简要记录的,丑的一匹),博客的格式和内容都无法保证,但我会慢慢改正自己,还有很多的不足都是自己长期以来都从未意识到的,so也希望大佬前辈们能够耐心监督并提出宝贵的建议,我一定会吸取教训慢慢改正自己!!!在此献出自己的膝盖QAQ!!!