深入理解抽象数据类型;
ADT是一些操作的集合,是数学的抽象,在ADT的定义中根本没涉及如何实现操作的集合,这个可以看作是模块化设计的补充。这些操作在程序只编写一次,而程序中任何其他部分需要在该ADT上运行其中的一种操作时可以通过调用适当的函数来进行,若需要改变操作细节,只需要修改运行这些ADT操作的例程就可以。
对所有的表操作都可以通过使用数组来实现,虽然数组是动态指定的,但是还是需要对标的最大值进行估计,并且插入和删除操作需要二次时间,所以简单数组一般不用来实现这种结构。而为了减少顺序列表的插入和删除带来的时间浪费,我们需要可以不连续储存的形式,这符合链式列表的想法。
然而有顺序表转换为链式列表会遇到一下三个问题:
1.不存在从表的前面插入元素的方法;
2.从最前面删除一个元素是一个特殊情况,因为它改变了表的起始位置,这将会造成表的丢失;
3.虽然上述指针移动很简单,删除一个元素时,但是,这要求我们必须记住删除元素前面的表格元素。
然而当我们在开头再加上一个空指针时就很容易的解决以上三个问题;
接下来设计一个表,按照C语言的约定,作为list表和Position以及函数的原型都列在所谓的头文件中,具体的Node节点则在.C文件中:
typedef int ElementType
#ifdef _List_H
struct Node;//声明节点为结构体类型
typedef struct Node *PtrToNode;
typedef PrtToNode List;
typedef PtrToNode Position;
List MakeEmpty(List L);//置空函数
int IsEmpty(List L);//是否为空
int IsLast(List L);//是否是到最后了
void Delete(ElementType X,List L);//删除指定位置的元素
Position Find(ElementType X,List L);//返回X在表中的位置
Position FindPrevious(ElementType X,List L);//返回X元素的前驱的位置
void Insert(ElementTypeX, List L,Positon P);//在P处后面插入元素X插入元素
void DEeleteList(List L);//删除整个表
Position Header(List L);//表头的位置
Position First(List L);//表中第一个元素的位置
Position Advance(Position P);//移动到位置P
ElementType Retrieve(Position P);//P处的元素值
#endif
建立Node节点信息的单元,包含一个数据体和一个指针
struct Node
{
ElementType Element;
Position Next;
};
实现第一个方法:将列表置空:
List
MakeEmpty( List L )
{
if( L != NULL )
DeleteList( L );
L = malloc( sizeof( struct Node ) );
if( L == NULL )
FatalError( "Out of memory!" );
L->Next = NULL;
return L;
}
检验是否为空的函数实现如下:
int IsEmpty( List L )
{
return L->Next == NULL;
}
检验数据是不是最后一个位置:
int IsLast( Position P, List L )
{
return P->Next == NULL;
}
查找位置:
Position
Find( ElementType X, List L )
{
Position P;
/* 1*/ P = L->Next;
/* 2*/ while( P != NULL && P->Element != X )
/* 3*/ P = P->Next;
/* 4*/ return P;
}
若删除列表中的元素,则:
void
Delete( ElementType X, List L )
{
Position P, TmpCell;
P = FindPrevious( X, L );
if( !IsLast( P, L ) ) /* Assumption of header use */
{ /* X is found; delete it */
TmpCell = P->Next;
P->Next = TmpCell->Next; /* Bypass deleted cell */
free( TmpCell );
}
}
寻找某个元素的前一个位置:
Position
FindPrevious( ElementType X, List L )
{
Position P;
/* 1*/ P = L;
/* 2*/ while( P->Next != NULL && P->Next->Element != X )
/* 3*/ P = P->Next;
/* 4*/ return P;
}
在线性表中插入某个数据:
void
Insert( ElementType X, List L, Position P )
{
Position TmpCell;
/* 1*/ TmpCell = malloc( sizeof( struct Node ) );
/* 2*/ if( TmpCell == NULL )
/* 3*/ FatalError( "Out of space!!!" );
/* 4*/ TmpCell->Element = X;
/* 5*/ TmpCell->Next = P->Next;
/* 6*/ P->Next = TmpCell;
}
删除整个列表:
void
DeleteList( List L )
{
Position P;
/* 1*/ P = L->Next; /* Header assumed */
/* 2*/ L->Next = NULL;
/* 3*/ while( P != NULL )
{
/* 4*/ free( P );
/* 5*/ P = P->Next;
P=Tmp;
}
}
返回表的位置和元素信息等:包括表的Header,表的第一个元素的位置,以及元素的类型等
Position
Header( List L )
{
return L;
}
Position
First( List L )
{
return L->Next;
}
Position
Advance( Position P )
{
return P->Next;
}
ElementType
Retrieve( Position P )
{
return P->Element;
}
测试文件如下:
#include <stdio.h>
#include "list.h"
void
PrintList( const List L )
{
Position P = Header( L );
if( IsEmpty( L ) )
printf( "Empty list\n" );
else
{
do
{
P = Advance( P );
printf( "%d ", Retrieve( P ) );
} while( !IsLast( P, L ) );
printf( "\n" );
}
}
main( )
{
List L;
Position P;
int i;
L = MakeEmpty( NULL );
P = Header( L );
PrintList( L );
for( i = 0; i < 10; i++ )
{
Insert( i, L, P );
PrintList( L );
P = Advance( P );
}
for( i = 0; i < 10; i+= 2 )
Delete( i, L );
for( i = 0; i < 10; i++ )
if( ( i % 2 == 0 ) == ( Find( i, L ) != NULL ) )
printf( "Find fails\n" );
printf( "Finished deletions\n" );
PrintList( L );
DeleteList( L );
return 0;
}