每天一算法 -- (插入排序)
一、原理
插入排序就是把当前待排序的元素插入到一个已经排好序的列表里面。对于给定的一组记录,初始时假定第一个记录自成一个有序序列,其余记录为无序序列。接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直到最后一个记录插到有序序列中为止。
二、思路
1.在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排好顺序的,现在要把第n个数找到相应位置并插入,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。
2.例子:假设有一个数组 :{3,1,2,8,7,9}
第一趟:1和3比较,1<3,则将1和3的位置互换,为:
1,3,2,8,7,9
第二趟:2和1、3比较,2<3,则将2和3的位置互换,为:
1,2,3,8,7,9
第三趟:8和1、2、3比较,8>前面的,则位置不变,为:
1,2,3,8,7,9
第四趟:7和1、2、3、8比较,7<8,则7和8的位置互换,为:
1,2,3,7,8,9
第五趟:9和1、2、3、7、8比较,9>前面的,则位置不变,为:
1,2,3,7,8,9
三、时间复杂度
在第一趟排序中,插入排序最多比较一次,第二趟最多比较两次,依次类推,最后一趟最多比较N-1次,因此有:
1+2+3+...+N-1 = N*N(N-1)/2.
然而,因为在每一趟排序发现插入点之前,平均只有全体数据项的一半真的进行了比较,除以2得到:
N*N(N-1)/4.
复制的次数大致等于比较的次数。然而,一次复制与一次比较的时间耗费不同,所以相对随机数据,这个算法比冒泡排序快一倍,比选择排序略快。
在任意情况,对于随机顺序的数据进行排序的时间复杂度为O(n2);对于已经有序或基本有序的数据来说,插入排序要好得多。当数据有序的时候,while循环的条件总是假。所以他就变成了外层循环中的一个简单语句,执行n-1次,在这种情况下,算法运行只需要O(n)的时间。如果基本有序,插入排序只需要O(n)的时间。但是,对于逆序排列的数据,每次比较和移动都会执行,所以插入排序不必冒泡排序快。
四、代码实现
1 /** 2 * 排序算法 3 * @author Administrator 4 */ 5 public class Sort { 6 7 /** 8 * 插入排序 9 * @param arr 10 */ 11 public static void insertSort(int[] arr){ 12 13 int insert = 0; // 要插入的元素 14 int j = 0; 15 16 for(int i = 1; i < arr.length; i ++){ // 从数组的第二个元素开始循环将数组中的元素插入 17 insert = arr[i]; // 设置数组中的第2个元素为第一次循环要插入的数据 18 j = i - 1; // 与待排序元素值作比较的元素的下标 19 while(j >= 0 && insert < arr[j]){ // 如果要插入的元素小于第j个元素,就将第j个元素向后移动 20 arr[j + 1] = arr[j]; 21 j --; 22 } 23 arr[j + 1] = insert; // 找到了插入的位置,插入 24 } 25 26 for(int i = 0;i < arr.length; i ++){ 27 System.out.print(arr[i] + " "); 28 } 29 } 30 31 /** 32 * 测试 33 * @param args 34 */ 35 public static void main(String[] args) { 36 int[] arr = {3,1,2,8,7,9}; 37 insertSort(arr); 38 } 39 }