(一)表的相关定义
大小为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}
Ai−1(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;
}