一、插入排序的基本思想

  从初始有序的子集合开始,不断地把新的数据元素插入到已排列有序子集合的合适位置上,使子集合中数据元素的个数不断增多,当子集合等于集合时,插入排序算法结束。常用的 插入排序算法有直接插入排序和希尔排序两种。

  

  二、直接插入排序

  1.直接插入排序的定义

  直接插入排序的基本思想是:顺序地把待排序的数据元素按其值的大小插入到已排序数据元素子集合的适当位置。子集合的数据元素个数从只有一个数据元素开始逐次增大。当子集合大小最终和集合大小相同时排序完毕。

  2.直接插入排序的实现

    public static void straightInsertionSort(int[] L) {
int i, j, temp;
for (i = 0; i < L.length - 1; i++) {
temp = L[i+1]; // 保存要插入的数据元素
j = i;
while (j > -1 && temp <= L[j]) { // 将temp插入到原数组集合中
L[j+1] = L[j];
j--;
}
L[j+1] = temp;
}
}   int[] array1 = {9,1,5,8,3,7,4,6,2};
  初始时,子集合中L0已经排好序,即为{9}
  i=0时,temp=L1=1,j=0,0大于-1且1小于9,则L1=9,j=-1,L0=1,即将1插入到9的前面,集合中{1,9}
  i=1时,temp=L2=5,j=1,1大于-1且5小于9,则L2=9,j=0,0大于-1但5不小于1,则L1=5,集合中{1,5,9}
  i=2时,temp=L3=8,即将8和9比较,8插入到9的前面,8和5比较,不动,8和1比较,也不动,集合中{1,5,8,9}
  ...

  3.直接插入排序的性能分析

  (1)时间复杂度为O(n²)

  • 最好情况是原始数据集合已经全部排好序。这时内层while循环的循环次数每次均为0,外层for循环中每次数据元素的比较次数均为1,数据元素的赋值语句执行次数均为2。因此整个排序过程中比较次数为n-1,移动次数为2(n-1),此时的时间复杂度为O(n)。
  • 最坏情况是与原始数据集合反序排列。这时内层while循环的循环次数每次均为i,这样,整个外层for循环中的比较次数为(1+1)+(2+1)+...+(n-1+1)=(n-1)(n+2)/2,而移动次数为(1+2)+(2+2)+...+(n-1+2)=(n-1)(n+4)/2。此时的时间复杂度为O(n²)。  
  • 随机情况是数据集合中大小的排列是随机的。这时比较次数的期望和移动次数的期望均为n²/4,此时的时间复杂度为O(n²)。

  (2)空间复杂度为O(1)。

  (3)是一种稳定的排序算法。

  三、希尔排序

  1.希尔排序的定义

  希尔排序的基本思想是:把待排序的数据元素分成若干个小组,对同一小组内的数据元素用直接插入法排序;小组的个数逐次缩小;当完成了所有数据元素都在一个组内的排序后排序过程结束。希尔排序又称作缩小增量排序。

  在直接插入排序算法的性能分析中可以得出结论:原始数据集合越接近有序,直接插入排序算法的时间效率越高,其时间效率在O(n)~O(n²)之间。这个结论是希尔排序算法能够成立的基础。希尔排序算法把待排序数据元素分成若干小组,在小组内用直接插入排序算法排序,当把若干个小组合并为一个小组时,组中的数据元素集合将会接近有序,这样各组内的直接插入排序算法的时间效率就很好,最终整个希尔排序的时间效率就很高。

  2.希尔排序的实现

    public static void shellSort(int[] L, int[] d) {
int i, j, k, m, span;
int temp;
for (m= 0; m < d.length; m++) {
span = d[m];
for (k = 0; k < span; k++) {
/********将i=0换成i=k,1换成span的直接插入排序**********/
for (i = k; i < L.length - span; i = i + span) {
temp = L[i+span];
j = i;
while (j > -1 && temp <= L[j]) {
L[j + span] = L[j];
j = j - span;
}
L[j + span] = temp;
print(L);
}
/***********************************************/
}
System.out.print("span的值为" + span + "时得到的序列为: ");
print(L);
}
}

  分析代码执行过程与输出为:

int[] array1 = {9,1,5,8,3,7,4,6,2};int[] d = {4,2,1};
分析执行过程:
m=0时,span=4,k=0时,i=0,j=0时,交换9和3得到{3,1,5,8,9,7,4,6,2};i=4,j=4时,交换9和2得到{3,1,5,8,2,7,4,6,9};j=0时,交换3和2得到{2,1,5,8,3,7,4,6,9};排序{2,3,9}
m=0时,span=4,k=1时,i=1,1和7不交换,排序{1,7}
m=0时,span=4,k=2时,i=2,交换5和4,得到{2,1,4,8,3,7,5,6,9};排序{4,5}
m=0时,span=4,k=3时,i=3,交换8和6,得到{2,1,4,6,3,7,5,8,9};排序{6,8}
m=0结束,得到{2,1,4,6,3,7,5,8,9};可以发现数字1、2等小数字已经在前两位,而8、9等大数字已经在后两位,整个序列已经基本有序了。
m=1时,span=2,k=0时,排序{2,4,3,5,9}为{2,3,4,5,9}
m=1时,span=2,k=1时,排序{1,6,7,8}
m=1结束,交叉两个排序得到{2,1,3,6,4,7,5,8,9}即将之前5个和4个分别直接插入排序,然后插入到原来的位置
m=2时,span=1,k=0时,排序{2,1,3,6,4,7,5,8,9}得到{1,2,3,4,5,6,7,8,9}
输出为:
希尔排序前: 9 1 5 8 3 7 4 6 2
span的值为4时得到的序列为: 2 1 4 6 3 7 5 8 9
span的值为2时得到的序列为: 2 1 3 6 4 7 5 8 9
span的值为1时得到的序列为: 1 2 3 4 5 6 7 8 9
希尔排序后: 1 2 3 4 5 6 7 8 9

  3.希尔排序的性能分析

  (1)时间复杂度

  希尔排序增量序列的选取非常关键,需要注意的是增量序列的最后一个增量值必须是1才行。通过设置合适的增量序列,可以使得时间复杂度为O(n3/2),要好于直接插入排序的O(n²)。

  (2)空间复杂度

  希尔排序算法的空间复杂度为O(1)。

  (3)稳定性

  由于希尔排序算法是按增量分组进行的排序,两个相同的数据元素有可能分在不同的组中,所以希尔排序算法是一种不稳定的排序算法。

  

最新文章

  1. [翻译]AKKA笔记 - 有限状态机 -1
  2. 开启基本数据结构和算法之路--初识Graphviz
  3. linux Mint wine安装qq,桌面快捷键配置
  4. java多线程系类:JUC线程池:03之线程池原理(二)(转)
  5. 解析大型.NET ERP系统 20条数据库设计规范
  6. Linux下interface文件修改
  7. C#.NET序列化XML、JSON、二进制微软自带DLL与newtonsoft(json.net)
  8. 迅为4412开发板Linux驱动教程之GPIO的初始化
  9. [LeetCode]题解(python):079 Word Search
  10. 保存会话数据——cookie学习
  11. hdu 2056
  12. linux入门教程(一) 关于linux的历史
  13. DataGridView 选中行 分类: DataGridView 2015-01-22 09:07 51人阅读 评论(0) 收藏
  14. 红黑树-Python实现
  15. 详细解释VB连接access几种方法数据库
  16. 关于PHP静态方法调用和实例化类调用的区别
  17. 从备份文件bak中识别SQL Server的版本
  18. OJ:自己实现一个简单的 priority_queue
  19. ALGO-5_蓝桥杯_算法训练_最短路
  20. springboot-7-配置druid数据源监视

热门文章

  1. Redis数据库之数据基本管理操作
  2. 死磕 java同步系列之mysql分布式锁
  3. DevExpress GridControl导出ExportToXls 数字类型显示成货币格式
  4. 织梦DEDE分类信息实现联动筛选(支持多条件多级选项)解决方案
  5. MongoDB 学习笔记之 Nested doc/DBRef (Spark)
  6. tensorflow中添加L2正则化损失
  7. .NET成人礼 | 还记得20年前一起拖过的控件吗?
  8. 小程序webview调用微信扫一扫的“曲折”思路
  9. Android 捕捉app系统中未处理的异常
  10. 执行Django数据迁移,报错 1091