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

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

哨兵的主要作用:

        ① 进人查找(插入位置)循环之前,它保存了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-1次插入

  {

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

      j=i-1;

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

      while ((j>=0)&& (temp

          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[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+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)

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

     稳定性:稳定的

你可能感兴趣的:(排序算法)