排序算法之一--直接插入排序

直接插入排序中加入了附加记录,又称监视哨或者哨兵。

哨兵的主要作用:

        ① 进人查找(插入位置)循环之前,它保存了R[i]的副本,使不致于因记录后移而丢失R[i]的内容;
      ② 它的主要作用是:在查找循环中监视下标变量j是否越界。一旦越界(即j=0),因为R[0].可以和自己比较,循环判定条件不成立使得查找循环结束,从而避免了在该循环内的每一次均要检测j是否越界(即省略了循环判定条件j>=1)。

      下面的c函数,是基础的直接插入排序,但是更容易帮助理解哨兵的意思

      

void insert_sort(int a[],int n)

//待排序元素用一个数组a表示,数组有n个元素

{

    int i,j;

    int temp;

    for i=1; i<n; i++) //i表示插入次数,共进行n-1次插入

  {

      temp=a[i]; //把待排序元素赋给temptempwhile循环中并不改变,这样方便比较,并且它是要插入的元素

      j=i-1;

      //while循环的作用是将比当前元素大的元素都往后移动一个位置

      while ((j>=0)&& (temp<a[j])){

          a[j+1]=a[j];

          j--; // 顺序比较和移动,依次将元素后移动一个位置

          }

 

      a[j+1]=temp;//元素后移后要插入的位置就空出了,找到该位置插入

  }

}

          上面的temp就相当于哨兵的意思

          下面是改进版的算法:

   void lnsertSort(SeqList R)
   {                                                     //对顺序表R中的记录R[1..n]按递增序进行插入排序
    int i,j;
    for(i=2;i<=n;i++)                         //依次插入R[2],…,R[n]
      if(R[i].key<R[i-1].key){                //若R[i].key大于等于有序区中所有的keys,则R[i]
                                                         //应在原有位置上
        R[0]=R[i];j=i-1;                          //R[0]是哨兵,且是R[i]的副本
        do{                                            //从右向左在有序区R[1..i-1]中查找R[i]的插入位置
         R[j+1]=R[j];                            //将关键字大于R[i].key的记录后移
         j-- ;
         }while(R[0].key<R[j].key);      //当R[i].key≥R[j].key时终止
        R[j+1]=R[0];                            //R[i]插入到正确的位置上
       }//endif
   }


   算法用c语言实现了,现在来分析一下时间复杂度和空间复杂度

   从空间上:

           只需要一个哨兵来辅助,因此空间复杂度为O(1)

   从时间上:

           最好的情况:所有的序列本来就是是需要的序列(顺序或者逆序),但还是需要遍历一遍所有元素,那个器时间复杂度为O(n)

           最坏的情况:所有的序列和需要的序列恰恰相反,需要(1,2,3,4,5),原序列是(5,4,3,2,1),那就需要在遍历每一个元素的时候,要进行一波与前面元素的交换,此时的时间复杂度为2+3+4+...+n 其时间复杂度为O(n2)

           一般情况:排序记录是随机的,

     稳定性:稳定的

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值