抽象数据类型——表ADT(一)

(一)表的相关定义

大小为N,形如 A 1 A_{1} A1, A 2 A_{2} A2, A 3 A_{3} A3, ········, A N A_{N} AN。大小为0的表成为空表
对于除空表外的任何表,我们 A i + 1 A_{i+1} Ai+1 后继 * A i A_i Ai(或 A i A_i Ai之后*)并称 A i − 1 A_{i-1} Ai1(i < N )前驱 A i A_i Ai(i > 1)。

(二)表的实现

1.表的数组实现

2.链表

链表由一系列不必在内存中相连的结构组成。每一个结构均含有表元素和指向包含该元素后继元的结构的指针。

最为例子,这里会写一些表的例程。在写例程之前,先声明要编写的函数。

注:本文中的链表中含有头结点

 #ifndef_List_H

 struct Node;
 typedef struct Node *PtrToNode;
 typedef PtrToNode List;
 typedef PtrToNode Position;
 
 List MakeEmpty( List L );
 int IsEmpty( List L ); /*测试一个链表是否是空链表*/
 int IsLast( Position P, List L ); /*测试当前位置是否是链表的末尾的函数*/
 Position Find( ElementType X, List L);/*查找某元素*/
 void Delete( ElementType X,List X);/*删除某元素*/
 Position FindPrevious( ElementType X, List L );/*查找某元素的前驱*/
 void Insert( ElementType X, List L, Position P );/*插入某元素到链表*/
 void DeleteList( List L );
 Position Header( List L );
 Position First( List L );
 Position Advance( Position P );
 ElementType Retrieve( Position P );
 
  #endif
struct Node{
ElementType Element;
Position Next;
}
  • IsEmpty函数
int IsEmpty( List L )
{
	return L->Next == NULL;
}
  • IsLast函数
int IsLast( Position P, List L)
{
	return P->Next == NULL;
}
  • Find函数
Position Find( ElementType X, List L )
{
	Position P;
	P = L->Next;
	while( P != NULL && P->Element != X)
	{
		p = p->Next;
	}
	return P;
}
  • Delete函数
void Delete( ElementType X, List L )
{
	Position P,TmpCell;
	P = FindPrevious( X, L );
	if( !IsLast( P, L ) )
	{
		TemCell = P->Next;
		P->Next = TemCell->Next;
		free(TemCell);
	}
}
  • FindPrevious函数
Position FindPrevious( ElementType X, List L )
{
	Position P;
	P = L;
	while( P->Next != NULL && P->Next->Element != X )
		P = P->Next;
	return P;
}
  • Insert函数
void Insert( ElementType X, List L, Position P )
{
	Position TmpCell;
	TmpCell = malloc( sizeof( struct Node ) );
	if(TmpCell == NULL )
		 FatalError( " out of space!!! " );
	 TmpCell->Element = X;
	 TmpCell->Next = P->Next;
	 P->Next = TmpCell;
}

3.链表的游标实现

在一些编程语言中(如BASIC,FORTRAN)不支持指针。如果要实现链表而又不能使用指针,那么就必须使用另外的实现方法。我们称之为游标实现法。

在链表的指针实现中有两个重要特点

  • 数据存储在一组结构体中。每一个结构体包含有数据以及指向下一个结构体的指针。
  • 一个新的结构体可以通过调用 malloc 而从系统全局内存得到,并可以通过调用 free 函数释放。

游标法必须能够模仿实现这两条特性。

  • 满足条件一的逻辑方法是要有一个全局的结构体数组。对于该数组中的任何单元,其数组下标可以用来代表一个地址,下面给出链表游标实现的声明。
 #ifndef_Cursor_H

 typedef int PtrToNode;
 typedef PtrToNode List;
 typedef PtrToNode Position;
 
 void InitializeCursorSpace( void );
 
 List MakeEmpty( List L );
 int IsEmpty( const List L ); /*测试一个链表是否是空链表*/
 int IsLast(const Position P, const List L ); /*测试当前位置是否是链表的末尾的函数*/
 Position Find( ElementType X, const List L);/*查找某元素*/
 void Delete( ElementType X, List X);/*删除某元素*/
 Position FindPrevious( ElementType X, const List L );/*查找某元素的前驱*/
 void Insert( ElementType X, List L, Position P );/*插入某元素到链表*/
 void DeleteList( List L );
 Position Header( const List L );
 Position First( const List L );
 Position Advance( Position P );
 ElementType Retrieve( const Position P );
 
  #endif
  
struct Node{
ElementType Element;
Position Next;
};
struct Node CursorSpace[ SpaceSize ];
  • 现在来模拟条件二,让CursorSpace数组中的单元行malloc和free函数的职能。为此,我们将保留一个表(即freelist),这个表由不在任何表中的单元构成。该表用单元0作为表头。起初是配置图如下:
    | Slot | Element | Next |
    |:------------| --------------? :--------?
    | 0 | | 1 |
    | 1 | | 2 |
    | 2 | | 3 |
    | 3 | | 4 |
    | 4 | | 5 |
    | 5 | | 6 |
    | 6 | | 7 |
    | 7 | | 8 |
    | 8 | | 9 |
    | 9 | | 10 |
    | 10 | | 0 |

CursorSpace数组中的初始化只需用一个简单for循环即可,这里不予写出。为了执行 malloc 功能,将(在表头后面的)的第一个元素从freelist中删除。为了执行 free 函数的功能,我们将该单元放在freelist 的前端。下面给出 malloc 和 free 的例程

注:Next == 0,等价于Next == NULL

static Position CursorAlloc( void )
{
	Position P;
	P = CursorSpace[ 0 ].next;
	CursorSpace[ 0 ].Next = CursorSpace[ P ].Next;
	return P;
}

static void CursorFree( Position P )
{
	CursorSpace[ P ].Next = CursorSpace[ 0 ].Next;
	CursorSpace[ 0 ].Next = P;
}

实现了malloc和free函数之后,我们可以开始编写之前声明的函数了。

  • IsEmpty函数
int IsEmpty( List L )
{
	return CursorSpace[ L ].Next == 0;
}
  • IsLast函数
int IsLast( Position P, List L)
{
	return CursorSpace[ P ].Next == 0;
}
  • Find函数
Position Find( ElementType X, List L )
{
	Position P;
	P = CursorSpace[ L ].Next;
	while( P && CursorSpace[ P ].Element != X)
	{
		p = CursorSpace[ P ].Next;
	}
	return P;
}
  • Delete函数
void Delete( ElementType X, List L )
{
	Position P,TmpCell;
	P = FindPrevious( X, L );
	if( !IsLast( P, L ) )
	{
		TemCell = CursorSpace[ P ].Next;
		CursorSpace[ P ].Next = CursorSpace[ TmpCell ].Next;
		CursorFree(TemCell);
	}
}
  • FindPrevious函数
Position FindPrevious( ElementType X, List L )
{
	Position P;
	P = L;
	while( P && CursorSpace[ P ].Next.Element != X )
		P = CursorSpace[ P ].Next;
	return P;
}
  • Insert函数
void Insert( ElementType X, List L, Position P )
{
	Position TmpCell;
	TmpCell = CursorAlloc();
	if(TmpCell == 0 )
		 FatalError( " out of space!!! " );
	 CursorSpace[ TmpCell ].Element = X;
	 CursorSpace[ TmpCell ].Next = CursorSpace[ P ].Next;
	 CursorSpace[ P ].Next = TmpCell;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值