第二章(3).静态链表

//这一部分,以前完成得不够后,后来在中途经过了完善才发表的!

//*************************************************************************//

//这种存储结构仍需要预先分配一个较大的空间,但在做线性表的插入和删除操作时不需要移动元素,
//仅需要修改指针,故仍具有链式存储结构的主要优点
#include<stdio.h>
#include<stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -2

#define MAXSIZE 10      //链表最大长度
typedef int ElemType;

typedef struct
{
  ElemType data;
  int cur;     //游标,代替指针指示结点在数组中的相对位置
}component ,SLinkList[MAXSIZE];    //数组的一个分量表示一个结点


void InitSpace_SL(SLinkList space)
{    //将一维数组space中各分量链成一个备用链表,space[0].cur为头指针,"0"表示空指针
  int i = 0 ;
 
  for( i = 0 ; i < MAXSIZE - 1 ; ++ i ) 
  {
   space[ i ].cur = i + 1;
  }
  space[ MAXSIZE - 1 ].cur = 0;   //链表的最后一个单元为空链表的表头
}

//为了辨明数组中那些分量未被使用,解决的办法是将所有未被使用过以及被删除的分量用游标链接成一个备用链表
//每当进行插入时便可以从备用链表上取得第一个结点作为待插入的新结点;反之,删除时将从链表中删除下来的结点链接到备用链表
int Malloc_SL( SLinkList space )
{    //若备用空间链表非空,则返回分配的结点下标,否则返回0
  int i ;
  i = space[0].cur ;
  if( i )  //备用空间链表非空
  {
   space[0].cur =  space[i].cur ;  //分配结点,从链表的头结点开始,即是space[i];
   return i ;
  }     //备用链表的头结点指向原备用链表的第二个结点
  return 0 ;
}

void Free_SL(SLinkList space,int k)  //将下标为k的空闲结点回收到备用链表
{
  space[k].cur = space[0].cur;   // 回收结点的'游标'指向备用链表的第一个结点
  space[0].cur = k;     // 备用链表的头结点指向新回收的结点
}

void ClearList( SLinkList space )  //"void DestroyList()" can't exist! 静态数组不能被销毁
{
  int i , j , k ;

  i = space[ MAXSIZE - 1 ].cur ;   //链表第一个结点的位置
  space[ MAXSIZE - 1 ].cur = 0 ;   //链表空
  k = space[ 0 ].cur ;  //备用链表的第一个结点的位置
  space[ 0 ].cur = i ;  //把链表的结点连到备用链表的表头
  while( i )
  {
   j = i ;
   i = space[ i ].cur ;  
  }
space[ j ].cur = k ;  // 备用链表的第一个结点接到链表的尾部
}

int LocateElem_SL(SLinkList space,ElemType e)   //找到则返回它在L中的位序,否则返回0
{
  int i;
  i = space[0].cur;    //i指示表中第一个结点指针

  while(i && space[i].data != e)
  {
   i = space[i].cur;
  }

    if(space[i].data == e)
  {
   return i;
  }
  return 0 ;
}

int ListEmpty( SLinkList space )
{
  if( space[ MAXSIZE - 1 ].cur == 0 )   //空表
  {
   return TRUE ;
  }
  return FALSE ;
}

int ListLength( SLinkList space ) //即为元素的个数 
{
  int j = 0 ;
  int i = space[ MAXSIZE - 1 ].cur ;  // i指向第一个元素

  while( i )
  {
   i = space[ i ].cur ; //指向下一个元素的位置
   j ++ ;
  }
  return j ;
}

void PriorElem( SLinkList space , ElemType e , ElemType *pre_e )
{ //操作结果:若e是space的数据元素,且不是第一个,则用pre_e返回它的前驱否则操作失败
  int j ;
  int i = space[ MAXSIZE - 1 ].cur ;  // i = 0 ;

  do
  {
  j = i ;
   i = space[ i ].cur ;
  }while( i && e != space[ i ].data ) ;

  if( i )
  {
   *pre_e = space[ j ].data ;
}
  else
  {
   printf( "Not exist!\n" ) ;
  }
}

void NextElem( SLinkList space , ElemType e , ElemType *next_e )
{ // 操作结果:若e是space的数据元素,且不是最后一个,则用next_e返回它的后继,否则操作失败
  int j ;
  int i = LocateElem_SL( space , e ) ;// 在space中查找第一个值为e的元素的位置

if( i )
  {
   j = space[ i ].cur ;
   if( j )
   {
    *next_e = space[ j ].data ;
   }
  }
  else
  {
   printf( "Not exist!\n" ) ;
  }
}  

void ListInsert( SLinkList space , int i , ElemType e )
{ // 在space中第i个元素之前插入新的数据元素e
  int j = 0 , l = 0 ;
  int k =  MAXSIZE - 1  ; //k指向表头

  if(i <1||i>ListLength( space )+ 1 )//if( i==ListLength( space ) + 1 ) ,Insert into the last!
  {
   printf( "It's Over!\n" ) ;
   exit( 0 ) ;
  }

  j = Malloc_SL( space ) ;
  if( j )
  {   space[ j ].data = e ;
   for( l = 1 ; l < i ; ++ l ) //移动i-1个元素
   {
    k = space[ k ].cur ;     //第一次k = 0 ;
   }
   space[ j ].cur = space[ k ].cur ;
   space[ k ].cur = j ;  }
  else
  {
   printf( "Not exist!\n" ) ;
  }
}

void ListDelete( SLinkList space , int i , ElemType *e )
{ // 删除在L中第i个数据元素e,并返回其值
  int j , k =  MAXSIZE - 1 ; // k指向表头 , not k = space[ MAXSIZE - 1 ]->cur

  if( i < 1 || i > ListLength( space ) )
  {
   printf( "It's Over!\n" ) ;
   exit( 0 ) ;
  }

for( j = 1 ; j < i ; ++ j )
  {
   k = space[ k ].cur ; //第一次k = 0 ;
  }
  j = space[ k ].cur ;
  space[ k ].cur = space[ j ].cur ;
  *e = space[ j ].data ;
  Free_SL( space , j ) ;
}

void Traverses( SLinkList space , void ( *v )( ElemType ) )
{
  int i = space[ MAXSIZE - 1 ].cur ; //i指向第一个元素
//  int i = space[ 1 ].cur ;   //Only for "difference()"!  Or choose "ListTraverse()"!

while( i )
  {
   v( space[ i ].data ) ; 
  i = space[ i ].cur ;
}
  printf( "\n" ) ;
}

void visit( ElemType e )
{
  printf( "%3d" , e ) ;
}

void ListTraverse( SLinkList space , int n , void( *v )( ElemType ) )  
{
  int i = space[ n ].cur ;  //i指向第一个元素

  while( i )
  {
   v( space[ i ].data ) ;

   i = space[ i ].cur ;
  }
  printf( "\n" ) ;
}

void difference( SLinkList space , int *S )  //得到(A-B) .书上坑爹啊!
{  //依次输入集合A和B的元素,在一维数组space中建立表示集合(A-B)U(B-A)的静态链表,S为其头指针,space[0].cur为其头指针
  int r , p , k ;     
  int m , n , i , j ;
  ElemType b ;       

  InitSpace_SL( space ) ;   //初始化备用空间
  ( *S ) = Malloc_SL( space ) ;  //生成S的头结点
  r = ( *S ) ;       //r指向S的当前最后结点

  printf( "Input the element's number of A and B:" ) ;
  scanf("%d %d" , &m , &n );  //输入A和B的元素个数

  printf( "Input the element of A :" ) ;
  for( j = 1 ; j <= m ; ++ j ) 
  {
   i = Malloc_SL( space ) ;   //分配结点
   scanf( "%d", &(space[ i ].data) ) ; //输入A的元素值
   space[ r ].cur = i ;    //插入到表尾
r = i ;
  }
  space[ r ].cur = 0 ;

printf( "Input the element of B :" ) ;
  for( j = 1 ; j <= n ; ++ j)  //依次输入B的元素,若不在当前表中,则插入,否则删除
  { 
   scanf( "%d" , &b ) ;
   p = ( *S ) ;
   k = space[ *S ].cur ;  // k = 指向集合A中第一个结点
  while( k != space[ r ].cur && space[ k ].data != b )
   {
    p = k ;
    k = space[ k ].cur ;
   }

   if (k == space[ r ].cur ) //当前表中不存在该元素,插入在r所指结点之后,且r的位置不变
   {       
    i = Malloc_SL( space ) ;
    space[ i ].data = b ;
    space[ i ].cur = space[ r ].cur ;
   space[ r ].cur = i ;
   }
   else
   { 
    space[ p ].cur = space[ k ].cur ; //p = k ;
   Free_SL( space , k ) ;
    if( r == k )   //若删除的是r所指的结点,则需要修改尾指针
    {
    r = p ;    
    }
  }
  }
}

void main()
{
  int S , j = 1 ;
  SLinkList space;
/*  ElemType e , pre_e ;
 
  InitSpace_SL( space ) ;
  printf( "%d\n" , ListLength( space ) ) ;
  printf( "%d\n" , ListEmpty( space ) ) ;

  for( j = 1 ; j < 6 ; ++ j )
  {
   ListInsert( space , 1 , j ) ;
  }

  ListDelete( space , 1 , &e ) ;
  printf( "%3d\n" , e ) ;
  Traverses( space , visit ) ;

  PriorElem( space ,  1 , &pre_e ) ;
  printf( "%3d\n" , pre_e ) ;
*/
  difference( space , &S ) ; 
  ListTraverse( space , S , visit ) ;
}

//静态链表也可以做成多条序列的(因为一个数组可生成若干静态链表)! 把备用的空间连成一条序列,已用的连成一条序列等!


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值