第十章(4).希尔排序

来源:互联网 发布:盛世赢家软件下载 编辑:程序博客网 时间:2024/05/17 01:37

#include <iostream>
using namespace std ;
//希尔排序(Shell Sort)又称"缩小增量排序",他是对插入排序类方法的改进
//1.对插入排序的分析得其时间复杂度为O(n*n),但若待排记录为"正序"时,其时间复杂度可提高至O(n)
//2.在直接插入排序中,当n值很小的时候效率比较高

//所以,希尔排序充分利用上述两点,先将待排记录序列分割成若干子序列分别进行直接插入排序,
//待整个序列中的记录"基本有序"时,再对全体记录进行一次直接插入排序

#define  MAXSIZE  20     //存储元素的顺序表的最大长度
typedef  int   KeyType ;   //关键字类型
typedef  int   InfoType ;   //其他数据项类型

typedef  struct {
 KeyType key ;
 InfoType otherinfor ;     //其他数据项
} RedType ;

typedef  struct {
 RedType r[ MAXSIZE + 1 ] ;    //r[0]闲置或用作哨兵单元
 int  length ;      //顺序表长度
} SqList ;         //顺序表类型

void InPut( SqList &L )
{
 int value = 0 ;
 int i = 1 ;
 while( i < ( MAXSIZE + 1 ) )
 {
  cin >> value ;
  if( value == -1 )     //以-1为结束符
   break ;
  L.r[ i ++ ].key = value ;
 }
 L.length = i - 1 ;
}

void ShellInsert( SqList &L , int dk )  //对顺序表L作一趟希尔插入排序(排序为从小到大)
{ //1.前后记录位置的增量是dk,而不是1.
 //2.r[0]只是暂存单元,不是哨兵.当 j <= 0 时,插入位置已找到。

 int j = 0 ;

 for( int i = dk + 1 ; i < L.length + 1 ; ++ i )//Take care! 当增量为dk时,则必须存在dk+1个元素。
 {
  if( L.r[ i ].key < L.r[ i- dk ].key )//L.r[ i- dk ].key没有智能引用key.只有当dk为一个常数时才会有智能引用key.(前面的元素大于后面的元素)
  {
   L.r[ 0 ] = L.r[ i ] ;   //暂存在L.r[ 0 ].
   for( j = i - dk ; j > 0 && ( L.r[ 0 ].key < L.r[ j ].key ) ; j -= dk )
    L.r[ j + dk ] = L.r[ j ] ; //凡是大于的记录均后移,查找插入位置
   L.r[ j + dk ] = L.r[ 0 ] ;  //插入
  }
 }
}

void ShellSort( SqList &L , int dlta[ ] , int t )
{ //按增量序列dlta[0…t-1]对顺序表L作希尔排序
 for( int k = 0 ; k < t ; ++ k )
  ShellInsert( L , dlta[ k ] ) ;  //一趟增量为dlta[k]的插入排序
}

void OutPut( SqList L )
{
 for( int i = 1 ; i < L.length + 1 ; ++ i )
 {
  cout << L.r[ i ].key << ' ' ;
 }
 cout << endl ;
}

int main( )
{ //希尔排序的分析是一个复杂的问题,因为它的时间是所取"增量"序列的函数
 //有人指出当增量序列dlta[k] = "2的(t-k+1)次方减1"时,其时间复杂读为n的2分之3.
 SqList L ;
 int dlta[ 3 ] = { 5 , 3 , 1 } ;   //增量序列可以有各种取法,但是应使增量序列中的值没有除1之外的公因子,并且最后一个增量值必须等于1.

 InPut( L ) ;       //49 38 97 76 13 27 49 55 04 -1(终结符)
 ShellSort( L , dlta , 3 ) ;
 OutPut( L ) ;

 return 0 ;
}


0 0
原创粉丝点击