【数据结构】插入排序

插入排序的基本思想是:每步将一个待排序的对象,按其关键字大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。

简言之,边插入边排序,保证子序列中随时都是排好序的。

直接插入排序

新元素插入到哪里?在已形成的有序表中线性查找,并在适当位置插入,把原来位置上的元素向后顺移。

关键字序列T=(13,6,3,31,9,27,5,11),请写出直接插入排序的中间过程序列。

图示

关键字序列T= (21,25,49,25*,16,08),请写出直接插入排序的具体实现过程。*表示后一个25

假设该序列已存入一维数组V[7]中,将V[0]作为缓冲或暂存单元(Temp)。则程序执行过程为:

图示

图示

Void InsertSort (SqList  &L) ——教材P265
{  // 对顺序表L做直接插入排序
    for ( i=2; i<=L.length; ++i )
       if (  LT (L.r[i].key, L.r[i-1].key) ) 
                                         // “<“,需将L.r[i]插入有序子表
         {  L.r[0] = L.r[i];          // 复制为哨兵
            L.r[i] = L.r[i-1];
            for ( j=i-2; LT(L.r[0].key, L.r[j].key); --j )
               L.r[ j+1] = L.r[ j];   // 记录后移
            L.r[ j+1] = L.r[0];     // 插入到正确位置
          }
}  // InsertSort
<?php
function insert_sort($arr) {
    //从第二个元素开始,到最后一个元素都是这个需要排序的元素
    for($i=1, $len=count($arr); $i<$len; $i++) {
        //获得当前需要比较的元素值。
        $tmp = $arr[$i];
        //内层循环控制 比较 并 插入
        for($j=$i-1;$j>=0;$j--) {
            //$arr[$i];//需要插入的元素; $arr[$j];//需要比较的元素
            if($tmp < $arr[$j]) {
                //发现插入的元素要小,交换位置
                //将后边的元素与前面的元素互换
                $arr[$j+1] = $arr[$j];
                //将前面的数设置为 当前需要交换的数
                $arr[$j] = $tmp;
            } else {
                //如果碰到不需要移动的元素
                //由于是已经排序好是数组,则前面的就不需要再次比较了。
                break;
            }
        }
    }
    //将这个元素 插入到已经排序好的序列内。
    //返回
    return $arr;
}
$arr = array(21,25,49,25,16,8);
$arr = insert_sort($arr);
print_r($arr);

折半插入排序

在已形成的有序表中折半查找,并在适当位置插入,把原来位置上的元素向后顺移。

图示

Void  BInsertSort (SqList  &L)  // 折半插入排序
{  for ( i=2;i<=L.length;++i )
   {  L.r[0] = L.r[ i ];      // 将L.r [i] 暂存到L.r[0]
      low=1;high=i-1while (low<=high)     //比较,折半查找插入位置
      {  m=(low+high)/2// 折半
         if (LT(L.r[0].key,L.r[m].key))  high=m-1//插入点在低半区
         else   low=m+1// 插入点在高半区
       } // while
      for (j=i-1;j>=high+1;--j)  L.r [j+1] = L.r [j];// 记录后移
      L.r [high+1] = L.r [0];                       // 插入
    }  // for
}  // BInsertSort

希尔(shell)排序(又称缩小增量排序)

基本思想:先将整个待排记录序列分割成若干子序列,分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。

技巧:子序列的构成不是简单地“逐段分割”,而是将相隔某个增量dk的记录组成一个子序列,让增量dk逐趟缩短(例如依次取5,3,1),直到dk=1为止。

优点:让关键字值小的元素能很快前移,且序列若基本有序时,再用直接插入排序处理,时间效率会高很多。

这里写图片描述

算法分析:开始时dk 的值较大,子序列中的对象较少,排序速度较快;随着排序进展,dk 值逐渐变小,子序列中对象个数逐渐变多,由于前面工作的基础,大多数对象已基本有序,所以排序速度仍然很快。

图示

void   ShellInsert (SqList &L,int dk) {
//对顺序表L进行一趟增量为dk的Shell排序,dk为步长因子

for(i=dk+1;i<=L.length; ++ i)//开始将r[i] 插入有序增量子表

      if (r[i].key < r[i-dk].key)  {         
       r[0]=r[i];//暂存在r[0]
       for( j=i-dk; j>0 &&(r[0].key<r[j].key); j=j-dk )
     r[ j+dk ]=r[j];//关键字较大的记录在子表中后移
        r[ j+dk ]=r[0];//在本趟结束时将r[i]插入到正确位置
       }
}
<?php

//希尔排序(对直接插入排序的改进)

function ShellSort(array &$arr)
{
    $count = count($arr);
    $inc = $count;    //增量
    do {
        //计算增量
        //$inc = floor($inc / 3) + 1;
        $inc = ceil($inc / 2);
        for ($i = $inc; $i < $count; $i++) {
            $temp = $arr[$i];    //设置哨兵
            //需将$temp插入有序增量子表
            for ($j = $i - $inc; $j >= 0 && $arr[$j + $inc] < $arr[$j]; $j -= $inc) {
                $arr[$j + $inc] = $arr[$j]; //记录后移
            }
            //插入
            $arr[$j + $inc] = $temp;
        }
        //增量为1时停止循环
    } while ($inc > 1);
}

$arr = array(49,38,65,97,76,13,27,49,55,4);
ShellSort($arr);
var_dump($arr);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值