插入排序

来源:互联网 发布:word vba编程代码大全 编辑:程序博客网 时间:2024/06/13 09:28

思想:
将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列, 然后从第2个记录逐个进行插入,直至整个序列有序为止。

要点:设立哨兵,作为临时存储和判断数组边界之用。 如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

实现过程:

从第一个元素开始,该元素可以认为已经被排序取出下一个元素,在已经排序的元素序列中从后向前扫描如果该元素(已排序)大于新元素,将该元素移到下一位置重复步骤3,直到找到已排序的元素小于或者等于新元素的位置将新元素插入到该位置后重复步骤2~5

宏观实现过程图:
这里写图片描述
这里写图片描述

 插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小,比如量级小于千,那么插入排序还是一个不错的选择。 插入排序在工业级库中也有着广泛的应用,在STL的sort算法和stdlib的qsort算法中,都将插入排序作为快速排序的补充,用于少量元素的排序(通常为8个或以下)。

代码:

package com.xujd.suanfa;import org.junit.Test;import com.xujd.util.TextUtil;public class InsertSort {    int a[]={6,5,8,3,2,4,1,7};// 分类 ------------- 内部比较排序// 数据结构 ---------- 数组// 最差时间复杂度 ---- 最坏情况为输入序列是降序排列的,此时时间复杂度O(n^2)// 最优时间复杂度 ---- 最好情况为输入序列是升序排列的,此时时间复杂度O(n)// 平均时间复杂度 ---- O(n^2)// 所需辅助空间 ------ O(1)// 稳定性 ------------ 稳定    public void insertSortA(){         int temp=0;              for(int i=1;i<a.length;i++){                 int j=i-1;                 temp=a[i];                 for(;j>=0&&temp<a[j];j--){                     a[j+1]=a[j];  //将大于temp的值整体后移一个单位                 }                 a[j+1]=temp;              }            TextUtil.print(a);    }    public void insertSortB(){          for(int i=1;i<a.length;i++){//从头部第一个当做已经排好序的,把后面的一个一个的插到已经排好的列表中去。                  if(a[i]<a[i-1]){                      int j;                      int x=a[i];//x为待插入元素                      a[i]=a[i-1];                      for(j=i-1; j>=0 && x<a[j];j--){//通过循环,逐个后移一位找到要插入的位置。                          a[j+1]=a[j];                      }                      a[j+1]=x;//插入                  }              }          TextUtil.print(a);    }//插入排序的更高效改进:希尔排序/*希尔排序,也叫递减增量排序,是插入排序的一种更高效的改进版本。希尔排序是不稳定的排序算法。  希尔排序是基于插入排序的以下两点性质而提出改进方法的:    插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率    但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位  希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。  假设有一个很小的数据在一个已按升序排好序的数组的末端。如果用复杂度为O(n^2)的排序(冒泡排序或直接插入排序),可能会进行n次的比较和交换才能将该数据移至正确位置。而希尔排序会用较大的步长移动数据,所以小数据只需进行少数比较和交换即可到正确位置。    */// 分类 -------------- 内部比较排序// 数据结构 ---------- 数组// 最差时间复杂度 ---- 根据步长序列的不同而不同。已知最好的为O(n(logn)^2)// 最优时间复杂度 ---- O(n)// 平均时间复杂度 ---- 根据步长序列的不同而不同。// 所需辅助空间 ------ O(1)// 稳定性 ------------ 不稳定    public void insertSortC(){        double d1=a.length;          int temp=0;          while(true){             d1= Math.ceil(d1/2);             int d=(int) d1;             for(int x=0;x<d;x++){                 for(int i=x+d;i<a.length;i+=d){                    int j=i-d;                    temp=a[i];                    for(;j>=0&&temp<a[j];j-=d){                         a[j+d]=a[j];                    }                    a[j+d]=temp;                 }             }             if(d==1){                 break;             }    }        TextUtil.print(a);    }}

这里写图片描述

 希尔排序是不稳定的排序算法,虽然一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱。

  比如序列:{ 3, 5, 10, 8, 7, 2, 8, 1, 20, 6 },h=2时分成两个子序列 { 3, 10, 7, 8, 20 } 和 { 5, 8, 2, 1, 6 } ,未排序之前第二个子序列中的8在前面,现在对两个子序列进行插入排序,得到 { 3, 7, 8, 10, 20 } 和 { 1, 2, 5, 6, 8 } ,即 { 3, 1, 7, 2, 8, 5, 10, 6, 20, 8 } ,两个8的相对次序发生了改变。

原创粉丝点击