插入排序的几种算法

原创 2015年07月10日 17:12:57

1.直接插入排序
直接插入排序是一种最简单的排序方法,它的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的、记录数增1的有序表。
一般情况下,第i趟直接插入排序的操作为:在含有i-1个记录的有序子序列r[1…i-1]中插入一个记录r[i]后,变成含有i个记录的有序子序列r[1…i];并且,和顺序查找类似,为了在查找插入位置的过程中避免数组下标出界,在r[0]处设置监视哨。在自i-1起往前搜索的过程中,可以同时后移记录。直接插入的时间复杂度为O(n²)。

void InsertionSort(Elem R[] , int n){
    //对R[1]-R[n]做直接插入排序,R[0]做监视哨
    int i,j;
    for(i=2;i<=n,i++){
        if(R[i].key<R[i-1].key){
            R[0]=R[i];     //复制到监视哨
            for(j=i-1;R[j].key>R[0].key;--j){
                R[j+1]=R[j];   //元素后移
            }
            R[j+1]=R[0];   //插入到正确位置
        }
    }
}

2.折半插入排序
由于插入排序的基本操作就是在一个有序表中进行查找和插入,这个“查找”可以利用“折半查找”来实现,由此进行的插入排序称之为折半插入排序,算法如下。

void BInsertSort(Elem R[] , int n){
    int i,j;
    for(i=2;i<=n,++i){
        if(R[i].key<R[i-1].key){
            R[0]=R[i];     //复制到监视哨
            //折半查找插入位置
            //查找到相等继续查找到插入为止,最后插入位置一定为high+1
            int low=1;
            int high=i-1;
            while(low<=high){
                int m = (low+high)/2;
                if(R[m].key<R[0].key){
                    low=m+1;
                }else{
                    high=m-1;
                }
            }
            for(j=i-1;j>=high+1;--j){
                R[j+1]=R[j];   //元素后移
            }
            R[j+1]=R[0];   //插入到正确位置
        }
    }
}

折半插入排序所需附加存储空间和直接插入排序相同,从时间上比较,折半插入排序仅减少了关键字间的比较次数,而记录的移动次数不变,因此时间复杂度仍为O(n²)。
3.表插入排序

 typedef struct
 {
   RedType rc; /* 记录项 */
   int next; /* 指针项 */
 }SLNode; /* 表结点类型 */

 typedef struct
 {
   SLNode r[SIZE]; /* 0号单元为表头结点 */
   int length; /* 链表当前长度 */
 }SLinkListType; /* 静态链表类型 */

 void TableInsert(SLinkListType *SL,RedType D[],int n)
 { /* 由数组D建立n个元素的表插入排序的静态链表SL */
   int i,p,q;
   (*SL).r[0].rc.key=INT_MAX; /* 表头结点记录的关键字取最大整数(非降序链表的表尾) */
   (*SL).r[0].next=0; /* next域为0表示表尾(现为空表,初始化) */
   for(i=0;i<n;i++)
   {
     (*SL).r[i+1].rc=D[i]; /* 将数组D的值赋给静态链表SL */
     q=0;
     p=(*SL).r[0].next;
     while((*SL).r[p].rc.key<=(*SL).r[i+1].rc.key)
     { /* 静态链表向后移 */
       q=p;
       p=(*SL).r[p].next;
     }
     (*SL).r[i+1].next=p; /* 将当前记录插入静态链表 */
     (*SL).r[q].next=i+1;
   }
   (*SL).length=n;
 }

表插入排序的时间复杂度仍为O(n²)。
4.希尔排序
希尔排序又称为“缩小增量排序”,时间效率较前面几种方法有很大改进。
直接插入排序为“正序”的时候,时间复杂度为O(n),由此可设想,待排序记录序列关键字“基本有序,直接插入排序的效率就大大提高;从另一方面看,由于直接插入排序算法简单,则在n值很小时效率比较高。希尔排序正是从这两点分析出发对直接插入排序进项改进得到的一种排序算法。
它的基本思路是:先将整个待排记录序列分割成若干个子序列分别进行直接插入排序,待整个序列中的记录”基本有序“时,在对全体记录进行一次直接插入排序。
特点是:子序列的构成不是简单地逐断分割,而是相隔某个”增量“的记录组成一个子序列,最后在进行一次增量是1的插入排序(等同于直接插入排序),此时序列以基本有序,只需要进行少量的比较和移动即可完成排序。

void  ShellInsert(ElemType R[] , int dk){
    //对顺序表R做一趟希尔插入排序。本算法与一趟直接插入排序,做了一下修改
    //1.前后记录位置的增量是dk,而不是1
    //2.R[0]只是暂存单元,不是哨兵。当j<=0时,插入位置已经找到
    int i,j;
    for(i=dk+1;i<n;1++){
        if(R[i].key<R[i-1].key){    // 需将R[i]插入到有序增量子表
            R[0]=R[i];              // 暂存在R[0]
            for(j=i-dk;j>0&&(R[j].key>R[0].key);j-=dk){
                R[j+dk]=R[j];       //记录后移,查找插入位置
            }
            R[j+dk]=R[0];           //插入
        }
    }
}

void ShellSort(ElemType R[] ,int dlta[], int t){
    //按增量序列dlta[0...t-1]对顺序表R做希尔排序
    int k;
    for(k=0;k<t;k++){
        ShellInsert(R,dlta[k]);     //一趟增量为dlta[k]的插入排序
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

几种插入排序法

几种常用的排序算法的分析及java实现(希尔排序,堆排序,归并排序,快速排序,选择排序,插入排序,冒泡排序)

最近决定每天学点数据结构与算法,写博客来督促自己继续学习~ 以下的每个排序的写法格式基本按照先介绍基本思想,再描述具体过程,最后是具体代码。关于复杂度等问题后续更新。如有写的不严谨的地方,欢迎指出,...

常见的几种排序算法一-选择排序,插入排序

对于排序,有的语言有特定的api,数据库里面也有排序的算法,但是一般不会公布,在这只是总结一下常见的排序算法,也算不辜负数据结构老师之前的谆谆教诲。参见算法(Algorithms Fourth Edi...
  • yhtgb
  • yhtgb
  • 2015-12-27 22:35
  • 149

几种基本的排序算法:选择排序、插入排序、冒泡排序

选择排序(Selection sort)、插入排序(Insertion sort)与冒泡排序(Bubble sort)這三个排序方式是初学排序所必须知道的三个基本排序方式,它们由于速度不快而不实用(时...

c语言中的几种排序算法——冒泡排序、快速排序、插入排序、选择排序

排序算法是我们会经常用到的,也是c语言中很重要的一个部分,我就把我整理的这几种排序的算法介绍给你们 :  第一种 : 快速排序   快速排序法(QuickSort)是一种非常快的对比排序方...

几种常用的排序算法(冒泡,插入排序,希尔排序,快速排序)

#include #include using namespace std; /*     冒泡排序     冒泡排序总的比较次数为:(n-1)+(n-2)...+1=n*(n-1)/2     ...

几种常用的排序算法:插入排序、冒泡排序、选择排序的算法及C++实现

所谓排序呢,就是要整理数组中的元素,使之按照递增或递减的次序排列起来。一般学习C语言编程的时候,首先学会写的程序就是排序,但是即便是这么简单的程序,在现在考起来,很多人不一定能正确的写出来。我也是在准...

几种排序算法(冒泡排序算法,选择排序算法,快速排序算法,插入排序)

#import void quick_sort(int s[], int l, int r); void InsertSort(int a[], int n); int main(int argc,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)