线性表的链式存储实现(C语言)



前言

由于顺序表的存储特点是用物理上的相邻实现了逻辑上的相邻,它要求用连续的存储单元顺序存储线性表中各元素,因此对顺序表的插入、删除时需要通过移动数据元素来实现,影响了运行效率并且会产生空间浪费,为此引入线性表另一结构—链式存储

在这里插入图片描述
如图是一个单向链表,表头变量head用来存放链表首结点的地址,链表中每个结点由数据部分和下一个结点的地址部分组成,即每个结点都包含指向下一个结点的指针。最后一个结点称为表尾,其下一个结点的地址部分的值为NULL(表示空地址),链表中的各个结点在内存中的存放可能是连续的,也可能是不连续的,具体存放位置由系统分配。

一、链式表的结构定义

typedef struct LNode * PtrToLNode;
struct LNode
{
	ElementType Data;
	PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;

二、求表长

在链式表中求表长需要将链表从头到尾遍历一遍,设一个移动指针p和计数器cnt,初始化后,p从表的第一个结点开始逐步往后移,同时cnt+1,当后面不再有结点时,cnt的值就是结点个数,即表长。具体代码如下:

int Length (List L)
{
	Position p;
	int cnt=0;//初始化计数器
	p=L;//p指向第一个结点
	while (p)
	{
		p=p->Next;
		cnt++;//当前p指向的是第cnt个结点
	}
	return cnt;
}

二、查找

1、链式表的按序号查找

对于链式存储的查找,假设要查找第K个元素的值,需要从链表的第一个结点起,判断当前结点是否是第K个,若是,返回该结点的值,否则继续后一个,直到表结束为止,如果没有第K个结点则返回错误信息。
代码如下:

#define ERROR -1
ElementType FindKth(List L,int K)
{//根据指定的位序K返回L中相应的元素
	Position p;
	int cnt=1;
	p=L;
	while (p&&cnt<K)
	{
		p=p->Next;
		cnt++;
	}
	if (cnt == K&&p)
		return p->Data;
	else 
		return ERROR;
}

2、链式表的按值查找

按值查找的基本方法也是从头到尾遍历,直到找到为止,从第一个结点起,判断当前结点的值是否等于X,若是,返回该结点的位置,否则继续后一个,直到表结束为止,找不到则返回错误信息。
代码如下:

#define ERROR NULL//用空地址表示错误
Position Find (List L, ElementType X)
{
	Position p=L;//p指向L的第一个结点
	while (p&&p->Data!=X)
		p=p->Next;
	if (p)
		return p;
	else
		return ERROR;
}

三、插入

线性表的插入是在指定位序i(1<=i<=n+1)前插一个新元素X。当插入位序为1时,代表插入到链表的头,i为n+1时,代表插入到链表最后。基本思路是如果i不为1,则找到位序为i-1的结点pre,若存在,则申请一个新结点并在数据域填上相应值X,然后将新结点插入到结点pre之后,返回链表,如果不存在则返回错误信息。代码如下:

1、不带头结点的链式表的插入

#define ERROR NULL
List Insert(List L, ElementType X, int i)
{
	Position tmp,pre;
	tmp=(Position)malloc(sizeof(struct LNode));//申请,填装结点
	tmp->Data=X;
	if(i==1)//新结点插在表头
	{
		tmp->Next=L;
		return tmp;//返回新表头指针
	}
	else
	{//查找位序为i-1的结点
		int cnt=1;
		pre=L;
		while(pre&&cnt<i-1)
		{
			pre=pre->Next;
			cnt++;
		}
		if(pre==NULL||cnt!=i-1)//所找结点不在L中
		{
			printf("插入位置参数错误\n");
			free(tmp);
			return ERROR;
		}
		else//找到了待插结点的前一个结点pre
		{
		//插入新结点并返回表头
			tmp->Next=pre->Next;
			pre->Next=tmp;
			return L;
		}
	}
}

2、带头结点的链式表的插入

bool Insert(List L, ElementType X, int i)
{
	Position tmp,pre;
	int cnt=0;
	pre=L;//pre指向表头
	while(pre&&cnt<i-1)
	{
		pre=pre->Next;
		cnt++;
	}
	if(pre==NULL||cnt!=i-1)//所找结点不在L中
	{
		printf("插入位置参数错误";
		return false;
	}
	else
	{//找到了待插结点的前一个结点pre,插入新结点,若i=1,则pre指向表头
		tmp=(Position)malloc(sizeof(struct LNode));//申请,填装结点
		tmp->Data=X;
		tmp->Next=pre->Next;
		pre->Next=tmp;
		printf("插入成功");
		return true;
		
	}
}

四、带头结点的链式表的删除

在单向链表中删除指定位序i的元素,首先需要找到被删除结点的前一个元素,然后再删除结点并释放空间。代码如下:

bool Delete( List L, int i)
{
//这里默认L有头结点
	Position tmp,pre;
	int cnt=0;	
	pre=L;//pre指向表头
	while(pre&&cnt<i-1)
	{
		pre=pre->Next;
		cnt++;
	}
	if(pre==NULL||cnt!=i-1||pre->Next==NULL)//所找结点或位序为i的结点不在L中
	{
		printf("删除位置参数错误")return false;
	}
	else//找到了待删结点的前一个结点
	{//将结点删除
		tmp=pre->Next;
		pre->Next=tmp->Next;
		free(tmp);
		printf("删除成功");
		return true;
	}
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值