前言:
最开始读M.A.W这本书时,已经简单了解了一些基本数据结构,于是刚开始读时总会有点囫囵吞枣的感觉,并没有认真研究链表的游标实现过程,
简单看了下书中代码就过了,现在从新翻阅,反而是让自己收获颇丰。
————————————————分割线——————————————————————
正文:
为什么我们会用到链表的游标实现,链表的核心用到了指针这样的概念,而许多语言是没有指针的,这个时候想要实现链表我们就要想其他办法了
那么我们应该从何开始呢?
回顾链表的指针实现的两个重要的特点:
1:数据储存在一组结构体中,每一个结构体包含有数据域以及指向下一个结构体的指针。
2:一个新的结构体可以通过调用malloc而从系统全局内存(global memory)得到,并可以调用free而被释放。
游标法必须能够模仿实现这两种特性,需要满足条件1的逻辑方法是要有一个全局的结构体数组。对于该数组中的任何单元,其数组线标用来代表一个地址。
初始配置如下:
一个初始化的CursorSpace
| 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 |
为了模拟特性2,让CursorSpace数组中的单元代行malloc和free的职能,
为此我们保留一个表(即freelist),该表将用单元0作为表头。
下面给出链表游标实现的声明:
Cursor.h:
#ifndef CURSOR_SPACE_H
#define CURSOR_SPACE_H
typedef char ElementType;
typedef int PtrToNode;
typedef PtrToNode Position;
typedef PtrToNode List;
void InitializeCursorSpace();
static Position CursorAlloc();
static void CursorFree(Position P);
List MakeEmpty(List L);
int IsLast(Position P, List L);
int IsEmpty(List L);
Position FindPrevious(List L, ElementType x);
Position Find(List L, ElementType x);
void Delete(List L, ElementType x);
void Insert(List L, ElementType x, Position P);
void InsertToTail(List L, ElementType x);
void InsertToHead(List L, ElementType x);
void PrintList(List L);
void DeleteList(List L);
#endif
需要实现整个例程主要是CursorAlloc()和CursorFree()这两个函数起关键作用:
/*每次CursorAlloc都从CursorSpace的单元0下一个开始Alloc8*/static Position CursorAlloc()
{
Position P;
P = CursorSpace[0].Next;
CursorSpace[0].Next = CursorSpace[P].Next;
return P;
}
/*当我们需要free时将把free的单元放在单元0的下一位*/
static void CursorFree(Position P)
{
CursorSpace[P].Next = CursorSpace[0].Next;
CursorSpace[0].Next = P;
}
下面给出声明中的所有完整例程实现代码,除CursorAlloc()和CursorFree()其余函数实现方法和单链表思想一致;
CursorSpace.c:
#include"Cursor.h"
#include<stdio.h>
#define SpaceSize 20
struct Node
{
ElementType Element;
Position Next;
};
struct Node CursorSpace[SpaceSize + 1];//定义一个全局CursorSpace空间
void InitializeCursorSpace()
{
int Slot;
for(Slot = 0; Slot < SpaceSize + 1; Slot++)
{
if(Slot != SpaceSize)
CursorSpace[Slot].Next = Slot + 1;
else
CursorSpace[Slot].Next = 0;
}
}
static Position CursorAlloc()
{
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;
}
List MakeEmpty(List L)
{
if(L != 0)
CursorSpace[L].Next = 0;
return L;
}
int IsLast(Position P, List L)
{
return CursorSpace[P].Next == 0;
}
int IsEmpty(List L)
{
return CursorSpace[L].Next == 0;
}
Position FindPrevious(List L, ElementType X)
{
Position P;
P = L;
while(CursorSpace[P].Next && CursorSpace[CursorSpace[P].Next].Element != X)
P = CursorSpace[P].Next;
return P;
}
Position Find(List L, ElementType X)
{
Position P;
P = CursorSpace[L].Next;
while(P && CursorSpace[P].Element != X)
P = CursorSpace[P].Next;
return P;
}
void Delete(List L, ElementType X)
{
Position Pre, Tmp;
Pre = FindPrevious(L, X);
if(Pre == 0)
printf("Sorry! Can't find element");
else
{
Tmp = CursorSpace[Pre].Next;
CursorSpace[Pre].Next = CursorSpace[Tmp].Next;
CursorFree(Tmp);
}
}
void Insert(List L, ElementType X, Position P)
{
Position NewCell;
NewCell = CursorAlloc();
if(NewCell == 0)
printf("No space for allocation!!");
else
{
CursorSpace[NewCell].Element = X;
CursorSpace[NewCell].Next = CursorSpace[P].Next;
CursorSpace[P].Next = NewCell;
}
}
void InsertToTail(List L, ElementType X)
{
Position Last;
Last = L;
/*遍历链表寻找最后一个结点*/
while(CursorSpace[Last].Next != 0)
Last = CursorSpace[Last].Next;
Insert(L, X, Last);
}
void InsertToHead(List L, ElementType X)
{
Insert(L, X, L);
}
void DeleteList(List L)
{
Position P, Tmp;
P = CursorSpace[L].Next;
CursorSpace[L].Next = 0;
while(P != 0)
{
Tmp = CursorSpace[P].Next;
CursorFree(P);
P = Tmp;
}
}
void PrintList(List L)
{
Position P;
P = CursorSpace[L].Next;
while(CursorSpace[P].Next != 0)
{
printf("%c-", CursorSpace[P].Element);
P = CursorSpace[P].Next;
}
printf("%c\n", CursorSpace[P].Element);
}
最后给出自己的一组测试实例
Test.c:
#include"Cursor.h"
#include<stdio.h>
int main()
{
InitializeCursorSpace();
ElementType Elem, De, PreElem, Ins;
Position Tmp;
List L;
L = CursorAlloc();
if(L == 0)
printf("No space for Allocation");
L = MakeEmpty(L);
printf("请输入链表元素以'#'结束:");
while((Elem = getchar()) != '#')
{
InsertToTail(L, Elem);
}
getchar();
PrintList(L);
printf("请输入你要删除的元素:");
scanf("%c", &De);
getchar();
Delete(L, De);
PrintList(L);
printf("请输入你将要插在哪个元素后:");
scanf("%c", &PreElem);
getchar();
Tmp = Find(L, PreElem);
printf("请输入你要插入的元素:");
scanf("%c", &Ins);
Insert(L, Ins, Tmp);
PrintList(L); /*最后删除整个表以及表头*/ DeleteList(L); CursorFree(L);
return 0;
}
