算法之直接插入排序和希尔排序

1.插入排序—直接插入排序(Straight Insertion Sort)

基本思想:

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

要点:设立哨兵,作为临时存储和判断数组边界之用。

直接插入排序示例:

如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

算法的实现:

  1. void print(int a[], int n ,int i)
  2. {
  3. cout<<i <<":";
  4. for(int j= 0; j<10; j++)
  5. {
  6. cout<<a[j] <<" ";
  7. }
  8. cout<<endl;
  9. }
  10. void InsertSort(int a[], int n)
  11. {
  12. for(int i= 1; i<n; i++)
  13. {
  14. if(a[i] < a[i-1])
  15. {                                //若第i个元素大于i-1元素,直接插入。小于的话,移动有序表后插入
  16. int j= i-1;
  17. int x = a[i];                //复制为哨兵,即存储待排序元素
  18. a[i] = a[i-1];              //先后移一个元素
  19. while(x < a[j])
  20. {                            //查找在有序表的插入位置
  21. a[j+1] = a[j];
  22. j--;                    //元素后移
  23. }
  24. a[j+1] = x;                 //插入到正确位置
  25. }
  26. print(a,n,i);                   //打印每趟排序的结果
  27. }
  28. }
  29. int main()
  30. {
  31. int a[10],i;
  32. for (i=0; i < 10; i++)
  33. {
  34. a[i] = rand() % 100;
  35. }
  36. InsertSort(a,10);
  37. print(a,10,10);
  38. }

效率:

时间复杂度:O(n^2).

其他的插入排序有二分插入排序,2-路插入排序。

2. 插入排序—希尔排序(Shell`s Sort)

希尔排序是1959 年由D.L.Shell 提出来的,相对直接排序有较大的改进。希尔排序又叫缩小增量排序

基本思想:

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

操作方法:

  1. 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
  2. 按增量序列个数k,对序列进行k 趟排序;
  3. 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

希尔排序的示例:

算法实现:

我们简单处理增量序列:增量序列d = {n/2 ,n/4, n/8 .....1} n为要排序数的个数

即:先将要排序的一组记录按某个增量d(n/2,n为要排序数的个数)分成若干组子序列,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。继续不断缩小增量直至为1,最后使用直接插入排序完成排序。

  1. void print(int a[], int n ,int i)
  2. {
  3. cout<<i <<":";
  4. for(int j= 0; j<10; j++)
  5. {
  6. cout<<a[j] <<" ";
  7. }
  8. cout<<endl;
  9. }
  10. /*直接插入排序的一般形式 ,int dk 缩小增量,如果是直接插入排序,dk=1 */
  11. void ShellInsertSort(int a[], int n, int dk)
  12. {
  13. for(int i= dk; i<n; ++i)
  14. {
  15. if(a[i] < a[i-dk])
  16. {                            //若第i个元素大于i-1元素,直接插入。小于的话,移动有序表后插入
  17. int j = i-dk;
  18. int x = a[i];           //复制为哨兵,即存储待排序元素
  19. a[i] = a[i-dk];         //首先后移一个元素
  20. while(x < a[j])
  21. {                    //查找在有序表的插入位置
  22. a[j+dk] = a[j];
  23. j -= dk;             //元素后移
  24. }
  25. a[j+dk] = x;            //插入到正确位置
  26. }
  27. print(a, n,i );
  28. }
  29. }
  30. /*先按增量d(n/2,n为要排序数的个数进行希尔排序*/
  31. void shellSort(int a[], int n)
  32. {
  33. int dk = n/2;
  34. while( dk >= 1  )
  35. {
  36. ShellInsertSort(a, n, dk);
  37. dk = dk/2;
  38. }
  39. }
  40. int main()
  41. {
  42. int a[10],i;
  43. for (i=0; i < 10; i++)
  44. {
  45. a[i] = rand() % 100;
  46. }
  47. shellSort(a,10);           //希尔插入排序
  48. print(a,10,10);
  49. }

希尔排序时效分析很难,关键码的比较次数与记录移动次数依赖于增量因子序列d的选取,特定情况下可以准确估算出关键码的比较次数和记录的移动次数。目前还没有人给出选取最好的增量因子序列的方法。增量因子序列可以有各种取法,有取奇数的,也有取质数的,但需要注意:增量因子中除1 外没有公因子,且最后一个增量因子必须为1。希尔排序方法是一个不稳定的排序方法。

时间: 2024-10-21 05:25:53

算法之直接插入排序和希尔排序的相关文章

七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)

 写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列.因此排序掌握各种排序算法非常重要.对下面介绍的各个排序,我们假定所有排序的关键字都是整数.对传入函数的参数默认是已经检查好了的.只是简单的描述各个算法并给出了具体实现代码,并未做其他深究探讨. 基础知识: 由于待排序的记录数量不同,使得排序过程中设计的存储器不同,可将排序方法分为两大类:一类是内部排序,指的是待排序记录存放在计算机随机存储器中进行的排序过程.另一类是外部排序,

插入排序算法之直接插入排序和希尔排序

插入排序算法 有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法--插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的.个数加一的有序数据. 直接插入排序 直接插入排序的排序思路是:每次将一个待排序的元素与已排序的元素进行逐一比较,直到找到合适的位置按大小插入. 例子: 有序列: 开始时,有序序列只有一个元素就是第一个元素(红色),后面的无序序列(绿色).接下来,取无序序列中

算法练习--直接插入排序、希尔排序

背景: 原来虽然有学过数据结构,排序一些,但是没有好好学,现在复习一下. 正题: 1.直接插入排序 直接贴一下百科:每次取出无序数组中的一个数,把他和有序数组中的数比较,插到适当位置,直到无序表为空,有序表满. 原理很简单,就我而言,首先想到的是新建一个new_list数组,充当有序表,然后一步一步将无序表里的值拿出来放到新的数组中.但是,写完之后,看了看书上的实例, 上面直接用单数组也可以,虚拟划分数组为两部分.代码简便多.于是很我也修改了一下自己的代码. 代码如下: <?php functi

数据结构精要------直接插入排序和希尔排序算法

上篇总结中主要实践了算法的内排序的选择排序,那么接下来我们继续实践插入排序排序的两种:直接插入排序和希尔排序算法. -----直接插入排序 package com.sort; /** * 直接插入排序 * * @author weixing-yang * * 算法思路: * 每步将一个待排序的元素,插入到前面已排序好的一组元素中的适当位置, * 直到所有元素全部出入完成为止. */ public class InsertionSort { public void insertionSort(in

#排序算法#【2】直接插入排序、希尔排序

直接插入排序法 插入排序的算法描述是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后移动,为最新元素提供插入空间. 核心代码: //直接插入排序法 void InsertSort(int a[],int n){ int i,j,k,t; for(i = 1 ; i<n;i++){ k = a[i]; /* 第一次比较粗糙的写法 j = i-1; while(

【数据结构与算法】内部排序之一:插入排序和希尔排序的N中实现(不断优化,附完整源码)

转载请注明出处:http://blog.csdn.net/ns_code/article/details/20043459   前言 本来想将所有的内部排序总结为一篇博文,但是随着研究的深入,还是放弃了这个念头,斟前酌后,还是觉得分开来写比较好,具体原因,看完本篇博文也就自然明了了. 本篇文章主要探讨插入排序和希尔排序,之所将二者放在一起,很明显,是因为希尔排序是建立在插入排序的基础之上的.     注:以下各排序算法的N种实现方法大部分都是我根据算法思想,自己写出来的,或者是参考其本身的经典实

算法3 七大排序之:直接插入排序和希尔排序

上一篇总结了直接选择排序和堆排序,这一篇要总结的是插入排序中的直接插入排序和希尔排序,我们主要从以下几点进行总结. 1.直接插入排序及算法实现 2.希尔排序及算法实现 3.直接插入排序PK希尔排序 1.直接插入排序及算法实现 什么是直接插入排序呢?直接插入排序的基本思想是:每次从无序序列中取出第一个元素插入到已经排好序的有序序列中,从而得到一个新的,数量加1的有序序列. 1-1.示意图 下面是直接插入排序的图解说明. 1-2.代码 下面是直接插入排序的算法实现代码. InsertSort.jav

插入排序 | 冒泡排序 | 希尔排序 | 堆排序 | 快速排序 | 选择排序 | 归并排序

以下是最近学习各种算法的代码实现: #include <stdlib.h> #include <stdio.h> #include <time.h> #include <limits.h> typedef int EleType; typedef int (*CompFunc)(void *,void *); int IntComp(void * a,void *b) { if(*(int *)a > *(int *)b) return 1; if(*

java排序之插入排序(直接插入排序和希尔排序)

上面一片博文探讨了关于的java选择排序(冒泡排序和快速排序)本章将继续探讨java排序之插入排序,插入排序分为直接插入排序和希尔排序两种. 1.直接插入排序思想:在需要排序的一组数据中假设前该数组的前n-1(n >= 2)个数是已经排好序的,现在要把第n个数插入到前面的n-1个数中,使得这n个数也是排好顺序的.如此反复进行,知道n等于需要排序的数组的长度时.就实现了该数组的直接插入排序. 代码如下: /** * * @param a 需要排序的数组 */ public static void