【零基础学数据结构】链表

这篇具有很好参考价值的文章主要介绍了【零基础学数据结构】链表。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 

目录

1.链表的概念

​编辑 2.链表的雏形

​编辑 3.链表的组成

​编辑 4.链表代码

 4.1创建节点

 4.2链表的打印

 4.3链表的尾插

 4.4链表的头插

 4.5链表的尾删

 4.6链表的头删

 4.7链表的查找

 4.8链表在指定位置之前插⼊数据

 4.9链表在指定位置之后插⼊数据

 4.9-1删除pos节点

 4.9-2删除pos之后的节点

4.9-3销毁链表

补充:测试文件:


1.链表的概念

 2.链表的雏形

 3.链表的组成

 4.链表代码

 创建准备;

  • SListNode.h文件
  • SListNode.c文件
  • text.c文件 

 4.1创建节点

 数据+指向下一个节点的指针

// 首先定义数据的类型,方便后续更改
typedef int SLTNodeDataType;

// 创建节点
typedef struct SListNode
{
	SLTNodeDataType data; // 存储数据
	struct SListNode* next;// 指向下一个节点的指针
}SLTNode;

 4.2链表的打印

 头文件声明:

void SLTPrint(SLTNode* phead);

执行文件代码实现: 

// 链表的打印
void SLTPrint(SLTNode* phead)
{
	SLTNode* pcur = phead;// 保证phead指向的位置是收节点,方便后续再次遍历
	while (pcur)// 等价于 pcur != NULL;
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("NULL\n");
}

 4.3链表的尾插

 头文件声明:

void SLTPushBack(SLTNode** pphead, SLTNodeDataType x);
// 创建新的节点
SLTNode* SLTBuyNode(SLTNodeDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (NULL == newnode)
	{
		perror("SLTBuyNode malloc err!");
		exit(1);
	}

	// 创建节点成功
	newnode->data = x;
	newnode->next = NULL;

	// 返回
	return newnode;
}

 执行文件代码实现: 

// 链表的尾插
void SLTPushBack(SLTNode** pphead, SLTNodeDataType x)
{
	// 传参不可为空
	assert(pphead);

	// 创建一个新的节点
	SLTNode* newnode = SLTBuyNode(x);

	// 空链表和非空链表
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{

		// 找尾巴
		SLTNode* ptail = *pphead;
		while (ptail->next) // 等价于ptail->next !=NULL;
		{
			ptail = ptail->next;
		}

		// 找到尾巴,开始连接
		ptail->next = newnode;
	}
	
}

 4.4链表的头插

  头文件声明:

// 链表的头插
void SLTPushFront(SLTNode** pphead, SLTNodeDataType x);

 执行文件代码实现:

// 链表的头插
void SLTPushFront(SLTNode** pphead, SLTNodeDataType x)
{
	// 传参不可为空
	assert(pphead);

	// 创建一个新的节点
	SLTNode* newnode = SLTBuyNode(x);

	// 头插
	newnode->next = *pphead;
	*pphead = newnode;
}

 4.5链表的尾删

 头文件声明:

void SLTPopBack(SLTNode** pphead);

  执行文件代码实现:

// 链表的尾删
void SLTPopBack(SLTNode** pphead)
{
	// 链表不可以为空,传参不可为空
	assert(pphead && *pphead);

	// 链表有一个节点和多个节点
	// 一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else //多个节点
	{
		// 找尾
		SLTNode* prev = *pphead;
		SLTNode* ptail = *pphead;

		while (ptail->next)
		{
			prev = ptail;
			ptail = ptail->next;
		}

		free(ptail); // 释放空间
		ptail = NULL;// 防止野指针
		prev->next = NULL;
	}
	
}

 4.6链表的头删

 头文件声明:

void SLTPopFront(SLTNode** pphead);

   执行文件代码实现:

// 链表的头删
void SLTPopFront(SLTNode** pphead)
{
	assert(pphead && *pphead);
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

 4.7链表的查找

 头文件声明:

SLTNode* SLTFind(SLTNode* phead, SLTNodeDataType x);

 执行文件代码实现:

// 链表的查找
SLTNode* SLTFind(SLTNode* phead, SLTNodeDataType x)
{
	
	SLTNode* prev = phead;
	while (prev)// 等价于 prev != NULL;
	{
		if (prev->data == x)
		{
			return prev;
		}
		prev = prev->next;
	}

	// 遍历完毕没有找到,返回空。
	return NULL;
}

 4.8链表在指定位置之前插⼊数据

 头文件声明:

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTNodeDataType x);

 执行文件代码实现:

// 链表在指定位置之前插⼊数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTNodeDataType x)
{
	// 不可以传入NULL
	assert(pphead && *pphead);
	assert(pos);

	// 创建一个新的节点
	SLTNode* newnode = SLTBuyNode(x);

	// 如果节点只有一个,就是头插
	if (pos == *pphead)
	{
		SLTPushFront(pphead, x);
	}
	else
	{
		SLTNode* pcur = *pphead;

		// pcur所指向的节点不为pos前一个节点
		while (pcur->next != pos)
		{
			pcur = pcur->next;
		}

		// pcur所指向的节点为pos前一个节点
		newnode->next = pos;
		pcur->next = newnode;
	}
}

 4.9链表在指定位置之后插⼊数据

  头文件声明:

void SLTInsertAfter(SLTNode* pos, SLTNodeDataType x);

 执行文件代码实现:

// 链表在指定位置之后插⼊数据
void SLTInsertAfter(SLTNode* pos, SLTNodeDataType x)
{
	assert(pos);

	// 创建要插入的节点
	SLTNode* newnode = SLTBuyNode(x);

	// 开始插入
	newnode->next = pos->next;
	pos->next = newnode;
}

 4.9-1删除pos节点

 头文件声明:

void SLTErase(SLTNode** pphead, SLTNode* pos);

  执行文件代码实现:

//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead && *pphead);
	assert(pos);
	if (*pphead == pos)
	{
		SLTPopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;

		while (prev->next != pos)
		{
			prev = prev->next;
		}

		// prev所指向的就是pos前一个节点
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}

}

 4.9-2删除pos之后的节点

 头文件声明:

void SLTEraseAfter(SLTNode* pos);

 执行文件代码实现:

//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos)
{
	assert(pos && pos->next); // 传过来的参数不可以为空,pos下一个的参数也不可以是NULL

	SLTNode* del = pos->next;
	pos->next = del->next;
	free(del);
	del = NULL;
}

4.9-3销毁链表

 文件声明:

void SListDesTroy(SLTNode** pphead);

 执行文件代码实现:

//销毁链表
void SListDesTroy(SLTNode** pphead)
{
	assert(pphead && *pphead);
	SLTNode* pcur = *pphead;
	while (pcur)
	{
		SLTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	// 全部销毁完后,置为空NULL;
	*pphead = NULL;
}

补充:测试文件:

//void SListNodeText01()
//{
//	// 创建节点
//	SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));
//	node1->data = 1;
//
//	SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));
//	node2->data = 2;
//
//	SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));
//	node3->data = 3;
//
//	SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));
//	node4->data = 4;
//
//	// 将四个节点连接起来
//	node1->next = node2;
//	node2->next = node3;
//	node3->next = node4;
//	node4->next = NULL;
//
//	// 打印
//	SLTPrint(node1);
//}

void SLTNodeText02()
{
	//SLTNode* plist = NULL;

	// 测试尾插
	//SLTPushBack(&plist, 1);
	//SLTPushBack(&plist, 2);
	//SLTPushBack(&plist, 3);
	//SLTPushBack(&plist, 4);
	/*SLTPrint(plist);*/// 1->2->3->4->NULL;


	// 测试头插
	/*SLTPushFront(&plist, 5);
	SLTPrint(plist);

	SLTPushFront(&plist, 6);
	SLTPrint(plist);

	SLTPushFront(&plist, 7);
	SLTPrint(plist);

	SLTPushFront(&plist, 8);
	SLTPrint(plist);*/


    // 测试尾删
	//SLTPopBack(&plist);
	//SLTPrint(plist);
	//SLTPopBack(&plist);
	//SLTPrint(plist);
	//SLTPopBack(&plist);
	//SLTPrint(plist);
	//SLTPopBack(&plist);
	//SLTPrint(plist);


	// 测试头删
	//SLTPopFront(&plist);
	//SLTPrint(plist);
	//SLTPopFront(&plist);
	//SLTPrint(plist);
	//SLTPopFront(&plist);
	//SLTPrint(plist);
	//SLTPopFront(&plist);
	//SLTPrint(plist);
	// 报错
	//SLTPopFront(&plist);
	//SLTPrint(plist);


	// 测试查找
	//SLTNode* find = SLTFind(plist, NULL);
	//if (find == NULL)
	//{
	//	printf("没有找到!\n");
	//}
	//else
	//{
	//	printf("找到了!\n");
	//}


	// 测试在pos位置之前插⼊数据
	//SLTNode* find = SLTFind(plist, 1);
	//SLTInsert(&plist, find, 11);
	//SLTPrint(plist);


	// 测试链表在指定位置之后插⼊数据
	/*SLTNode* find = SLTFind(plist, 4);
	SLTInsertAfter(find, 11);
	SLTPrint(plist);*/

	// 测试删除pos之后的节点
	/*SLTNode* find = SLTFind(plist, 1);
	SLTEraseAfter(find);
	SLTPrint(plist);*/

	// 测试销毁
	SListDesTroy(&plist);
}

int main()
{
	//SListNodeText01();
	SLTNodeText02();
	return 0;
}

 文章来源地址https://www.toymoban.com/news/detail-849909.html

到了这里,关于【零基础学数据结构】链表的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 探索树形数据结构,通识树、森林与二叉树的基础知识(专有名词),进一步利用顺序表和链表表示、遍历和线索树形结构

      结点之间有分支,具有层次关系 树的定义 : 树 (tree)是n(n≥0)个有限集。 若n = 0,则称为空树; 若n 0,则它满足如下两个条件: 有且仅有一个特定的称为根(Root)的结点; 其余结点可分为m(m≥0)个互不相交的有限集T1,T2,T3,.....,Tm,其中每一个集合本身又是一棵树,并称为根的

    2024年02月01日
    浏览(33)
  • 数据结构-链表结构-双向链表

    双向链表也叫双链表,与单向链表不同的是,每一个节点有三个区域组成:两个指针域,一个数据域 前一个指针域:存储前驱节点的内存地址 后一个指针域:存储后继节点的内存地址 数据域:存储节点数据 以下就是双向链表的最基本单位 节点的前指针域指向前驱,后指针

    2024年02月04日
    浏览(36)
  • <数据结构> 链表 - 链表的概念及结构

    概念: 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的 逻辑顺序 是通过链表中的 指针链接 次序实现的 1、链表由一系列结点(链表中每一个元素称为结点)组成。 2、结点可以在运行时动态(malloc)生成。 3、每个结点包括两个部分:一个是存储数据元素的

    2023年04月09日
    浏览(32)
  • 【数据结构-链表-01】反转链表

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年02月10日
    浏览(33)
  • 数据结构——线性数据结构(数组,链表,栈,队列)

    数组(Array) 是一种很常见的数据结构。它由相同类型的元素(element)组成,并且是使用一块连续的内存来存储。 我们直接可以利用元素的索引(index)可以计算出该元素对应的存储地址。 数组的特点是: 提供随机访问 并且容量有限。 2.1. 链表简介 链表(LinkedList) 虽然是

    2024年02月11日
    浏览(33)
  • 【数据结构】链表的回文结构

    单链表的操作算法是笔试面试中较为常见的题目。 本文将着重介绍平时面试中常见的关于链表的应用题目,马上要进行秋招了。希望对你们有帮助 _ 😀 对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。 给定一个链表的头指针

    2024年02月12日
    浏览(41)
  • 【数据结构】详解链表结构

    上篇博客已经介绍了顺序表的实现:【数据结构】详解顺序表。最后在里面也谈及了顺序表结构的缺陷,即 效率低,空间浪费 等等问题,那么为了解决这些问题,于是乎我们引入了链表的概念,下面将对链表结构进行讲解 首先肯定会问,到底什么是链表? 链表的概念 : 链

    2024年02月05日
    浏览(33)
  • 【数据结构】浅谈数据结构-链表【思路+例题学习】

    🏆今日学习目标: 🍀学习算法-数据结构-链表 ✅创作者:贤鱼 ⏰预计时间:30分钟 🎉个人主页:贤鱼的个人主页 🔥专栏系列:算法 🍁贤鱼的个人社区,欢迎你的加入 贤鱼摆烂团 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中

    2024年01月21日
    浏览(39)
  • 【数据结构】每天五分钟,快速入门数据结构(二)——链表

    目录 一 构建一个单向链表 二 特点 三 时间复杂度 四 相关算法 1.判断链表是否成环及成环位置 2.链表反转 五 Java中的LinkedList 类 1.使用 2.LinkedList 方法 长度无限 适合任意位置插入和删除频繁的场景 物理上可以不连续 访问、插入、删除 的时间复杂度均为O(n) 在头部插入元素

    2024年02月21日
    浏览(31)
  • 【数据结构】反转链表、链表的中间节点、链表的回文结构(单链表OJ题)

    正如标题所说,本文会图文详细解析三道单链表OJ题,分别为:  反转链表 (简单)  链表的中间节点 (简单)  链表的回文结构 (较难) 把他们放在一起讲的原因是:  反转链表 和  链表的中间节点 是  链表的回文结构 的基础 为什么这样说?请往下看: 目录 1. 反转链

    2024年02月13日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包