排序之直接插入排序

                    排序之直接插入排序

    插入排序的基本思想是:每次将一个待排序的元素,按其大小插入到已经排好序的子序列中的适当位置,直到全部元素插入完成为止,下面先来介绍一下直接插入排序。

   直接插入排序的思路是:假设待排序的元素放在数组a[0..n-1]中,排序过程中的某一时刻,a被划分为两个子区间a[0…i-1]和a[i…n-1](刚开始时i=1,有序区只有a[0]一个元素),其中,前一个子区间是已经排好序的有序区,后一个区间则是当前未排序的部分,称其为无序区。直接插入排序的一趟操作是将当前无序区的开头元素a[i](1<=i<=n)插入到有序区a[0..i-1]中适当的位置,使a[0….i]变为新的有序区,过程如下所示,该方法称为增量法,因为它每趟操作使有序区增加一个元素。

                                                         有序区              无序区

                         开始时:        { a[0]…..a[i-1]}      { a[i]….a[n-1] }

                 一趟排序后:    { a[0]…...a[i-1]a[i]}    { a[i+1]….a[n-1] }

 

   下面先来说一下直接插入排序的过程:直接插入排序由两重循环构成,对于具有n个元素的序列,外循环要进行n-1趟排序,把所有的元素均插入到序列中。在每一趟排序中,仅当待插入的元素a[i]的值大于等于a[i-1]的值时(亦即此时a[i]的值大于序列a[0….i-1]的所有的值,才无需进入内循环。内循环的作用是把待插入的元素插入到合适的位置上,可以使用元素后移或者元素的交换来实现。下面先给出根据这一思路得到的最直接的代码,然后再给出其优化,为了方便阅读,有些重要语句的意思直接在代码中给出,就不再另写了。

//先判断出要插入的位置,再进行移动覆盖
void Sort_insert(int *a, int n)
{
       inti,j,k;
       for(i=1;i<n;i++)
       {
              for(j=i-1;j>=0;j--)
              {
                     if(a[j]<a[i])
                            break;
              }
              //找到比a[i]大的最小位置,结果再减去1(j--),也就是满足a[j]<a[i]的最大j值
              //所以下面进行数据移动时,K>j,因为a[j]<a[i],不应该参加移动
              if(j!= i-1)
              {
                     inttemp = a[i];
                     for(k=i-1;k>j;k--)
                            a[k+1]= a[k];
                     a[k+1]= temp;//把a[i]的值放到正确顺序的位置上
              }
       }

简化后的代码:

//不是事先找到合适的位置,而是边比较边移动
//不使用移动覆盖,用swap函数交换比较简洁
//不过弱化了直接插入的概念,和冒泡排序法有相似之处
//exchange numbers
void swap(int &Num1, int &Num2)
{
       inttemp;
       temp= Num1;
       Num1= Num2;
       Num2= temp;
}
//sort
void Sort_insert(int *a, int n)
{
       inti,j;
       for(i=1;i<n;i++)
              for(intj=i-1; j>=0 && a[j]>a[j+1]; j--)
                     swap(a[j],a[j+1]);
}


  直接插入排序在序列最初为正序时,算法的时间复杂度为最好的情况,为O(n),在最初的序列为反序时,算法的最坏时间复杂度为O(n^2),算法的平均时间复杂度为O(n^2),另外直接插入排序属于就地排序算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值