实现思路:链表的各个节点预先存放在一个节点数组中 ,每个节点的"next"是一个整数,代表下一个节点在节点数组中的位置。
优缺点:由于不需要动态内存分配置,此链表比文章(5)中的链表实现快,但是需要预先估计链表的大小,防止链表太大时没有节点可分配。
额外操作:在使用游标链表前,需要一个循环把节点数组“串连”起来。
关键问题:
A:怎么样表示一个节点?
Q:以数组的下标表示一个节点
假如数组下标为n,则CursorSpace[n]表示此实际节点
A:怎么样表示next指针?
Q:以数组下标代替指针。
假如n表示节点,则CursorSpace[n].next表示下一个指向的节点(next就是一个数组下标)
实现关键有几点:
1。需要一个全局的节点数组CursorSpace[](不是动态分配),节点定义如:
struct Cur_Node
{
Cur_Element e;
Cur_Position next;
};
Cur_Position 定义为整数,代表下一个节点的数组的下标
2。需要实现一个CursorAlloc()分配游标,定义一个CursorFree回收游标。
3。链表使用前需要初始化节点数组,以开成一个“分配链”
节点数组初始化如图1:
4。解决了用下标“模拟”next指针这个问题后,其它的实现就和一般链表的实现一样,可以看到,cur_list.h和”文章(5)“中的list.h几乎一模一样,只是为了区别每个函数加了cur_前缀
图1
调用一次CursorAlloc实际上等于分配第0个节点指向的下一个节点,假如前三个可分配节点为:n0 ,nx,ny,那么本次分配表示如下:
n0.next=nx.next
return x
如果x=0,说明已经没有节点可分配,否则CursorSpace[x]就是分配到的节点,当然CursorSpace应该是被封装起来的,在头文件中看不到。
从图1中的节点调用一次CursorAlloc节点1被分配分去,如下图所示:
ADT cur_list.h:
/**********************************
*author:Felix
*last update:Sun Jan 6 12:33:03 EST 2008
*description:
*
*
*
*/
#ifndef ___LIST___
#define ___LIST___
#include<stdio.h>
#include<stdlib.h>
/*define MAX_CURSOR_SIZE to decide the cursor size*/
#ifndef ___MAX_CURSOR_SIZE___
#define MAX_CURSOR_SIZE 1024
#define __MAX_CURSOR_SIZE___
#endif
struct Cur_Node;
typedef int Cur_PtrNode;
typedef Cur_PtrNode Cur_List;
typedef Cur_PtrNode Cur_Position;
typedef int Cur_Element;
void cur_InitializeCursor();
Cur_List cur_MakeEmpty();
int cur_IsEmpty(Cur_List l);
int cur_IsLast(Cur_Position p);
Cur_Position cur_Find(Cur_Element e,Cur_List l);
void cur_Delete(Cur_Element e,Cur_List l);
Cur_Position cur_FindPrevious(Cur_Element e,Cur_List l);
Cur_Position cur_Insert(Cur_Element e,Cur_List l,Cur_Position p);
void cur_DeleteList(Cur_List l);
Cur_Position cur_Header(Cur_List l);
Cur_Position cur_First(Cur_List l);
Cur_Position cur_Advance(Cur_Position p);
Cur_Element cur_Retrieve(Cur_Position p);
void cur_Update(Cur_Position p,Cur_Element e);
#endif
实现文件 cur_list.c
/**********************************
*author:Felix
*last update:Tue Jan 1 04:33:03 EST 2008
*description:
*
*
*
*/
#include "cur_list.h"
struct Cur_Node
{
Cur_Element e;
Cur_Position next;
};
static struct Cur_Node CursorSpace[MAX_CURSOR_SIZE];
int CursorInitFlag=0;/*to decide whether it's been initialized*/
static Cur_Position CursorAlloc();
static void CursorFree(Cur_Position p);
/*assume that the first position is dump cursor(unused) that just for a sign*/
Cur_Position CursorAlloc()
{
Cur_Position p;
p=CursorSpace[0].next;
CursorSpace[0].next=CursorSpace[p].next;
return p;
}
void CursorFree(Cur_Position p)
{
CursorSpace[p].next=CursorSpace[0].next;
CursorSpace[0].next=p;
}
void cur_InitializeCursor()
{
int i=0;
if(CursorInitFlag==0)/*to decide whether it's been initialized*/
{
while(i<MAX_CURSOR_SIZE-1)
CursorSpace[i].next=++i;
CursorSpace[i].next=0;
CursorInitFlag=1;
}
}
Cur_List cur_MakeEmpty() {
Cur_Position p;
p= CursorAlloc();
CursorSpace[p].next=0;
return p;
}
int cur_IsEmpty(Cur_List l)
{
return 0==CursorSpace[l].next;
}
int cur_IsLast(Cur_Position p)
{
return 0==CursorSpace[p].next;
}
Cur_Position cur_Find(Cur_Element e,Cur_List l)
{
Cur_Position p=cur_First(l);
while(p&&CursorSpace[p].e!=e)p=cur_Advance(p);
return p;
}
void cur_Delete(Cur_Element e,Cur_List l)
{
Cur_Position p=cur_FindPrevious(e,l);
Cur_Position tmp=cur_Advance(p);
CursorSpace[p].next=cur_Advance(tmp);
CursorFree(tmp);
}
Cur_Position cur_FindPrevious(Cur_Element e,Cur_List l)
{
Cur_Position p=l;
while(CursorSpace[p].next&&CursorSpace[CursorSpace[p].next].e!=e)p=cur_Advance(p);
return CursorSpace[p].next?p:0;
}
Cur_Position cur_Insert(Cur_Element e,Cur_List l,Cur_Position p)
{
Cur_Position tmp=(Cur_Position)CursorAlloc();
if (!tmp) return 0;
CursorSpace[tmp].e=e;
CursorSpace[tmp].next=CursorSpace[p].next;
CursorSpace[p].next=tmp;
return tmp;
}
void cur_DeleteList(Cur_List l)
{
CursorSpace[cur_Header(l)].next=0;
}
Cur_Position cur_Header(Cur_List l)
{
return l;
}
Cur_Position cur_First(Cur_List l)
{
return CursorSpace[l].next;
}
Cur_Position cur_Advance(Cur_Position p)
{
return p?CursorSpace[p].next:0;
}
Cur_Element cur_Retrieve(Cur_Position p)
{
return CursorSpace[p].e;
}
void cur_Update(Cur_Position p,Cur_Element e)
{
CursorSpace[p].e=e;
}
/*****************
测试部分:
*************/
/*menu_c.h*/
/*///
*author:Felix
*create date:Tue Jan 1 05:13:11 EST 2008
*last update:Tue Jan 1 05:13:11 EST 2008
*description:
*
*
*/
#include <stdio.h>
#ifndef __MENU____
#define __MENU____
#define SELECT() ((___sel=___select())!='0')
#define SELECTION ___sel
char ___sel;
char ___select();
/*
define the menu:
*/
#endif
/*menu_c.c*/
/*///
*author:Felix
*create date:Tue Jan 1 05:13:11 EST 2008
*last update:Tue Jan 1 05:13:11 EST 2008
*description:
*
*
*/
#include "menu_c.h"
char *___menu[]={
"1.Print list.h",
"2.Initialize the list with random integer.",
"3.Insert a number to the list.",
"4.Delete a number from the list.",
"5.Update a number in the list.",
"6.Delete the whole list.",
"7.Print the list",
"0.EXIT",
NULL
};
void ___showMenu()
{
printf("please select:/n");
char **p=___menu;
while(*p)printf("%s/n",*p++);
printf(":>");
}
char ___select()
{
char c;
___showMenu();
while((c=getchar())=='/n');
return c;
}
/*testList.c*/
/*///
*author:Felix
*create date:Tue Jan 1 05:13:11 EST 2008
*last update:Tue Jan 1 05:13:11 EST 2008
*description:
*
*
*//
#include "menu_c.h"
#include<stdio.h>
#include<stdlib.h>
#include<cur_list.h>
#define RAN_COUNT 30
#define DEF_MAX 9999
int main()
{
Cur_List l;
Cur_Position p;
int n,n2;
int count;
cur_InitializeCursor();
l=cur_MakeEmpty();
while(SELECT())
{
switch (SELECTION)
{
/*Print list.h*/
case '1':
system("less ../cur_list.h");
break;
/*Initialize the list with random integer.*/
case '2':
count=RAN_COUNT;
while(count-->0)cur_Insert(random_f(DEF_MAX),l,cur_Header(l));
break;
/*Insert a number to the list.*/
case '3':
printf("number to insert:>");
if(scanf("%d",&n)>0)
cur_Insert(n,l,cur_Header(l));
else printf("illegal input");
break;
/*Delete a number from the list.*/
case '4':
printf("number to delete:>");
if(scanf("%d",&n)>0)
{
if (cur_Find(n,l))cur_Delete(n,l);
else printf("no match found/n");
}else printf("illegal input/n ");
break;
/*Update a number in the list.*/
case '5':
printf("integer to update:>");
if(scanf("%d",&n)>0)
{
if (p=cur_Find(n,l))
{
printf("update with:>");
if(scanf("%d",&n2)>0)cur_Update(p,n2);
else printf("illegal input");
}
else printf("no match found/n");
}else printf("illegal input/n ");
break;
/*Delete the whole list.*/
case '6':
cur_DeleteList(l);
break;
/*print the list*/
case '7':
p=cur_First(l);
while(p)
{
printf("%d ",cur_Retrieve(p));
p=cur_Advance(p);
}
default:break;
}
}
return 0;
}
优缺点:由于不需要动态内存分配置,此链表比文章(5)中的链表实现快,但是需要预先估计链表的大小,防止链表太大时没有节点可分配。
额外操作:在使用游标链表前,需要一个循环把节点数组“串连”起来。
关键问题:
A:怎么样表示一个节点?
Q:以数组的下标表示一个节点
假如数组下标为n,则CursorSpace[n]表示此实际节点
A:怎么样表示next指针?
Q:以数组下标代替指针。
假如n表示节点,则CursorSpace[n].next表示下一个指向的节点(next就是一个数组下标)
实现关键有几点:
1。需要一个全局的节点数组CursorSpace[](不是动态分配),节点定义如:
struct Cur_Node
{
Cur_Element e;
Cur_Position next;
};
Cur_Position 定义为整数,代表下一个节点的数组的下标
2。需要实现一个CursorAlloc()分配游标,定义一个CursorFree回收游标。
3。链表使用前需要初始化节点数组,以开成一个“分配链”
节点数组初始化如图1:

4。解决了用下标“模拟”next指针这个问题后,其它的实现就和一般链表的实现一样,可以看到,cur_list.h和”文章(5)“中的list.h几乎一模一样,只是为了区别每个函数加了cur_前缀
图1
调用一次CursorAlloc实际上等于分配第0个节点指向的下一个节点,假如前三个可分配节点为:n0 ,nx,ny,那么本次分配表示如下:
n0.next=nx.next
return x
如果x=0,说明已经没有节点可分配,否则CursorSpace[x]就是分配到的节点,当然CursorSpace应该是被封装起来的,在头文件中看不到。
从图1中的节点调用一次CursorAlloc节点1被分配分去,如下图所示:

ADT cur_list.h:
/**********************************
*author:Felix
*last update:Sun Jan 6 12:33:03 EST 2008
*description:
*
*
*
*/
#ifndef ___LIST___
#define ___LIST___
#include<stdio.h>
#include<stdlib.h>
/*define MAX_CURSOR_SIZE to decide the cursor size*/
#ifndef ___MAX_CURSOR_SIZE___
#define MAX_CURSOR_SIZE 1024
#define __MAX_CURSOR_SIZE___
#endif
struct Cur_Node;
typedef int Cur_PtrNode;
typedef Cur_PtrNode Cur_List;
typedef Cur_PtrNode Cur_Position;
typedef int Cur_Element;
void cur_InitializeCursor();
Cur_List cur_MakeEmpty();
int cur_IsEmpty(Cur_List l);
int cur_IsLast(Cur_Position p);
Cur_Position cur_Find(Cur_Element e,Cur_List l);
void cur_Delete(Cur_Element e,Cur_List l);
Cur_Position cur_FindPrevious(Cur_Element e,Cur_List l);
Cur_Position cur_Insert(Cur_Element e,Cur_List l,Cur_Position p);
void cur_DeleteList(Cur_List l);
Cur_Position cur_Header(Cur_List l);
Cur_Position cur_First(Cur_List l);
Cur_Position cur_Advance(Cur_Position p);
Cur_Element cur_Retrieve(Cur_Position p);
void cur_Update(Cur_Position p,Cur_Element e);
#endif
实现文件 cur_list.c
/**********************************
*author:Felix
*last update:Tue Jan 1 04:33:03 EST 2008
*description:
*
*
*
*/
#include "cur_list.h"
struct Cur_Node
{
Cur_Element e;
Cur_Position next;
};
static struct Cur_Node CursorSpace[MAX_CURSOR_SIZE];
int CursorInitFlag=0;/*to decide whether it's been initialized*/
static Cur_Position CursorAlloc();
static void CursorFree(Cur_Position p);
/*assume that the first position is dump cursor(unused) that just for a sign*/
Cur_Position CursorAlloc()
{
Cur_Position p;
p=CursorSpace[0].next;
CursorSpace[0].next=CursorSpace[p].next;
return p;
}
void CursorFree(Cur_Position p)
{
CursorSpace[p].next=CursorSpace[0].next;
CursorSpace[0].next=p;
}
void cur_InitializeCursor()
{
int i=0;
if(CursorInitFlag==0)/*to decide whether it's been initialized*/
{
while(i<MAX_CURSOR_SIZE-1)
CursorSpace[i].next=++i;
CursorSpace[i].next=0;
CursorInitFlag=1;
}
}
Cur_List cur_MakeEmpty() {
Cur_Position p;
p= CursorAlloc();
CursorSpace[p].next=0;
return p;
}
int cur_IsEmpty(Cur_List l)
{
return 0==CursorSpace[l].next;
}
int cur_IsLast(Cur_Position p)
{
return 0==CursorSpace[p].next;
}
Cur_Position cur_Find(Cur_Element e,Cur_List l)
{
Cur_Position p=cur_First(l);
while(p&&CursorSpace[p].e!=e)p=cur_Advance(p);
return p;
}
void cur_Delete(Cur_Element e,Cur_List l)
{
Cur_Position p=cur_FindPrevious(e,l);
Cur_Position tmp=cur_Advance(p);
CursorSpace[p].next=cur_Advance(tmp);
CursorFree(tmp);
}
Cur_Position cur_FindPrevious(Cur_Element e,Cur_List l)
{
Cur_Position p=l;
while(CursorSpace[p].next&&CursorSpace[CursorSpace[p].next].e!=e)p=cur_Advance(p);
return CursorSpace[p].next?p:0;
}
Cur_Position cur_Insert(Cur_Element e,Cur_List l,Cur_Position p)
{
Cur_Position tmp=(Cur_Position)CursorAlloc();
if (!tmp) return 0;
CursorSpace[tmp].e=e;
CursorSpace[tmp].next=CursorSpace[p].next;
CursorSpace[p].next=tmp;
return tmp;
}
void cur_DeleteList(Cur_List l)
{
CursorSpace[cur_Header(l)].next=0;
}
Cur_Position cur_Header(Cur_List l)
{
return l;
}
Cur_Position cur_First(Cur_List l)
{
return CursorSpace[l].next;
}
Cur_Position cur_Advance(Cur_Position p)
{
return p?CursorSpace[p].next:0;
}
Cur_Element cur_Retrieve(Cur_Position p)
{
return CursorSpace[p].e;
}
void cur_Update(Cur_Position p,Cur_Element e)
{
CursorSpace[p].e=e;
}
/*****************
测试部分:
*************/
/*menu_c.h*/
/*///
*author:Felix
*create date:Tue Jan 1 05:13:11 EST 2008
*last update:Tue Jan 1 05:13:11 EST 2008
*description:
*
*
*/
#include <stdio.h>
#ifndef __MENU____
#define __MENU____
#define SELECT() ((___sel=___select())!='0')
#define SELECTION ___sel
char ___sel;
char ___select();
/*
define the menu:
*/
#endif
/*menu_c.c*/
/*///
*author:Felix
*create date:Tue Jan 1 05:13:11 EST 2008
*last update:Tue Jan 1 05:13:11 EST 2008
*description:
*
*
*/
#include "menu_c.h"
char *___menu[]={
"1.Print list.h",
"2.Initialize the list with random integer.",
"3.Insert a number to the list.",
"4.Delete a number from the list.",
"5.Update a number in the list.",
"6.Delete the whole list.",
"7.Print the list",
"0.EXIT",
NULL
};
void ___showMenu()
{
printf("please select:/n");
char **p=___menu;
while(*p)printf("%s/n",*p++);
printf(":>");
}
char ___select()
{
char c;
___showMenu();
while((c=getchar())=='/n');
return c;
}
/*testList.c*/
/*///
*author:Felix
*create date:Tue Jan 1 05:13:11 EST 2008
*last update:Tue Jan 1 05:13:11 EST 2008
*description:
*
*
*//
#include "menu_c.h"
#include<stdio.h>
#include<stdlib.h>
#include<cur_list.h>
#define RAN_COUNT 30
#define DEF_MAX 9999
int main()
{
Cur_List l;
Cur_Position p;
int n,n2;
int count;
cur_InitializeCursor();
l=cur_MakeEmpty();
while(SELECT())
{
switch (SELECTION)
{
/*Print list.h*/
case '1':
system("less ../cur_list.h");
break;
/*Initialize the list with random integer.*/
case '2':
count=RAN_COUNT;
while(count-->0)cur_Insert(random_f(DEF_MAX),l,cur_Header(l));
break;
/*Insert a number to the list.*/
case '3':
printf("number to insert:>");
if(scanf("%d",&n)>0)
cur_Insert(n,l,cur_Header(l));
else printf("illegal input");
break;
/*Delete a number from the list.*/
case '4':
printf("number to delete:>");
if(scanf("%d",&n)>0)
{
if (cur_Find(n,l))cur_Delete(n,l);
else printf("no match found/n");
}else printf("illegal input/n ");
break;
/*Update a number in the list.*/
case '5':
printf("integer to update:>");
if(scanf("%d",&n)>0)
{
if (p=cur_Find(n,l))
{
printf("update with:>");
if(scanf("%d",&n2)>0)cur_Update(p,n2);
else printf("illegal input");
}
else printf("no match found/n");
}else printf("illegal input/n ");
break;
/*Delete the whole list.*/
case '6':
cur_DeleteList(l);
break;
/*print the list*/
case '7':
p=cur_First(l);
while(p)
{
printf("%d ",cur_Retrieve(p));
p=cur_Advance(p);
}
default:break;
}
}
return 0;
}