初阶数据结构:链表

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

1. 引子:什么是链表

经过学习与练习,已经掌握了顺序表的相关知识并且能够自我实现。在这一过程中,通过对其结构的实现,发现顺序表的尾部插入删除数据效率很高,可是,在头部与随机插入的场景下效率低下而且存在扩容消耗等一些问题。而有这样一种数据结构可以很好的解决顺序表存在的这些问题,将琐碎的系统空间充分利用,任意位置的插入删除效率都很高。此种数据结构称为链表,接下来进行对其的学习。

2. 简单数据结构:链表

2.1 链表简介与功能分析

简介:

链表,正如其名,存储其中的数据在物理上是离散的,各个数据间使用一条 “链子” 串联而成(记录下一元素地址的指针)。链表的具体结构存在数种,以是否带头是否能双向访问是否循环,这三个特点被简单分为六种,下面,我们先进行其中一种,带头单向不循环链表进行学习。

单向带头不循环链表结构图:
初阶数据结构:链表,数据结构,链表

功能分析模块:

数据存储方式:

  1. 动态开辟malloc的一块块小内存块。
  2. 存储信息为数据值,与记录下一个结点的指针
    以上两点创建的结点结构体

数据管理方式:

  1. 增(头插,尾插,随机插入):push_front,push_back,insert,insertafter
  2. 删(头删,尾删,随机删除):pop_front,pop_back,erase,eraseafter
  3. 改(指定数据的修改):modify
  4. 查(指定数据的查询):find

2.2 单链表的实现

2.2.1 单链表:存储数据的结构体

链表结点的构建:

typedef int ListDataType;

typedef struct ListNode
{
	ListDataType val;
	//声明类型的过程中不能直接使用typedef后的名字
	struct ListNode* next;
}ListNode;

2.2.2 单链表:结点创建与链表数据清理

结点创建:

初阶数据结构:链表,数据结构,链表

ListNode* BuyNewNode(ListDataType val)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
		perror("malloc failed");
		exit(-1);
	}

	newnode->val = val;
	newnode->next = NULL;

	return newnode;
}

链表销毁:

过程演示:

初阶数据结构:链表,数据结构,链表

//链表销毁
void ListDestroy(ListNode** PPhead)
{
	assert(PPhead);
	ListNode* Phead = *PPhead;

	ListNode* cout = Phead;

	if (Phead != NULL)
	{
		while (Phead->next != NULL)
		{
			Phead = Phead->next;
			free(cout);
			cout = Phead;
		}

		free(Phead);

		*PPhead = NULL;
	}
}

注:Phead为list的一份值拷贝,因此要想能够改变list(链表头)的值,传参是我们应该采用二重指针传址传参。

初阶数据结构:链表,数据结构,链表

2.2.2 单链表插入数据与删除

头插,头删:

头插过程演示:

链表为空时头插:
初阶数据结构:链表,数据结构,链表

链表不为空时头插:
初阶数据结构:链表,数据结构,链表

头删过程演示:

初阶数据结构:链表,数据结构,链表

//头插
void ListPush_Front(ListNode** PPhead, ListDataType val)
{
	assert(PPhead);
	ListNode* Phead = *PPhead;

	ListNode* newnode = BuyNewNode(val);

	if (Phead == NULL)
	{
		*PPhead = newnode;
	}
	else
	{
		ListNode* next = Phead;
		newnode->next = Phead;
		*PPhead = newnode;
	}
}


//头删
void ListPop_Front(ListNode** PPhead)
{
	assert(PPhead);
	ListNode* Phead = *PPhead;
	assert(Phead);

	ListNode* next = Phead->next;
	
	free(Phead);
	*PPhead = next;
}

尾插,尾删:

//尾插
void ListPush_Back(ListNode** PPhead, ListDataType val)
{
	assert(PPhead);
	ListNode* Phead = *PPhead;
	
	ListNode* end_node = Phead;
	while (end_node != NULL && end_node->next != NULL)
	{
		end_node = end_node->next;
	}

	ListNode* newnode = BuyNewNode(val);
	if (end_node == NULL)
	{
		*PPhead = newnode;
	}
	else//end_node->next == NULL
	{
		end_node->next = newnode;
	}

}

//尾删
void ListPop_Back(ListNode** PPhead)
{
	assert(PPhead);
	ListNode* Phead = *PPhead;
	assert(Phead);

	ListNode* end_node = Phead;
	//特殊情况
	if (end_node->next == NULL)
	{
		free(end_node);
		*PPhead = NULL;
	}
	else//end_node->next != NULL
	{
		//逻辑短路
		while (end_node->next->next != NULL)
		{
			end_node = end_node->next;
		}

		free(end_node->next);
		end_node->next = NULL;
	}
}

随机插入与删除:

在指定结点(pos)之前插入:

void ListInsert(ListNode** PPhead, ListNode* pos, ListDataType val)
{
	//不考虑结点不存在的情况
	//与ListFind模块配合使用
	assert(PPhead);
	ListNode* Phead = *PPhead;
	assert(Phead);
	assert(pos);
	
	//复用头插
	if (pos == Phead)
	{
		ListPush_Front(PPhead, val);
	}
	else
	{
		ListNode* search = Phead;
		//寻找pos结点
		while (search->next != pos)
		{
			search = search->next;
		}
		
		//插入
		ListNode* newnode = BuyNewNode(val);
		ListNode* next = search->next;
		
		search->next = newnode;
		newnode->next = next;
	}
}

在指定结点(pos)之后插入:

void ListInsertAfter(ListNode* pos, ListDataType val)
{
	//结点不能为NULL
	assert(pos);

	ListNode* next = pos->next;

	ListNode* newnode = BuyNewNode(val);

	pos->next = newnode;
	newnode->next = next;
}

删除指定结点(pos)之后的结点:

void ListEraseAfter(ListNode* pos)
{
	assert(pos);
	assert(pos->next);

	ListNode* next = pos->next;
	pos->next = pos->next->next;

	free(next);

	next = NULL;

	pos->next = next;
}

删除指定结点(pos):

void ListErase(ListNode** PPhead, ListNode* pos)
{
	assert(PPhead);
	ListNode* Phead = *PPhead;
	assert(Phead);
	assert(pos);
	
	//头删
	if (pos == Phead)
	{
		ListPop_Front(PPhead);
	}
	else
	{
		ListNode* search = Phead;
		while (search->next != pos)
		{
			search = search->next;
		}

		ListNode* next = search->next->next;

		free(search->next);
		search->next = next;
	}
}

2.2.3 单链表查询与修改

元素查询:

ListNode* ListFind(ListNode** PPhead, ListDataType val)
{
	assert(PPhead);
	ListNode* Phead = *PPhead;
	assert(Phead);

	ListNode* search = Phead;
	while (search != NULL && search->val != val)
	{
		search = search->next;
	}

	return search;
}

数据修改:

void ListModify(ListNode* Node, ListDataType val)
{
	assert(Node);

	Node->val = val;
}

链表元素打印:文章来源地址https://www.toymoban.com/news/detail-807525.html

void ListPrint(ListNode* Phead)
{
	while (Phead != NULL)
	{
		printf("%d->", Phead->val);
		Phead = Phead->next;
	}
	printf("NULL\n");
}

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

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

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

相关文章

  • 初阶数据结构之---顺序表和链表(C语言)

    线性表: 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构。线性表在逻辑上是线性结构,也就是说是连续的一条直线。但在物理上并不一定是连续的。线性表在物理上存储时,通常以 数组 和 链式结构 的形式存储。

    2024年02月22日
    浏览(67)
  • 【数据结构初阶】四、线性表里的链表(带头+双向+循环 链表 -- C语言实现)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【数据结构初阶】三、 线性表里的链表(无头+单向+非循环链表 -- C语言实现)-CSDN博客  ====

    2024年02月08日
    浏览(45)
  • 『初阶数据结构 • C语言』⑨ - 基于结点的数据结构——链表(单链表&&双向循环链表)附完整源码

      本章内容 1.什么是链表 2.链表常见几种形式 3.无头单向非循环链表的实现 3.1结点结构的定义 3.2函数接口的实现 3.2.1尾插 3.2.2尾删 4. 带头双向循环链表的实现 4.1结点结构的定义 4.2函数接口的实现 5.两种链表的差异 ①尾插与尾删的时间复杂度 ②头插与头删的时间复杂度 ③

    2024年02月16日
    浏览(82)
  • 【数据结构和算法初阶(C语言)】复杂链表(随机指针,随机链表的复制)题目详解+链表顺序表结尾

    目录  1.随机链表的复制 1.2题目描述  1.3题目分析 1.4解题: 2.顺序表和链表对比 2.1cpu高速缓存利用率 3.结语 一个长度为  n  的链表,每个节点包含一个额外增加的随机指针  random   该指针可以指向链表中的任何节点或空节点。        构造这个链表的  深拷贝 。 深拷贝

    2024年03月10日
    浏览(87)
  • 【数据结构初阶】三、 线性表里的链表(无头+单向+非循环链表 -- C语言实现)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【数据结构初阶】二、 线性表里的顺序表(C语言实现顺序表)-CSDN博客  =========================

    2024年02月08日
    浏览(57)
  • 数据结构(初阶)第一节:数据结构概论

    本篇文章是对数据结构概念的 纯理论 介绍,希望系统了解数据结构概念的友友可以看看,对概念要求不高的友友稍做了解后移步下一节: 数据结构(初阶)第二节:顺序表-CSDN博客 目录 正文 1.数据结构的相关概念 1.1什么是数据 1.2什么是数据结构 1.3为什么需要数据结构 1

    2024年04月10日
    浏览(71)
  • 『初阶数据结构 • C语言』① - 数据结构为何重要

    本文内容借鉴一本我非常喜欢的书——《数据结构与算法图解》。学习之余,我决定把这本书精彩的部分摘录出来与大家分享。 数组是计算机科学中最基本的数据结构之一。如果你用过数组,那么应该知道它就是一个含有 数据的列表。它有多种用途,适用于各种场景,下面

    2024年02月16日
    浏览(47)
  • 数据结构:二叉树(初阶)

    朋友们、伙计们,我们又见面了,本期来给大家解读一下二叉树方面的相关知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!   C 语 言 专 栏:C语言:从入门到精通 数据结构专栏:数据结构 个  人  主  页 :stackY、 目录  ​编辑 前言:

    2024年02月07日
    浏览(36)
  • 数据结构初阶

    讲到了数据结构是什么,我们就得先知道什么叫做数据。 数据   数据,《大话数据结构》这本书中,给出的定义:是描述客观事物的符号,是计算机中可以操作的对象,是能够被计算机识别,并输入给计算机处理的符号集合。   数据不仅仅包括整型,实型等数值类型,还包

    2024年02月04日
    浏览(39)
  • 数据结构初阶--二叉树的链式结构

    目录 一.二叉树链式结构的概念 二.二叉树链式结构的功能实现 2.1.链式二叉树的定义 2.2.链式二叉树的构建 2.3.链式二叉树的遍历 2.3.1.先序遍历 2.3.2.中序遍历 2.3.3.后序遍历 2.3.4.层序遍历 2.4.链式二叉树的求二叉树的结点数量 法一:计数法 法二:分治法 2.5.链式二叉树的求二

    2024年02月12日
    浏览(43)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包