諸如BASIC和FORTRAN等許多語言都不支持指針。如果需要鏈表而又不能使用指針,這時我們可以使用遊標(cursor)實現法來實現鏈表。
在鏈表的實現中有兩個重要的特點:
1,數據存儲在一組結構體中。每一個結構體包含有數據以及指向下一個結構體的指針。
2,一個新的結構體可以通過調用malloc而從系統全局內存(global memory)得到,並可以通過free而被釋放。
個人理解爲用一個結點數組來模擬實現內存的分配和釋放,在結構體數組中,保留一個表freelist作爲備用單鏈表,用來alloc或free遊標可用空間,該表用0作爲表頭。剛開始時,freelist就是整個結構體數組。
從不同的表頭(Index)出發形成了不同的單鏈表。如果定義一個大小爲10的遊標空間,則其初始化狀態應如下:
slot | Element | Next |
0 | 1 | |
1 | 2 | |
2 | 3 | |
3 | 4 | |
4 | 5 | |
5 | 6 | |
6 | 7 | |
7 | 8 | |
8 | 9 | |
9 |
0 |
Code is here~
.h 中的聲明:
#ifndef CUSORLIST_H_INCLUDED
#define CUSORLIST_H_INCLUDED
typedef int PtrToNode;
typedef PtrToNode List;
typedef PtrToNode Position;
void InitializeCursorSpace(void);
#define ElementType int //set the type of element as Integer
// Functions
List MakeEmpty(List L);
List InitialList();
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 L);
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 Last(const List L);
Position Advance(const Position P);//not implemented yet
ElementType Retrive(const Position P);//not implemented yet
#endif // CUSORLIST_H_INCLUDED
.c文件:
#include "CusorList.h"
#include <stdio.h>
#include <stdlib.h>
struct Node{
ElementType Element;
Position Next;
};
#define SpaceSize 40
struct Node CursorSpace[SpaceSize]; // CursorSpace here is an array of Nodes
void InitializeCursorSpace() {
int i;
for (i = 0; i < SpaceSize - 1; i++) {
CursorSpace[i].Next = i + 1;
}
CursorSpace[SpaceSize - 1].Next = 0; // here "0" means "NULL"
}
static Position CursorAlloc(void) {
// remember that Position(P) here is just a index of array, that's to say, an integer.
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;
}
int IsEmpty(const List L) { // Return true if L is empty
return CursorSpace[L].Next == 0;
}
int IsLast(const Position P, const List L) { // return true if P is the last Position
return CursorSpace[P].Next == 0;
}
Position Find(ElementType X, const List L) { // return Position of X in L; 0 if not found
Position P = CursorSpace[L].Next;
while (P && CursorSpace[P].Element != X)
P = CursorSpace[P].Next;
return P;
}
void Delete(ElementType X, List L) { // Delete the first occurrence of X from L
Position P, tmp;
P = FindPrevious(X, L);
if (!IsLast(P,L)) {
tmp = CursorSpace[P].Next;
CursorSpace[P].Next = CursorSpace[tmp].Next;
CursorFree(tmp);
}
}
Position FindPrevious(ElementType X, const List L) {
Position P = L;
Position tmp = CursorSpace[P].Next;
while (CursorSpace[tmp].Element != X && tmp) {
tmp = CursorSpace[tmp].Next;
P = CursorSpace[P].Next;
}
return P;
}
/*Insert(after legal position)*/
/*Header implementation assumed*/
/*Parameter L is unused in this implementation*/
void Insert(ElementType X, List L, Position P) {
Position tmp;
tmp = CursorAlloc();
if (0 == tmp) {
printf("Out of space!");
} else {
CursorSpace[tmp].Element = X;
CursorSpace[tmp].Next = CursorSpace[P].Next;
CursorSpace[P].Next = tmp;
}
}
void DeleteList(List L) {
Position P = CursorSpace[L].Next;
Position tmp = P;
while (tmp != 0) {
P = CursorSpace[P].Next;
CursorFree(tmp);
if (P == 0) {
break;
}
tmp = P;
}
CursorSpace[L].Next = 0;
}