表是一种常用的数据结构,可以采用数组实现和链表实现。若采用数组实现,需要对表的大小进行事先估计,通常需要估计的大一些,从而会浪费一些空间,这是严重的局限,特别是在存在许多未知大小的表的情况下。
数组实现使得PrintList和FInd操作以线性时间执行,而FindKth(查找第K个元素)则花费常数时间。然而,插入和删除的花费则是昂贵的。例如,在位置0插入元素,首先需要将整个数组后移一个位置一空出空间来,而删除第一个元素则需要将表中的所有元素向前移动一个位置,因此这两种情形的最坏运行时间都为O(N)。因为数组实现插入和删除的运行时间如此的慢,并且还需要事先估计表的大小,所以表的实现一般都采用链表,包括单向链表,双向链表,循环链表等。
为了避免插入和删除的线性开销,需要允许表可以不连续存储,否则表的部分或全部需要整体移动。图1-1给出了链表的一般想法。
头文件:list.h
#ifndef _List_H
#define _List_H
typedef int ElementType;
struct Node;
typedef struct Node *PtrToNode;
typedef PtrToNode List;
typedef PtrToNode Position;
List MakeEmpty( List L ); //如果L不为空,则将L的空间回收,然后重新分配空间,初始化。
int IsEmpty( List L );
int IsLast( Position P, List L ); //判断P是否是最后一个元素
int Length( List L ); //返回链表的长度
Position Find( ElementType X, List L );
void Delete( ElementType X, List L ); //删除X元素的节点
Position FindPrevious( ElementType X, List L ); //寻找X元素的前驱,如果X不存在,返回最后一个元素
void Insert( ElementType X, List L, Position P ); //在位置P之后插入元素X
void DeleteList( List L ); //删除整个链表
Position Header( List L );
Position Advance( Position P ); //功能就是 P = P->Next;
ElementType Retrieve( Position P ); //功能就是 X = P->Element;
void PrintList( List L );
List Intersect( const List A, const List B); //两个链表的交集
List Union( const List A, const List B); //两个链表的并集
List Reverse( List L ); //转置链表,新开辟N个元素空间
List Reverse_constVolume( List L ); //转置链表,但只耗费常量个元素空间
#endif
链表实现文件:list:
#include "list.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
struct Node
{
ElementType Element;
Position Next;
};
List MakeEmpty(List L)
{
if (L != NULL)
DeleteList(L);
L = (List)malloc(sizeof(struct Node));
if (L == NULL)
cout << "Out of memory!" << endl;
L->Next = NULL;
return L;
}
int IsEmpty(List L)
{
return L->Next == NULL;
}
int IsLast( Position p, List L )
{
return p->Next == NULL;
}
int Length( List L )
{
Position P = L->Next;
int len = 0;
while (P != NULL)
{
++len;
P = P->Next;
}
return len;
}
Position Find(ElementType X, List L)
{
Position p;
p = L->Next;
while (p != NULL && p->Element != X)
p = p->Next;
return p;
}
void Delete( ElementType X, List L )
{
Position p, TmpCell;
p = FindPrevious(X, L); //找到X的前驱,如果X不存在,那么其前驱则是表中最后一个元素
if (!IsLast(p, L))
{
TmpCell = p->Next;
p->Next = TmpCell->Next;
free(TmpCell);
}
}
Position FindPrevious( ElementType X, List L )
{
Position p;
p = L;
while (p->Next != NULL && p->Next->Element != X)
p = p->Next;
return p;
}
void Insert( ElementType X, List L, Position P )
{
Position TmpCell;
TmpCell = (Position)malloc(sizeof(struct Node));
if (TmpCell == NULL)
cout << "Out of space!!!" << endl;
TmpCell->Element = X;
TmpCell->Next = P->Next;
P->Next = TmpCell;
}
void InsertNode(PtrToNode node, List L, Position P)
{
node->Next = P->Next;
P->Next = node;
}
void DeleteList(List L)
{
Position P, Tmp;
P = L->Next;
L->Next = NULL;
while (P != NULL)
{
Tmp = P->Next;
free(P);
P = Tmp;
}
}
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;
}
void PrintList( List L )
{
if (!IsEmpty(L))
{
Position Tmp = L->Next;
while(Tmp != NULL)
{
printf("%5d", Retrieve(Tmp));
Tmp = Advance(Tmp);
}
printf("\n");
}
else
printf("The List is empty!!\n");
}
void Swap( Position BeforeP, List L )
{
if (IsLast(BeforeP->Next, L))
{
printf("Cannot swap!\n");
return;
}
Position P, AfterP;
P = BeforeP->Next;
AfterP = P->Next;
BeforeP->Next = AfterP;
P->Next = AfterP->Next;
AfterP->Next = P;
}
List Intersect( const List A, const List B)
{
List result = NULL;
result = MakeEmpty(result);
Position PA = A->Next;
Position PB = B->Next;
Position PR = Header(result);
while (PA != NULL && PB != NULL)
{
if (PA->Element < PB->Element)
PA = PA->Next;
else if (PA->Element > PB->Element)
PB = PB->Next;
else
{
Insert(PA->Element, result, PR);
PA = PA->Next;
PB = PB->Next;
PR = PR->Next;
}
}
return result;
}
List Union( const List A, const List B)
{
List result = NULL;
result = MakeEmpty(result);
Position PA = A->Next;
Position PB = B->Next;
Position PR = Header(result);
while (PA != NULL && PB != NULL)
{
if (PA->Element < PB->Element)
{
Insert(PA->Element, result, PR);
PA = PA->Next;
PR = PR->Next;
}
else if (PA->Element > PB->Element)
{
Insert(PB->Element, result, PR);
PB = PB->Next;
PR = PR->Next;
}
else
{
Insert(PA->Element, result, PR);
PA = PA->Next;
PB = PB->Next;
PR = PR->Next;
}
}
if (PA == NULL)
{
PA = PB;
}
while (PA != NULL)
{
Insert(PA->Element, result, PR);
PA = PA->Next;
PR = PR->Next;
}
return result;
}
List Reverse( List L )
{
int N = Length(L);
ElementType *array = (ElementType *)malloc(sizeof(ElementType) * N);
Position P = L->Next;
int i = 0;
while (P != NULL)
{
array[i] = P->Element;
++i;
P = P->Next;
}
P = L->Next;
for (i = N - 1; i >= 0; --i)
{
P->Element = array[i];
P = P->Next;
}
free(array);
return L;
}
List Reverse_constVolume( List L )
{
Position Tmp, P = L->Next;
while (P->Next != NULL)
{
Tmp = P->Next;
P->Next = Tmp->Next;
Tmp->Next = L->Next;
L->Next = Tmp;
}
return L;
}