第十一章(2).置换—选择排序

#include < stdio.h >
#include < stdlib.h >

#define w  6
#define MAXKEY 100    //最大关键字
#define MINKEY 0    //最小关键字
#define N  24    //数据个数

typedef  int  KeyType ;
typedef  int  LoserTree[ w ] ;

typedef struct {
 KeyType key ;
// int  sign ;
}RcdType ;
typedef struct {
 RcdType  rec ;    //记录
 KeyType  key ; 
 int   rnum ;    //所属归并段号
} RcdNode , WorkArea[ w ] ;   //内存工作区,容量为w

void Replace_Selection( LoserTree *ls , WorkArea *wa , FILE *fi , FILE *fo ) ;
void get_run( LoserTree *ls , WorkArea *wa , int rc , int *rmax , FILE *fi , FILE *fo ) ;
void Select_MinMax( LoserTree *ls , WorkArea wa , int q ) ;
void Construct_Loser( LoserTree *ls , WorkArea *wa , FILE *fi ) ;

 

#include "RepSelSorting.h"

void Replace_Selection( LoserTree *ls , WorkArea *wa , FILE *fi , FILE *fo )
{ //在败者树ls和内存工作区wa上用置换—选择排序求初始归并段,fi,fo两文件指针所指文件均已打开
 int rc , rmax ;
 
 Construct_Loser( ls , wa , fi ) ;    //初建败者树
 rc = rmax = 1 ;         //rc指示当前生成的初始归并段的段号
             //rmax指示wa中关键字所属初始归并段的最大段号
 while( rc <= rmax )        // "rc = rmax+1"标志输入文件的置换—选择排序已完成
 {
  get_run( ls , wa , rc , &rmax , fi , fo ) ; //求得一个初始归并段
 // fwrite( &RUNEND_SYMBOL , sizeof( RcdType ) , 1 , fo ) ;//将段结束标志写入输入文件
  fputs( "*\n" , fo ) ;
  rc = (*wa)[ (*ls)[0] ].rnum ;     //设置下一段的段号
 }
}

void get_run( LoserTree *ls , WorkArea *wa , int rc , int *rmax , FILE *fi , FILE *fo )
{ //求得一个初始归并段,fi,fo为输入输出文件指针
 int q , minmax ;

 while( (*wa)[ (*ls)[0] ].rnum == rc )    //选得的MINMAX记录属当前段时
 {
  q = (*ls)[ 0 ] ;       //q指示MINMAX记录在wa中的位置
  minmax = (*wa)[ q ].key ;

 // fwrite( &wa[ q ]->rec , sizeof( RcdType ) , 1 , fo ) ;//将选好的MINMAX记录写入输出文件
  fprintf( fo , "%d " , (*wa)[ q ].key ) ;
  if( feof( fi ) )       //输入文件结束,虚设记录( 属"rmax+1"段 )
  { 
   (*wa)[ q ].rnum = (*rmax) + 1 ;
   (*wa)[ q ].key = MAXKEY ;  
  }
  else
  {
  // fread( &wa[ q ]->rec , sizeof( RcdType ) , 1 , fi ) ; //读入下一个记录
   fscanf( fi , "%d" , &(*wa)[ q ].rec ) ;
   (*wa)[ q ].key = (*wa)[ q ].rec.key ;  //提取关键字
   
   if( (*wa)[ q ].key < minmax )    //新读入的记录属下一段
   {
    (*rmax) = rc + 1 ;
    (*wa)[ q ].rnum = (*rmax) ;
   }
   else
    (*wa)[ q ].rnum = rc ;    //新读入的记录属于当前段
  }
  Select_MinMax( ls , *wa , q ) ;    //选择新的MINMAX记录
 }
}

void Select_MinMax( LoserTree *ls , WorkArea wa , int q )
{ //从wa[q]起到败者树的根比较选择MINMAX记录,并由q指示它所在的归并段
 int t , p , temp ;
 for( t = ( w + q ) / 2 , p = (*ls)[t] ; t > 0 ; t = t/2 , p = (*ls)[t] )
 {
  if( wa[ p ].rnum < wa[ q ].rnum || ( wa[ p ].rnum == wa[ q ].rnum && wa[ p ].key < wa[ q ].key ) )
  {
   temp = q ;
   q = (*ls)[t] ;       //q指示新的胜利者
   (*ls)[t] = temp ;
  }
 }
 (*ls)[ 0 ] = q ;
}

void Construct_Loser( LoserTree *ls , WorkArea *wa , FILE *fi )
{ //输入w个记录到内存工作区wa,建得败者树ls, 选出关键字最小的记录并由s指示其在wa中的位置
 int i ;
 for( i = 0 ; i < w ; ++ i )
  (*wa)[ i ].rnum = (*wa)[ i ].key = (*ls)[ i ] = 0 ;//工作区初始化 

 for( i = w - 1 ; i >= 0 ; -- i )
 {
 // fread( &(*wa)[ i ].rec , sizeof( RcdType ) , 1 , fi ) ;//输入一个记录
  fscanf( fi , "%d" , &(*wa)[ i ].rec ) ;
  (*wa)[ i ].key = (*wa)[ i ].rec.key ;    //提取关键字

  (*wa)[ i ].rnum = 1 ;        //其段号为"1"
  Select_MinMax( ls , *wa , i ) ;     //调整败者
 }
}
int main( )
{

 LoserTree ls ;
 WorkArea wa ;
 FILE *fi , *fo ;

 if( !( fi = fopen( "Input.txt" , "r" ) ) || !( fo = fopen( "Output.txt" , "w" ) ) )   //重新打开
 {
  exit( 0 ) ;
 }

 Replace_Selection( &ls , &wa , fi , fo ) ;

 fclose( fi ) ;
 fclose( fo ) ;
 return 0 ;


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值