第九章(2).次优查找树

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

//顺序查找以及折半查找最优的前提是各记录被查找的概率相等!而显示中很多地方,各记录的查找概率不等!
//在概率不等的情况下,取最小的二叉树为静态最优查找树(Static Optimal Search Tree),
//由于构造静态最优查找树花费的时间代价较高,所以有了次优查找树(Nearly Optimal Search Tree)
#include < stdio.h >
#include < stdlib.h >
#include < math.h >
#include < string.h >

 

#define TRUE 1  
#define FALSE 0    
#define OK 1
#define ERROR 0
typedef int Status ;

 

typedef char KeyType ; 
typedef struct {   
 KeyType  key ;  
 float  weight ;
} SElemType ;

typedef struct {     //静态查找表的顺序存储结构
 SElemType *elem ;    //数据元素存储的空间基址,建表时按实际长度分配,0号单元留空.
 int   length ;   //表长度
} SSTable ;

//------------------------Link Tree--------------------------//

typedef SElemType TElemType ;
typedef struct BiTNode
{
 TElemType data ;
 struct BiTNode *lchild , *rchild ;//有时为了便于找到双亲,可以加一个指向双亲的指针域
} BiTNode , *BiTree ;

//-----------------------------------------------------------//

Status Creat_Seq( SSTable *ST , int n , SElemType *Data ) ;
Status Destroy( SSTable *ST ) ;

 

typedef BiTree SOSTree ;

 

void SecondOptimal( BiTree *T ,  SElemType R[] , float sw[] , int low , int high ) ;
void Find( float *sw , SSTable ST ) ;
Status CreateSOSTree( SOSTree *T ,  SSTable ST ) ;

Status SOSSearch( SOSTree T , KeyType key ) ;
void visit( SElemType e ) ;


Status DestroySOSTree( BiTree *T ) ;
Status SOSTreeEmpty( BiTree T ) ;

 

Status SOSTreeAjust( SOSTree *T ) ;

//-------------------------Link Queue---------------------------//

typedef SOSTree QElemType ;
typedef struct QNode               //链结点
{
 QElemType data ;
 struct QNode *next ;
} QNode , *QueuePtr ;

typedef struct                   
{
 QueuePtr front ;            //队头指针   队头出元素
 QueuePtr rear ;             //队尾指针   队尾进元素
} LinkQueue ;

Status InitQueue(LinkQueue *Q) ;
Status EnQueue(LinkQueue *Q, QElemType e) ;
Status DeQueue(LinkQueue *Q, QElemType *e) ;
Status QueueEmpty(LinkQueue Q) ;


 

//----------------------------Basic Fuction!----------------------------------//

Status Creat_Seq( SSTable *ST , int n , SElemType *Data )  //创建顺序表
{
 int i ;

 ( *ST ).elem = ( SElemType * )malloc( sizeof( SElemType ) * ( n + 1 ) ) ;           //0号单元不用
 if( !( *ST ).elem )
 {
  printf( "Malloc failed!\n") ;
  return ERROR ;
 }

 for( i = 1 ; i <= n ; ++ i )
 {
  ( *ST ).elem[ i ] = Data[ i - 1 ] ;    
 }
 ( *ST ).length = n ;

 return OK ;
}

Status Destroy( SSTable *ST )
{
 free( ( *ST ).elem ) ;
 ( *ST ).elem = NULL ;
 ( *ST ).length = 0 ;
 return OK ;
}

//---------------------------------------------------------------------------------//

void SecondOptimal( BiTree *T ,  SElemType R[] , float sw[] , int low , int high )
{ //由有序表R[low…high]及其累积权值表sw(其中sw[0]==0)递归构造次优查找树T.
 int j , i = low ;
 float min = abs( sw[ high ] - sw[ low ] ) ;
 float dw = sw[ high ] + sw[ low - 1 ] ;

 for( j = low + 1 ; j < high + 1 ; ++ j )
 {
  if( abs( dw - sw[ j ] - sw[ j - 1 ] ) < min )
  {
   i = j ;
   min = abs( dw - sw[ j ] - sw[ j - 1 ] ) ;
  }
 }

 ( *T ) = ( BiTree )malloc( sizeof( BiTNode ) ) ;
 ( *T )->data = R[ i ] ;           //生成结点

 if( i == low )
  ( *T )->lchild = NULL ;
 else
  SecondOptimal( &(( *T )->lchild) , R , sw , low , i - 1 ) ; //构造左子树
 
 if( i == high )
  ( *T )->rchild = NULL ;
 else
  SecondOptimal( &(( *T )->rchild) , R , sw , i + 1 , high ) ;//构造右子树
}

void Find( float *sw , SSTable ST )
{ //按照由有序表ST中个数据元素的weight域求累计权值表sw.
 int i ;

 sw[ 0 ] = 0 ;
 for( i = 1 ; i < ST.length + 1 ;  ++ i )
  sw[ i ] = ST.elem[ i ].weight + sw[ i - 1 ] ;    //此处求累计权值
}

Status CreateSOSTree( SOSTree *T ,  SSTable ST )
{ //由有序表ST构造一颗次优查找树T. ST的数据元素含有权域weight.
 float *sw ;

 sw = ( float * )malloc( sizeof( float ) * ( ST.length + 1 ) ) ;
 if( ST.length == 0 || !sw )
  ( *T ) = NULL ;
 else
 {
  Find( sw , ST ) ; 
  SecondOptimal( T , ST.elem , sw , 1 , ST.length ) ;
 }
 return OK ;
}

Status SOSSearch( SOSTree T , KeyType key )
{
 LinkQueue Q ;
 QElemType a ;

 if( T )
 {
  InitQueue( &Q ) ;
  EnQueue( &Q , T ) ;     //根指针入栈
  while( !QueueEmpty( Q ) )
  {
   DeQueue( &Q , &a ) ;
   if( key == a->data.key )
   {
    visit( a->data ) ;
    return OK ;
   }
   else
   {
    if( a->lchild )
     EnQueue( &Q , a->lchild ) ;
    if( a->rchild )
     EnQueue( &Q , a->rchild ) ;
   }
  }//--while--//
 }
 return ERROR ;
}

void visit( SElemType e )
{
 printf( "%c %f\n" , e.key , e.weight ) ;
}

Status DestroySOSTree( SOSTree *T )    
{
 if( *T )
 {
  if( ( *T )->lchild )
  {
   DestroySOSTree( &( *T )->lchild ) ;
  }
  if( ( *T )->rchild )
  {
   DestroySOSTree( &( *T )->rchild ) ;
  }
  free( *T ) ;
  ( *T ) = NULL ;
 }
 return OK ;
}

Status SOSTreeEmpty( SOSTree T )
{
 if( !T )  
  return TRUE ;
 return FALSE ; 
}

//-------------- 树调整算法-----------------------//
/*
void AjustSecond( BiTNode *subtree , BiTNode *leaf )  //将leaf嫁接到subtree上:"subtree->data.weight > leaf->data.weight' already.
{
 while( subtree )
 {
  if( !subtree->lchild || !subtree->rchild )        
  {
   if( !subtree->lchild )
    subtree->lchild = leaf ; 
   else
    subtree->rchild = leaf ; 
   return ;
  }
  else
  {
   if( subtree->lchild->data.weight < subtree->lchild->data.weight )
    subtree = subtree->lchild ;
   else
    subtree = subtree->lchild ;   
  }
 } 
}

Status SOSTreeAjust( SOSTree *T )       //没有达到要求,有逻辑错误!
{ //因为在构造次优查找树的过程中,没有考察单个关键字的相应权值,则有可能出现被选为根的关键字的权值比 (只是可能哦)
 //它相邻的关键字的权值小,所以需要调整:选取邻近的权值较大的关键字作次优查找树的跟结点
 BiTNode *Node ;

 if( !( *T )->lchild || !( *T )->rchild || ( ( *T )->data.weight > ( *T )->lchild->data.weight && ( *T )->data.weight > ( *T )->rchild->data.weight ) )
  return OK ;
 else  //要么其中一者不存在,要么( *T )->data.weight小于左右子树中的一者
 {
  if( !( *T )->lchild ||  ( *T )->rchild->data.weight > ( *T )->data.weight  ) //向左子树移动
  {   
   Node = ( *T )->rchild ;   
   if( !( *T )->lchild )
    AjustSecond( Node , ( *T ) ) ;
   else
   {
    ( *T )->rchild = NULL ;
    SOSTreeAjust( T ) ;
    AjustSecond( Node , *T ) ;
   }   
  }
  else               
  {
   if( !( *T )->rchild ||  ( *T )->lchild->data.weight > ( *T )->data.weight  )//向右子树移动
   {
    Node = ( *T )->lchild ;
    if( !( *T )->rchild )
    {
     AjustSecond( Node , ( *T ) ) ;
    }
    else
    {
     ( *T )->lchild = NULL ;
     SOSTreeAjust( T ) ;
     AjustSecond( Node , *T ) ;
    }
   }
  }     
  ( *T ) = Node ;  
  return OK ;
 }
}
*/

//---------------------------------------------------------------------------//

int main( )
{
 SSTable ST ;  //表
 SOSTree T ;   //树
 SElemType Data[ ] = { { 'A' , 1 } , { 'B' , 30 } , { 'C' , 2 } , { 'D' , 29 } , { 'E' , 3 } } ;

 Creat_Seq( &ST , 5, Data ) ;   //创建表
 CreateSOSTree( &T , ST ) ;    //创建树
 SOSSearch( T , 'A' ) ;

//SOSTreeAjust( &T ) ;

 return 0 ;
}

下一部分内容本为索引顺序表的查找,但因为在第四章有关于索引表的处理相关,所以对该部分不做叙述!
0 0
原创粉丝点击