(二)插入排序:直接插入排序,希尔排序

直接插入排序指的是先将一小部分排好序,然后从未排序的元素中找一个出来.遍历已排序好的数组,插入到合适位置.

 

直接插入排序:

void StraightInsertSort(int* arr, int len)

{

    int tmp;

    int j;

    for(int i = 1; i < len; i++)

       {

           tmp = arr[i];

           for(j = i-1; j >=0 ; j --)  //遍历已经排好序的部分,找到合适的位置j + 1

           {

              if( arr[j] >= tmp)

                break;

           }

         for(int k = i; k > j + 1; k--) //把位置j + 1后面的元素右移

           {

                arr[k] = arr[k -1];

            }

         arr[j + 1] = tmp;  //插入元素到位置j+1

       }

}

 

我们看到在从已经排好序的数组中找合适的位置的时候可以改进一下,用下二分查找的方法.

 

改进的插入排序算法:(有时也叫作二分插入排序)

void BinaryInsertSort(int* arr, int len)

{

int tmp;

int j;

for(int i = 1; i < len; i++)

{

tmp = arr[i];

int left = 0;

int right = i - 1;

while(left <= right)  //通过二分查找找到合适的插入位置

{

  int mid = (left + right)/2;

  if( tmp == arr[mid])

  {

       j = mid;

       break;

  }

  else if( tmp < arr[mid])

        right = mid -1;

   else if( tmp > arr[mid])

        left = mid + 1;

 

}

 

if(left > right)

    j = left - 1;

for(int k = i; k > j + 1; k--) //把位置j + 1后面的元素右移

{

arr[k] = arr[k -1];

}

arr[j + 1] = tmp; //插入元素到位置j+1

}

}

 

希尔排序(shell sort)

当数组中的元素基本有序的时候采用直接插入排序效率非常高,根据这个思路产生了一个改进的插入排序算法,希尔排序.

大体思路是先把整个待排序元素序列分割成若干子序列(由相隔的增量组成)分别采用直接插入排序,这样每排一次元素就变得更有序,然后增量缩小再接着重复上面的操作.

比如按增量5,3,1,0分别进行插入排序.当增量是1时就相当于对整个数组采取直接插入排序了.

你可能会好奇这个增量是怎么确定的? 这就存在很多不同的方法了,一般用的较多较容易的就是直接用数组长度n除以2,然后把结果继续除2.

void ShellSort(int* arr, int len)

{

   for( int gap = len/2; gap > 0; gap = gap/2) //通过不同的增量来使数组一步步达到更有序的状态

{

     for( int i = 0; i < gap; i ++)

       {

           for(int j = i + gap; j < len; j = j + gap)       //对每个增量产生的子序列进行插入排序

             if( arr[j] < arr[j - gap])

              {

                   int tmp =arr[j];

                  int k ;

                   for( k = j - gap; k >= 0; k = k - gap) 

                    {

                        if( tmp < arr[k])

                            arr[k + gap] = arr[k];

                        else

                             break;

                    }

                   arr[ k +gap] = tmp;

               }

        }

}

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值