第九章(1).顺序查找以及折半查找

来源:互联网 发布:淘宝500的充气娃娃图片 编辑:程序博客网 时间:2024/06/16 03:03

//查找表(Search Table)是由同一类型的数据元素构成的集合。由于"集合"中的数据元素之间存在完全松散的关系,因此查找表是一种非常灵便的数据结构。
//对查找表的操作经常有:(1)查询某个元素是否在表中;(2)检索某个特定元素的各种属性;(3)在查找表中插入一个元素;(4)从查找表中删去某个数据元素.

//静态查找表只对查找表做前两种关于查找的操作。而动态查找表可以做后两种操作。
#include < stdio.h >
#include < stdlib.h >
#include < string.h >
//#include < limits.h >

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

#define N 5
typedef int KeyType ;  //定义关键字的类型

//-----对数值型关键字的比较--------//
#define EQ( a , b ) ( ( a ) == ( b ) )
#define LT( a , b ) ( ( a ) < ( b ) )
#define LQ( a , b ) ( ( a ) <= ( b ) )
//-----字符串型关键字的比较--------//
//#define EQ( a , b ) ( !strcmp( a , b ) )
//#define LT( a , b ) ( strcmp( a , b ) < 0 )
//#defien LQ( a , b ) ( strcmp( a , b ) <= 0 )

typedef struct {   //数据元素
 long Number ;
 char Name[ 10 ] ;
 int Politics ;
 int Chinese ;
 int English ;
 int Math ;
 int Physics ;
 int Chemical ;
 int Biology ;
 KeyType key ;   //关键字 key == totalscore.
} SElemType ;

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

//---------------------------------------------------------------------------//
//顺序表查找:为了提高查找效率,我们可以在每个记录中附设一个访问频度,并使顺序表中的记录始终保持按访问频率度非递减有序的次序排序,或者在每次查找后都将刚查到的记录直接移至表尾。
Status Creat_Seq( SSTable *ST , int n , SElemType *Data ) ;
Status Destroy( SSTable *ST ) ;
Status Search_Seq( SSTable ST , KeyType key ) ;
Status Traverse( SSTable ST , void( *Visit )( ElemType ) ) ;
void visit( SElemType set ) ;

//---------------------------------------------------------------------------//
//以有序表表示静态查找表时,Search可以用折半查找来实现!
Status Ascend( SSTable *ST , int n , SElemType *Data ) ;//创建一个有序表
Status Search_Bin( SSTable ST , KeyType key ) ;
//折半查找效率比顺序查找效率高,但折半查找只适用于有序表,且限于顺序存储结构(对线性链无法有效地进行折半查找)
//(概率相等的情况下,折半查找的性能最优)

#include "head.h"

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

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 ).elem[ i ].Number = Data[ i - 1 ].Number ;
  strcpy( ( *ST ).elem[ i ].Name , Data[ i - 1 ].Name ) ;
  ( *ST ).elem[ i ].Biology = Data[ i - 1 ].Biology ;
  ( *ST ).elem[ i ].Chemical = Data[ i - 1 ].Chemical ;
  ( *ST ).elem[ i ].Chinese = Data[ i - 1 ].Chinese ;
  ( *ST ).elem[ i ].English = Data[ i - 1 ].English ;
  ( *ST ).elem[ i ].Math = Data[ i - 1 ].Math ;  
  ( *ST ).elem[ i ].Physics = Data[ i - 1 ].Physics ;
  ( *ST ).elem[ i ].Politics = Data[ i - 1 ].Politics ;  */
  ( *ST ).elem[ i ].key = Data[ i - 1 ].Biology + Data[ i - 1 ].Chemical + Data[ i - 1 ].Chinese +
   Data[ i - 1 ].English + Data[ i - 1 ].Math + Data[ i - 1 ].Physics + Data[ i - 1 ].Politics ;   //key为总成绩
 }
 ( *ST ).length = n ;

 return OK ;
}

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

Status Search_Seq( SSTable ST , KeyType key )  //在顺序表中查找关键字等于key的数据元素,若找到则返回该元素在表中的位置,否则返回0.
{
 int i ;

 //0号单元留空的.
 ST.elem[ 0 ].key = key ;  //"哨兵",目的在于免去查找过程中每一步都要检测整个表是否查找完毕(需要比较).仅仅这这个技巧的改进,就能使顺序表查找在ST.Length>=1000时,进行一次查找所需的平均时间几乎减少一半.
 for( i = ST.length ; !EQ( ST.elem[ i ].key , key ) ; -- i ) ; //从后往前找,找不到时,i刚好为0
 return i ;
}

Status Traverse( SSTable ST , void( *Visit )( ElemType ) )
{
 SElemType *p ;
 int i ;

 p = ++ST.elem ;
 for( i = 1 ; i <= ST.length ; ++ i )
 {
 // Visit( ST.elem[ i ] ) ;
  Visit( *p++ ) ;
 }
 return OK ;
}

void visit( SElemType set )
{
  printf( "%6ld%8s :%4d,%5d,%5d,%5d,%5d,%5d,%5d,%5d\n" ,set.Number , set.Name , set.Politics , set.Chinese ,
   set.English , set.Math , set.Physics , set.Chemical , set.Biology , set.key ) ;
}

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

Status Ascend( SSTable *ST , int n , SElemType *Data )  //有序表!非递减有序
{
 int i , j , k ;

 Creat_Seq( ST , n , Data ) ;
 for( i = 1 ; i < ( *ST ).length ; ++ i )
 {
  k = i ;    //最小关键字的序号
  ( *ST ).elem[ 0 ] = ( *ST ).elem[ i ] ;

  for( j = i + 1 ; j <= ( *ST ).length ; ++ j )
  {
   if( LT( (*ST).elem[ j ].key , (*ST).elem[ 0 ].key ) ) //(*ST).elem[ 0 ].key不能改为(*ST).elem[ i ].key,否则会成为原表的倒序.
   {
    k = j ;
    ( *ST ).elem[ 0 ] = ( *ST ).elem[ j ] ; //选出最小元素
   }
  }

  if( k != i )
  {
   ( *ST ).elem[ k ] = ( *ST ).elem[ i ] ;
   ( *ST ).elem[ i ] = ( *ST ).elem[ 0 ] ;
  }
 }

 return OK ;
}

Status Search_Bin( SSTable ST , KeyType key )  //折半查找关键字为key的数据元素,若找到则返回该元素的位置,否则返回0.
{
 int low , high , mid ;    //起搜索指针的作用!

 low = 1 ;
 high = ST.length ;

 while( low <= high )
 {
  mid = ( low + high )/2 ;
  if( EQ( key , ST.elem[ mid ].key ) )
  {
   return mid ;
  }
  else
  {
   if( LT( key , ST.elem[ mid ].key ) )
    high = mid - 1 ;
   else
    low = mid + 1 ;
  }
 }
 return 0 ;
}


int main( )
{
 int i , s ;
 SSTable ST ;
 SElemType  Data[ N ] = { { 179324,"何芳芳",85,89,98,100,93,80,47 } , // 全局变量
 { 179325,"陈红",85,86,88,100,92,90,45 } ,
 { 179326,"陆华",78,75,90,80,95,88,37 } ,
 { 179327,"张平",82,80,78,98,84,96,40 } ,
 { 179328,"赵小怡",76,85,94,57,77,69,44 } } ;

// Creat_Seq( &ST , N , Data ) ;
 Ascend( &ST , N , Data ) ; 

 printf( "准考证号  姓名   政治  语文  外语  数学  物理  化学  生物  总分\n" ) ;
    Traverse( ST , visit ) ;  //按顺序输出静态查找表

 printf( "请输入待查找人的总分: " ) ;
    scanf( "%d" , &s ) ;
//  i = Search_Seq( ST , s ) ;  //顺序查找
 i = Search_Bin( ST , s ) ;     //折半查找
 
 if( i )
 {  
  printf( "该学生学号为: %4ld.\n" , ST.elem[ i ].Number ) ;
 }
 else
 {
  printf( "Sorry! 未找到该学生!\n" ) ;
 }

 Destroy( &ST ) ; 
 return 0 ;
}


0 0