插入排序的基本思想是:每一趟将一个待排序的记录,按器关键字的大小插入到已经排好序的一组记录的适当位置上,直到所有待排序记录全部插入为止。
例如,打扑克牌在抓牌的时要保证抓过的牌有序排列则每抓一张牌,就插入到合适的位置,直到抓完牌为止,即可得到一个有序序列。
可以选择不同的方法在已排好序的记录中寻找插入位置。根据查找方法的不同,有多种插入排序方法,这里主要介绍直接插入排序。
直接插入排序
直接插入排序(Straight Insertion Sort)是一种最简单的排序方法,其基本操作是将一条记录插入到已排好序的有序表中,从而得到一个新的、记录数量增1的有序表
算法步骤
1)设待排序的记录放在数组中r[1...n]中,r[1]是一个有序序列。
2)循环n-1次,每次使用顺序查找法,查找r[i](i=2,...n)在已排好序的序列r[1...i-1]中的插入位置,然后将r[i]插入表长为i-1的有序序列r[1...i-1],直接将r[n]插入表长为n-1的有序序列r[1...n-1],最后得到一个表长为n的有序序列
java代码的实现
package com.hxy.sort; import java.util.Arrays; public class InsertSort { public static void main(String[] args) { int[] arr ={49,38,65,97,76,13,27,49}; System.out.println("排序之前的数组"); System.out.println(Arrays.toString(arr)); insertSort(arr); System.out.println("排序之后的数组"); System.out.println(Arrays.toString(arr)); } public static void insertSort(int[] arr){ for (int i = 1; i<arr.length;i++){ if(arr[i]<arr[i-1]){//若第i个元素小于第i-1个元素,移动有序序列, 如果大于的话则直接插入 int temp = arr[i];//存储待插入的记录 arr[i] = arr[i-1]; int j = i-1; for(;j>=0&&temp<arr[j];j--){//判断条件 arr[j+1] = arr[j]; } arr[j+1] = temp;// 将待插入的元素插到指定位置 } } } }
结果如下图所示
动画示意图
时间复杂度
对于整个排序过程需执行n-1趟,在最好的情况下(正序:待排序序列中记录按关键字非递减有序排列),总的移动比较次数达到最小值n-1,记录不需移动;最坏情况下(即待排序表为逆序),总的关键字比较次数为(n+2)(n-1)/2≈/2,记录移动次数为(n+4)(n-1)/2≈/2。若待排序序列中出现各种可能排列的概率相同,则可取上述最好情况和最坏情况的平均情况。在平均情况下,直接插入排序关键字的比较次数和记录移动次数均约为/4。由此,直接插入排序的时间复杂度为O()
空间复杂度
直接插入排序只需要一个记录的辅助空间temp,所以空间复杂度为O(1)。
算法的特点
(1)稳定排序
(2)算法简单,且容易实现
(3)也适用于链式存储结构,只是在单链表上无需移动记录,只需修改相应的指针。
(4)更适合初始记录基本有序(正序)的情况,当初始记录无序,n较大时,此算法的时间复杂度较高,不宜采用