链表的游标实现

有许多语言都不支持指针,若需要链表又不能使用指针,就必须用另外的实现方法。我们称之为 游标(cursor)实现法。

链表的指针实现中有两个重要特性:

1.数据存储在一组结构体中,每个结构体包含数据以及指向下一个结构体的指针。

2.一个新的结构体可以通过调用malloc而从系统全局内存(global memory)中得到,并可通过调用free释放。

游标法必须能够模仿实现这两条特性。满足条件1的逻辑方法是要有一个全局的结构体数组。数组下标可以用来代表一个地址,要模拟条件2,可以让 CursorSpace数组中的单元来代行 malloc和free的职能,为此我们保留一个表(即freelist),这个表由不在任何表中的单元构成,该表将用单元0作为表头。如下给出链表游标实现的声明:

typedef int Position;
typedef int List;
typedef int ElementType;

struct Node
{
	ElementType Element;
	Position next;
};

struct Node CursorSpace[SIZE];

对于next,0的值等价于NULL指针。

初始化结构体数组例程:

一开始全为freelist,所以表为顺序相连的一个表,最后一个单元指向空 也即是0。

void InitCursorSpace()
{
	int i;
	for (i = 0; i < SIZE; i++)
	{
		CursorSpace[i].element = 0;
		CursorSpace[i].next = i + 1;
		if (i == SIZE - 1)
			CursorSpace[i].next = 0;
	}
}

创建表头例程:

List HeaderCreate()
{
	List list = CursorAlloc();
	if (list)
	{
		CursorSpace[list].next = 0;
		CursorSpace[list].element = 0;
	}
	return list;
}

声明空间例程:

将freelist中第一个单元的位置,也即CursorSpace[0].next位置的空间赋给p,然后freelist变成了从第二个单元开始的表,第五行将表头指向第二个单元,

Position CursorAlloc()
{
	Position p;
	p = CursorSpace[0].next;
	CursorSpace[0].next = CursorSpace[p].next;
	return p;
}

释放空间例程:

释放p位置的空间,就是把p位置的空间放到freelist中,最方便的是放到第一个单元,那么单元p指向原第一单元,再将表头指向单元p,那么p进入freelist中,释放完成。

void CursorFree(Position p)
{
	CursorSpace[p].next = CursorSpace[0].next;
	CursorSpace[0].next = p;
}

判断表是否为空与某单元是否在表末尾:查找与查找前一个:

Position Find(List list, ElementType x)
{
	Position tmpNode;
	tmpNode = CursorSpace[list].next;
	while (tmpNode && CursorSpace[tmpNode].element != x)
		tmpNode = CursorSpace[tmpNode].next;
	return tmpNode;
}
Position FindPrevious(List list, ElementType x)
{
	if (IsEmpty(list))
		return 0;
	Position tmpNode = list;
	Position nextNode = CursorSpace[tmpNode].next;
	while (!IsLast(tmpNode) && CursorSpace[nextNode].element != x)
	{
		tmpNode = CursorSpace[tmpNode].next;
		nextNode = CursorSpace[tmpNode].next;
	}
	return tmpNode;
}

删除:

这里没写出尾删,读者可以试一试自行写出

void Delete(List list, ElementType x)
{
	Position p, tmpNode;
	p = FindPrevious(list, x);
	if (!IsLast(p))
	{
		tmpNode = CursorSpace[p].next;
		CursorSpace[p].next = CursorSpace[tmpNode].next;
		CursorFree(tmpNode);
	}
}

插入与尾插:

void Insert(List list, ElementType x, Position p)
{
	Position tmpNode = CursorAlloc();
	if (!tmpNode)
	{
		printf("insert failed\n");
		return;
	}
	CursorSpace[tmpNode].element = x;
	CursorSpace[tmpNode].next = CursorSpace[p].next;
	CursorSpace[p].next = tmpNode;
}
void BackInsert(List list, ElementType x)
{
	Position tmpNode = list;
	while (CursorSpace[tmpNode].next)
		tmpNode = CursorSpace[tmpNode].next;
	Insert(list, x, tmpNode);
}

链表的打印:

void PrintList(List list)
{
	Position tmpNode = list;
	while (CursorSpace[tmpNode].next)
	{
		printf("%d ", CursorSpace[CursorSpace[tmpNode].next].element);
		tmpNode = CursorSpace[tmpNode].next;
	}
	printf("\n");
}

测试:

int main()
{
	InitCursorSpace();
	List L = HeaderCreate();
	BackInsert(L, 4);
	BackInsert(L, 2);
	BackInsert(L, 3);
	BackInsert(L, 7);
	BackInsert(L, 6);
	BackInsert(L, 10);

	PrintList(L);

	Delete(L, 4);
	PrintList(L);
	
	Delete(L, 6);
	PrintList(L);
	return 0;
}

输出结果:

4 2 3 7 6 10

2 3 7 6 10

2 3 7 10

至此链表的游标实现完成。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值