线性表的静态单链表存储结构

/*
借用一维数组来描述线性链表 
—————— 线性表的静态单链表存储结构——————
#define MAXSIZE 1000 //链表的最大长度
typedef struct 
{
	ElemType data;
	int cur;
}component,SLinkList[MAXSIZE];
这种描述方法便于不设“指针”类型的高级程序设计语言中使用链表结构 
如上描述的链表中,数组的一个分量表示一个结点,同时用游标(指示器cur)代替指针指示结点在数组中的相对位置
数组的第零分量可看成头结点,其指针域指示链表的第一个结点
这种存储结构仍需要预先分配一个较大的空间,但在线性链表的插入和删除操作时不需要移动元素,
仅需修改指针(cur),仍具有链式存储结构的优点,把这种用数组描述的链表起名叫 静态链表
*/

#include <stdio.h>

#define MAXSIZE 100 //链表的最大长度
typedef struct 
{
	int data;
	int cur;
}component,SLinkList[MAXSIZE];

void InitList(SLinkList L); //构造一个空的链表

//以下两个函数被函数ListInsert()调用
int Malloc(SLinkList space); 
int ListLength(SLinkList L); //返回L中数据元素的个数
bool ListInsert(SLinkList L,int i,int e); //在L中第i个元素之前插入新的数据元素e 

bool ListTraverse(SLinkList L); //输出线性表的数据
void ListEmpty(SLinkList L); //判断线性表是否为空
bool ClearList(SLinkList L); //将L置为空表
bool GetElem(SLinkList L,int i,int *e); //用e返回L中第i元素的值
int LocateElem(SLinkList L,int e);
bool PriorElem(SLinkList L,int cur_e,int *pre_e); 
bool NextElem(SLinkList L,int cur_e,int *next_e);
void Free(SLinkList space,int k);
bool ListDelete(SLinkList L,int i,int *e);

int main()
{
	int j, k;
	int e, e0;
	SLinkList L;
	InitList(L);
	for(j = 1; j <= 5; j++)
		ListInsert(L,1,j);
	printf("在L的表头依次插入1-5后:L = ");
	ListTraverse(L);
	
	ListEmpty(L); //判断L是否为空 
	printf("len = %d\n",ListLength(L));

	ClearList(L); //清空链表
	ListEmpty(L); //判断L是否为空

	for(j = 1; j <= 10; j++)
		ListInsert(L,j,j);
	printf("在L的表中依次插入1-10后:L = ");
	ListTraverse(L);

	GetElem(L,5,&e);//把第5个元素赋给 e
	printf("第5个元素的值为:%d\n",e);

	for(j = 1; j <= 10; j++)
	{
		k = LocateElem(L,j);
		if(k)
			printf("值为%d的元素在静态链表中的位序为%d\n",j,k);
		else
			printf("没有值为%d的元素\n",j);
	}

	for(j = 1; j <= 2; j++) //测试头两个数据
	{
		GetElem(L,j,&e0); //把第j个数据赋给e0
		PriorElem(L,e0,&e); //求e0的前驱
		if( PriorElem(L,e0,&e) )
			printf("元素%d的前驱为:%d\n",e0,e);
		else
			printf("元素%d无前驱\n",e0);
	}

	for(j = ListLength(L) - 1; j <= ListLength(L); j++) //最后两个数据
	{
		GetElem(L,j,&e0); //把第j个元素赋给e0;
		NextElem(L,e0,&e); //求e0的后继
		if( NextElem(L,e0,&e) )
			printf("元素%d的后继为:%d\n",e0,e);
		else
			printf("元素%d无后继\n",e0);
	}

	k = ListLength(L); //k为表长
	ListDelete(L,k,&e);
	printf("删除的元素为: %d\n",e);
	ListDelete(L,k-1,&e);
	printf("删除的元素为: %d\n",e);
	printf("依次输出L的元素:");
	ListTraverse(L); //输出元素的值

	return 0;
}

void InitList(SLinkList L) //构造一个空的链表
{	//表头为L的最后一个单元L[MAXSIZE-1] ,其余单元链成一个
	//备用链表,表头为L的第一个单元L[0].cur, "0"表示空指针
	int i;
	L[MAXSIZE-1].cur = 0; //L的最后一个单元为空链表的表头
	for(i = 0; i < MAXSIZE - 2; i++) //将其余单元链接成以L[0]为表头的备用链表
		L[i].cur = i + 1;
	L[MAXSIZE-2].cur = 0;
}

bool ListInsert(SLinkList L,int i,int e) //在L中第i个元素之前插入新的数据元素e 
{
	int l, j, k = MAXSIZE - 1; //k指向表头
	if(i < 1 || i > ListLength(L) + 1)
		return false;
	j = Malloc(L); //申请新单元
	if(j) //申请成功
	{
		L[j].data = e; //赋值给新单元
		for(l = 1; l < i; l++) //移动第i-1个元素
			k = L[k].cur;
		L[j].cur = L[k].cur;
		L[k].cur = j;
		return true;
	}
	return false;
}

int ListLength(SLinkList L) //返回L中数据元素的个数
{
	int j = 0, i = L[MAXSIZE-1].cur; //i指向第一个元素
	while(i) //没到静态链表尾
	{
		i = L[i].cur; //指向下一个元素
		j++;
	}
	return j;
}

int Malloc(SLinkList space)
{	//若备用链表非空,则返回分配的结点下标(备用链表的第一个结点),否则返回 0
	int i = space[0].cur;
	if(i) //备用链表非空
		space[0].cur = space[i].cur; //备用链表的头节点指向原备用链表的第二个结点
	return i; //返回
}

bool ListTraverse(SLinkList L) //输出线性表的数据
{
	int i = L[MAXSIZE-1].cur; //指向第一个元素
	while(i) //没有到静态链表尾
	{
		printf("%d ",L[i].data);
		i = L[i].cur; //指向下一个元素
	}
	printf("\n");
	return true;
}

void ListEmpty(SLinkList L) //判断线性表是否为空
{
	if(L[MAXSIZE-1].cur == 0) //表为空
		printf("链表为空\n");
	else
		printf("链表不为空\n");
}

bool ClearList(SLinkList L) //将L置为空表       
{
	int i, j, k;
	i = L[MAXSIZE-1].cur; //链表第一个结点的位置
	L[MAXSIZE-1].cur = 0; //链表空
	k = L[0].cur; //备用链表第一个结点的位置
	L[0].cur = i; // 把链表的结点连接到备用链表的表头
	while(i) //没有到表尾
	{
		j = i;
		i = L[i].cur; //指向下一个元素
	}
	L[j].cur = k; //备用链表的第一个结点连接到链表的尾部
	return true;
}

bool GetElem(SLinkList L,int i,int *e) //用e返回L中第i元素的值
{
	int l,k = MAXSIZE - 1; //K指向表头序号
	if(i < 1|| i > ListLength(L))
		return false;
	for(l = 1; l <= i; l++) //移动到第i个元素处
		k = L[k].cur;
	*e = L[k].data;
	return true;
}

int LocateElem(SLinkList L,int e)
{
	//在静态单链线性表L中查找第i个值为e的元素 若找到,则返回它在L中的位序 
	int i = L[MAXSIZE-1].cur; //i指示表中第一个结点
	while(i && L[i].data != e) //在表中顺序查找
		i = L[i].cur;
	return i;
}

bool PriorElem(SLinkList L,int cur_e,int *pre_e)
{
	// 若cur_e是L的数据元素,且不是第一个 则用pre_e返回它的前驱
	int j, i = L[MAXSIZE-1].cur; //i指示链表第一个结点的位置
	do
	{
		//向后移动结点
		j = i;
		i = L[i].cur;
	}while(i && cur_e != L[i].data);
	if(i) //找到该元素
	{
		*pre_e = L[j].data;
		return true;
	}
	return false;
}

bool NextElem(SLinkList L,int cur_e,int *next_e)
{
	//若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继
	int j, i = LocateElem(L,cur_e); //在L中查找第一个值为cur_e元素的位置
	if(i) //L中存在cur_e
	{
		j = L[i].cur; //cur_e的后继位置
		if(j) //cur_e有后继
		{
			*next_e = L[j].data;
			return true; //cur_e元素有后继
		}
	}
	return false;
}

bool ListDelete(SLinkList L,int i,int *e)
{
	//删除在L中第i个数据元素e 并返回其值
	int j, k = MAXSIZE - 1;
	if(i < 1 || i > ListLength(L))
		return false;
	for(j = 1; j < i; j++) //移动 i- 1 个元素
		k = L[k].cur;
	j = L[k].cur;
	L[k].cur = L[j].cur;
	*e = L[j].data;
	Free(L,j);
	return true;
}

void Free(SLinkList space,int k)
{
	//将下标为k的空闲结点回收到备用链表
	space[k].cur = space[0].cur; //回收结点的“游标”指向备用链表的第一个结点
	space[0].cur = k; //备用链表的头结点指向新的收点
}

程序执行结果:


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值