文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C语言单链表的图文示例讲解

2023-02-14 15:00

关注

在上一篇所讲述的 动态顺序表 中存在一些缺陷

1、当空间不够时需要扩容,扩容是有一定的消耗的

如果每次空间扩大一点,可能会造成空间的浪费,而空间扩小了,又会造成频繁的扩容2、在顺序表中进行头部和中部的插入时需要移动数据,效率低下

对于顺序表的这些缺陷,有如下解决方案

1、需要时申请一块空间,不需要时将其释放

2、插入删除不需要移动数据

而链表就符合这两点,本篇介绍 无头单向非循环链表(单链表)

一、单链表的结构

空链表: 此时没有存储数据,只有一个指针指向 NULL

以上便是单链表的结构:

在习惯上将申请的一块一块的空间称为结点,指向第一个结点的指针称为头指针

//数据的类型:这里以 int 来举例
typedef int SLTDataType;
//结点的类型
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

二、单链表的函数接口

1. 申请结点及打印单链表

在插入时需要申请结点,为了避免麻烦重复的操作,这里将申请结点封装为一个函数

申请结点函数如下:

SLTNode* BuySLTNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if(newnode == NULL)
	{
		//开辟空间失败,打印错误信息
		perror("malloc");
		//结束程序
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

为了验证插入、删除等得到的结果是否正确,提供打印单链表的函数,这里数据类型以 int 为例,当读者采用的类型不同时,自行更改函数即可

打印单链表函数如下:

void SLTPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	//打印数据
	while(cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

2. 尾插尾删

尾插:在链表的最后一个结点之后插入结点

尾插函数如下:

//在链表为空时,需要改变头指针,这里采用传二级指针的方式
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	//申请结点
	SLTNode* newnode = BuySLTNode(x);
	//链表为空时
	if(*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		//找到最后一个结点
		SLTNode* ptail = *pphead;
		while(ptail->next)
		{
			ptail = ptail->next;
		}
		ptail->next = newnode;
	}
}

尾删:删除链表最后一个结点

尾删函数如下:

//链表只有一个结点时,需要改变头指针,这里采用传二级指针的方式
void SLTPopBack(SLTNode** pphead)
{
	//链表为空时,无法删除
	assert(*pphead);
	//链表只有一个结点时
	if((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		//找到倒数第二个结点
		SLTNode* ptail = *pphead;
		while(ptail->next->next)
		{
			ptail = ptail->next;
		}
		free(ptail->next);
		ptail->next = NULL;
	}
}

3. 头插头删

头插: 在第一个结点之前插入新结点

头插函数如下:

//需要改变头指针,这里采用传二级指针的方式
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	//申请结点
	SLTNode* newnode = BuySLTNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

头删:删除链表的第一个结点

头删函数如下:

//需要改变头指针,这里采用传二级指针的方式
void SLTPopFront(SLTNode** pphead)
{
	//链表为空时,无法删除
	assert(*pphead);
	//保存第二个结点
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

4. 中间插入和删除

中间插入:通过后面介绍的查找函数 SLTFind 获得指向结点的指针 pos,在 pos 指向的 结点之前 或 之后 插入结点

1. 在 pos 指向的结点之后插入结点

在 pos 之后插入结点函数如下:

void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	//pos 不能为空
	assert(pos);
	//申请结点
	SLTNode* newnode = BuySLTNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

2. 在 pos 指向的结点之前插入结点

在 pos 之前插入结点函数如下:

//pos 指向头结点时,需要改变头指针,这里采用传二级指针的方式
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	//pos 不能为空
	assert(pos);
	//头插
	if(*pphead == pos)
	{
		SLTPushFront(pphead, x);
	}
	else
	{
		//找到 pos 的前一个结点
		SLTNode* prev = *pphead;
		while(prev->next != pos)
		{
			prev = prev->next;
		}
		//申请结点
		SLTNode* newnode = BuySLTNode(x);
		newnode->next = pos;
		prev->next = newnode;
	}
}

中间删除:通过后面介绍的查找函数 SLTFind 获得指向结点的指针 pos,删除 pos 指向的结点 或 后一个结点

3. 删除 pos 指向的结点的后一个结点

删除 pos 之后的结点函数如下:

void SLTEraseAfter(SLTNode* pos)
{
	//pos 不能为空
	assert(pos);
	//指向最后一个结点时,不做处理
	if(pos->next == NULL)
	{
		return;
	}
	else
	{
		//保存后一个结点
		SLTNode* next = pos->next;
		pos->next = next->next;
		free(next);
	}
}

4. 删除 pos 指向的结点

删除 pos 指向的结点函数如下:

//pos 指向头结点时,需要改变头指针,这里采用传二级指针的方式
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	//pos 不能为空
	assert(pos);
	//头删
	if (*pphead == pos)
	{
		SLTPopFront(pphead);
	}
	else
	{
		//找到 pos 的前一个结点
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

6. 查找

查找:如果数据存在,返回该数据结点的指针,不存在返回 NULL

查找函数如下:

SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* cur = phead;
	//查找
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

7. 销毁单链表

在单链表中,存储数据的结点是由自己开辟的,当不使用单链表时,应将其销毁

销毁单链表函数如下:

需要将头指针置空,这里采用传二级指针的方式
void SLTDestroy(SLTNode** pphead)
{
	SLTNode* cur = *pphead;
	while (cur)
	{
		//保存下一个结点
		SLTNode* nextnode = cur->next;
		free(cur);
		cur = nextnode;
	}
	//将头指针置空
	*pphead = NULL;
}

到此这篇关于C语言单链表的图文示例讲解的文章就介绍到这了,更多相关C语言单链表 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯