第五章(1)数组的顺序表示和实现

好吧!在这一章开始之前先说一说我当初的心得吧!

当初,链表,栈和队列,因为老师强调的比较多,运用的也比较多,理解得也很好,代码量也不大,所以完成了比较顺利。再后来,关于串的三种存储表示,代码量稍稍增加,但也不成问题。结果一进入第五章,人就懵了!简直就像之前还在印度平原漫步,结果一抬头,应该是一仰头,就看见喜马拉雅山了!!!着实吓着了,想放弃了,结果还是坚持下去了!

尤其第一节的数组的顺序表示和实现,里面有个很揪心的变参函数!查了很久,大概明白了是什么意思(不过在学术上,最好不要不求甚解!“大概”不好!!)结果也与编译器有若干联系。不过还算让自己满意!

再后来,自己敲的代码也多了,也没觉得当初的代码敲得怎么揪心了,只是有个浅浅的记忆而已!不过我从中也获得了一个很好的启示:当你遇到一个难题时,不要紧,再去找一个更难的题做吧!那样你就会觉得以前那个题也就那么点难度!

 

#include< stdio.h >
#include< stdlib.h >
#include< stdarg.h >    //提供宏va_start,va_arg,va_end.用于存取变长参数表

#define MAX_ARRAY_DIM 8  //数组的最大维数

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define UNDERFLOW -3


typedef int Status;      //函数一般有返回值最好,即使没有用,也可以用来判断
typedef int ElemType ;

typedef struct
{
 ElemType *base ;     //数组元素基址
 int  dim ;           //数组维数
 int  *bounds ;       //数组维界基址
 int  *constants ;    //数组映像函数常量基址
}Array ;

  //-------基本操作的函数原型说明--------
Status InitArray(Array * A, int dim, ...);
          //若维数dim和随后的各维长度合法,则构造相应的数组A,并返回OK
Status SestroyArray(Array * A);
          //销毁数组A
Status Value(Array A, ElemType *e ,...);
          //A是n维数组,e为元素变量,随后是n个下标值。
          //若各下标不超界,则e赋值为所指定的A的元素值,并返回OK
Status Assign(Array * A, ElemType e, ...);
          //A是n维数组,e为元素变量,随后是n各下标值
          //若各下标不超界,则将e的值赋给所指定的A的元素,并返回OK

//--------------------------basic function!----------------------------//
Status InitArray( Array *A , int dim , ... )
{
 va_list ap ;                   //就把 ap 当成是一个 char * 的指针;
 int elemtotal , i ;
 if( dim < 1 || dim > MAX_ARRAY_DIM )
 {
  return ERROR ;
 }
 
 ( *A ).dim = dim ;
 ( *A ).bounds = ( int * ) malloc ( dim * sizeof( int ) ) ;
 if( !( *A ).bounds )
 {
  exit( OVERFLOW ) ;
 }

 elemtotal = 1 ;
 va_start( ap , dim ) ;             //ap为va_list类型,用于存放变长参数表信息的数组
 //va_start(ap, e); va_start 是一个宏,展开后,实际上相当于 ap = (char*)&e + sizeof(e);

 for( i = 0 ; i < dim ; ++ i )
 {
  ( *A ).bounds[ i ] = va_arg( ap , int ) ;   //T var = va_arg(ap, T); 这个相当于 两句话, T var = *(T*)ap; ap+= sizeof(T);
  if( ( *A ).bounds[ i ] < 0 )
  {
   return UNDERFLOW ;
  }
  elemtotal *= ( *A ).bounds[ i ] ;
 }

 va_end( ap ) ;                  //#define va_end(ap)  (void)0

 ( *A ).base = ( ElemType *) malloc ( elemtotal * sizeof( ElemType ) ) ;
 if( !( *A ).base )
 {
  exit( OVERFLOW ) ;
 }

 //求映像函数的常熟Ci,并存入(*A).constants[i-1] , i =1,2……dim;
 ( *A ).constants = ( int * )malloc( dim * sizeof( int ) ) ;
    if( !( *A ).constants )
 {
  exit( OVERFLOW ) ;
 }

 ( *A ).constants[ dim - 1 ] = 1 ;  //L= 1 , 指针的增减以元素的大小为单位   ???

 for( i = dim - 2 ; i >= 0 ; -- i )
 {
  ( *A ).constants[ i ] = ( *A ).bounds[ i + 1 ] * ( *A ).constants[ i + 1 ] ;
 }

 return OK ;
}


Status DestroyArray( Array *A )
{
 if( !( *A ).base )
 {
  return ERROR ;
 }
 free( ( *A ).base ) ; 
 ( *A ).base = NULL ;

    if( !( *A ).bounds )
 {
  return ERROR ;
 }
 free( ( *A ).bounds ) ;
 ( *A ).bounds = NULL ;

 if( !( *A ).constants )
 {
  return ERROR ;
 }
 free( ( *A ).constants ) ;
 ( *A ).constants = NULL ;
 
 return OK ;
}

Status Locate( Array A ,va_list ap , int *off )
{   //若ap指示的各下标值合法,则求出该元素在A中的相对地址off
 int i , ind ;
 ( *off ) = 0 ;

 for( i = 0 ; i < A.dim ; ++ i )
 {
  ind = va_arg( ap , int ) ;          // //T var = va_arg(ap, T); 这个相当于 两句话, T var = *(T*)ap; ap+= sizeof(T);
  if( ind < 0 || ind >= A.bounds[ i ] )
  {
   return OVERFLOW ;
  }
  ( *off ) += A.constants[ i ] * ind ;
 }

 return OK ;
}


Status Value( Array A , ElemType *e , ... )
{    //A是n维数组,*e为元素变量,随后是n个下标值
  //若各下标不超界,则e赋值为所指定的A的元素值,并返回OK
 va_list ap ;
 int off , result ;

 va_start( ap , *e ) ;
 if( ( result = Locate( A , ap , &off ) ) <= 0 )
 {
  return result ;
 }
 *e = *( A.base + off ) ;
 
 return OK ;
}

Status Assign( Array *A , ElemType e , ... )
{   // A是n维数组,e为元素变量,随后是n各下标值
 //若各下标不超界,则将e的值赋给所指定的A的元素,并返回OK
 va_list ap ;
 int off , result ;

 va_start( ap , e ) ;
 if( ( result = Locate( *A , ap , &off ) ) <= 0 )
 {
  return result ;
 }
 va_end( ap ) ;
 *( ( *A ).base + off ) = e ;

 return OK ;
}

//-------------------------------main function!----------------------------//
void main( )
{
 Array A ;
 ElemType e ;
 int i , j ;
 
 int t = 1 ; 

 InitArray( &A , 2 , 2 , 2 ) ;
 for( i = 0 ; i < 2 ; ++ i )
 {
  for( j = 0 ; j < 2 ; ++ j )
  {
   Assign( &A , t , i , j ) ;
   ++ t ;
  }
 }

 for( i = 0 ; i < 4 ; ++ i )
 {
  printf( "%-3d" , A.base[ i ] ) ;
 }

 printf( "\n" ) ;

    Value( A , &e , 0 , 0 ) ;

 printf( "%d\n" , e ) ;

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值