链表:概念解析与C语言代码实现

数据结构学习指南:从概念到代码实践,构建立体知识体系 数据结构是计算机科学的核心基础,它研究数据的组织、存储和操作方式,是算法设计与程序优化的基石。其核心原理在于通过逻辑结构(如线性表、树、图)描述数据关系,并通过物理存储结构(如顺序、链式)在计算机内存中实现。掌握数据结构的技术价值在于能够显著提升程序运行效率与资源利用率,是解决复杂计算问题、进行系统性能优化的关键。在应用场景上,从数据库索引(B树)、网络路由(图算法)到编译器设计(栈)、缓存系统(队列),数据结构无处不在。本文以严蔚敏经典教材为蓝本,通过重构知识框架与提供可运行的C语言代码,特别是针对链表操 阅读详情

一、前言

前几篇博客里介绍了顺序表这种数据结构。

顺序表:概念解析与C语言代码实现-优快云博客

基于顺序表实现通讯录项目-优快云博客

用双指针法解决两道顺序表基础算法题(LeetCode 27 & 88)-优快云博客

而顺序表虽然可以方便地完成增删查改等操作,却也存在不足:

1、中间、头部的插入删除,涉及到移动数据,比较麻烦。

2、增容需要申请新的空间、拷贝数据、释放旧空间,会有不小的性能消耗。

3、增容一般是呈2倍的增长,势必会有一定的空间浪费。

为了解决以上问题,我们引入了另一种数据结构“链表”。

本文会详细介绍链表的概念和代码实现。

二、链表的概念

链表和顺序表一样,也是线性表的一种。链表在逻辑结构上是线性的,而在物理结构上不是线性的。

链表由一个一个的节点组成。每个节点由两部分组成,一是这个节点存储的数据,二是指向下一个节点的指针。

那么我们只需定义每个节点的结构,把它们连接起来就可以形成链表了。根据上面的描述我们可以知道,我们定义的表示的节点结构体应该有两个成员:(以存储整型数据为例)一个整型数据data和一个指向下一个节点的结构体指针。

理解了链表的概念,接下来我们就可以着手写代码去实现它了。

三、代码实现

3.1 创建文件

SList.h用来定义节点结构体和链表的各种功能,SList.c用来实现各种功能,test.c用来测试。

3.2 定义节点结构体
//SList.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

//定义节点的结构
typedef struct SListNode
{
	int data;
	struct SListNode* next;
}SLTNode;

创建好这个结构体,我们在test.c文件中用它来创建一个链表。

我们创建四个节点,它们的指针分别是node1、node2、node3、node4。我们用malloc给这四个节点分别开辟一块空间,在四个节点里分别放入1、2、3、4这四个整型数据。

最后我们让每个节点中的结构体指针成员指向下一个节点,就得到了一个完整的链表。

//test.c
void SListTest01()
{
	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;
}

int main()
{
	SListTest01();
}
3.3 功能实现
3.3.1 打印链表

由于实现和测试后续功能的过程中我们肯定需要频繁打印链表的内容,所以我们在此处写一个函数来实现打印链表的功能。

void SLTPrint(SLTNode* phead)
{
	SLTNode* pcur = phead;
	while (pcur)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("NULL\n");
}

此处我们创建了一个临时的指针变量pcur,让它顺着链表移动,就可以打印出链表的所有元素了。

测试一下。

我们创建一个指向头结点的指针变量,把它传给SLTPrint。

3.3.2 尾部插入

现在我们实现的各种功能都以int类型数据为例。为了使链表能够存储更多类型的数据,我们使用typedef将int类型重新定义为SLTDataType,这样以后一次修改,全局生效。

typedef int SLTDataType;

typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

现在我们来实现尾部插入功能。

我们只需创建一个新的节点,找到尾节点,让尾结点中的结构体指针指向新节点,就完成了尾插。

我们此时意识到“创建一个新的节点”在后续的操作中肯定是一个常见的操作。所以我们把它拎出来,专门写一个函数来实现这个功能。

SLTNode* SLTBuyNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc failed!");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;

	return newnode;
}

现在我们可以用这个函数来实现尾插功能了。

需要特别注意的是,此处我们想用形参改变实参,需要传址调用,函数的参数应该为二级指针。

void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
    assert(pphead);
	SLTNode* newnode = SLTBuyNode(x);
	SLTNode* ptail = *pphead;
	while (ptail->next != NULL)
	{
		ptail = ptail->next;
	}
	ptail->next = newnode;
}

此处还需要注意,链表可能为空,此时phead为空指针,那么上述代码中对ptail解引用的语句就会报错。所以我们需要将这种情况拎出来专门讨论。

这种情况下我们只需创建一个新节点,然后让phead指向这个新节点即可。完整的代码如下:

void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
    assert(pphead);
	SLTNode* newnode = SLTBuyNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		SLTNode* ptail = *pphead;
		while (ptail->next != NULL)
		{
			ptail = ptail->next;
		}
		ptail->next = newnode;
	}
}

测试一下这个功能:

3.3.3 头部插入

我们只需创建一个新的节点,让新节点中的next指向现有链表的头结点,再让新的节点成为头结点即可。如果操作的链表为空,那么就把新节点中的next直接置为空,不需要特别处理。

void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = SLTBuyNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

测试一下:

3.3.4 尾部删除

这里需要分成“链表只有一个节点”和“链表有两个及以上的节点”两种情况来考虑。

当链表只有一个节点的时候,我们只需用free将这一个节点释放即可。

当链表有多个节点的时候,我们需要先用循环找到最后一个节点和倒数第二个节点,将最后一个节点释放,将倒数第二个节点的next置为空。

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;
	}
}

测试一下这个功能:

3.3.5 头部删除

我们只需要将第一个节点释放即可。但是如果直接释放,我们就无法找到第二个节点的位置。所以我们要创建一个临时变量,存储一下第二个节点的地址。

void SLTPopFront(SLTNode** pphead)
{
	//链表不能为空
	assert(pphead && *pphead);
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

考虑一下链表只有一个元素的情况:此时上述代码依然适用,不需要特别处理。

测试一下:

3.3.6 查找

我们只需遍历链表中的所有元素,找到需要查找的数据后返回其节点的指针,没找到返回NULL即可。

此处我们只是要查找数据,不需要改变链表,所以传参传一级指针就好。

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

测试一下:

3.3.7 指定位置之前插入

这个函数需要三个参数:链表头结点的二级指针、指定位置的地址、需要插入的数据。

首先我们用SLTBuynode创建一个新的节点。

然后我们需要找到指定位置的前一个节点,让这个节点的next指向新节点,再让新节点的next指向指定位置的节点,这样我们就把一个新的节点插入到了指定位置的前面。

按照上面的思路我们可以写出以下代码:

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead && *pphead);
	assert(pos);
	SLTNode* newnode = SLTBuyNode(x);

	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	newnode->next = pos;
	prev->next = newnode;
}

但此时我们考虑一下特殊情况:

如果指定位置就是链表的头节点,那么prev和pos都指向头结点。prev->next不等于pos,prev往后走一个节点;此时prev->next仍然不等于pos,prev继续往后走一个节点。就这样循环,当prev走到最后一个节点的时候,会出现对空指针的解引用,代码报错。这显然无法满足我们的需求。

所以我们需要单独处理这种情况。在头结点之前插入数据,我们只要调用一下头部插入的函数即可。修改后的代码如下:

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead && *pphead);
	assert(pos);
	SLTNode* newnode = SLTBuyNode(x);

	if (pos == *pphead)
	{
		SLTPushFront(pphead, x);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		newnode->next = pos;
		prev->next = newnode;
	}
}

测试一下:

测试在头结点前面插入数据的特殊情况:

3.3.8 指定位置之后插入

在指定位置之后插入数据,我们只需要两个参数:指定位置的地址和要插入的数据。

为什么不需要头结点的二级指针了呢?

刚才的指定位置之前插入,我们需要找到指定位置之前的节点。我们无法从指定位置向前找到它的前一个节点,因此需要从头节点开始找。

但是要找指定位置的后一个节点是很方便的,我们只需要用一下指定位置节点的next就可以了。所以在指定位置之后插入数据,我们用不到头结点的二级指针。

那么接下来着手实现这个功能。

我们只需调用SLTBuyNode创建一个新的节点,然后让指定位置节点的next指向新节点,让新节点的next指向指定位置之后的节点即可。

需要注意的是,如果我们先改变指定位置节点的next,就找不到原来链表中排在指定位置之后的节点了。所以我们要先改变新节点的next,再让指定位置节点的next指向指定位置之后的节点。

void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = SLTBuyNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

考虑一下特殊情况:如果指定位置是原链表的最后一个节点,上述代码依然适用,不需要特别处理。

测试一下:

3.3.9 指定位置删除

这个函数需要两个参数:头结点的二级指针(因为我们需要寻找指定位置的前一个节点)和指定位置。

我们只需让指定位置前一个节点的的next指向指定位置后一个节点,再把指定位置的节点释放掉即可。

考虑特殊情况:和头部删除时遇到的问题一样,如果指定位置就是头结点,需要特别处理。

void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead && *pphead);
	assert(pos);

	if (pos = *pphead)
	{
		SLTPopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

测试一下:

3.3.10 指定位置之后删除

实现指定位置之后删除的时候,如果我们直接让指定位置节点的next指向要删除的节点的下一个节点,就找不到要删除的那个节点的地址了。所以我们要设置临时变量。

void SLTEraseAfter(SLTNode* pos)
{
	assert(pos && pos->next);
	SLTNode* del = pos->next;
	pos->next = del->next;
	free(del);
	del = NULL;
}

测试一下:

3.3.11 销毁链表

销毁链表时要从头结点开始,顺着链表一个节点一个节点往后删除。

在删除每个节点的时候,要注意用临时变量保存一下下一个节点的地址,否则删除当前节点后就找不到下一个节点了。

最后要把指向头结点的指针置为空。

void SListDestroy(SLTNode** pphead)
{
	assert(pphead && *pphead);

	SLTNode* pcur = *pphead;
	while (pcur)
	{
		SLTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	*pphead = NULL;
}

测试一下:

现在我们已经实现了链表的全部功能。

从以上这些功能的实现过程中我们可以看出,链表与顺序表相比,插入数据时不需要移动数据,也不需要用realloc扩容,进而避免了浪费空间的问题以及realloc所带来的性能消耗。不过,链表也有缺陷:它无法通过下标来随机访问。顺序表适合元素高效存储和频繁访问,链表则适用于需要在任意位置频繁插入和删除的场景。两者是“互补”的数据结构。

END

【C语言】链表 本篇文章将详细讲到有关链表的概念,链表节点,链表分类,链表的基本操作包括初始化链表,遍历链表,插入节点,删除节点,清空链表,销毁链表。 阅读详情

相关推荐

C语言链表操作详解

为什么要使用链表 在未学习链表时,我们常用的存储数据的方式无非就是数组。使用数组存储数据的好处就是查询快,但是它的弊端也很明显: 使用前需声明数组的长度,一旦声明长度就不能更改 插入和删除操作需要移动大量的数组元素,效率慢 只能存储一种类型的数据. 而链表则可以实现以上这些数组所不具备的功能,此时引入了结构体来实现创建链表的操作。 链表的特点: n个节点离散分配 每一个节...

qq_41481924的博客 14万+

双向链表:概念解析与C语言代码实现

介绍了双向链表的概念和C语言代码实现

dev_jin的博客 715

【C语言】深入浅出:C语言链表的全面解析

全面剖析C语言链表:单链表、双向链表、循环链表

LuckiBit 2242

C语言链表相关问题:

文章目录链表简述计算与指定数字相同的数的个数 链表简述 链表是通过指向结构的指针把自定义的结构类型结点串连起来,形成复杂数据存储模式。下图给出了链表的图形模拟: head的值为第一个结点的地址,链表以结点为单位进行连接,在C语言中,我们用一个结构体类型表示这个结点 typedef struct node { int data;//数据域 struct node* next;//指针域 } ...

weixin_42124234的博客 316

Maya ACES工作流程配置(Arnold 及 RedShift 贴图配置规范-还原出SP-Aces流程下贴图正确的效果) PS还原Aces流程下渲染的图

*如果使用SP,项目工程如果新建的时候设置的就是Aces的流程的话,按规范正常导出即可,贴图会带上相对应的后缀,然后贴图导入材质球的时候会根据后缀自动设置相对应的色彩空间;**万一不是,就自己手动设置一下对应的色彩空间即可;然后点击选择当前的或者选择全部导入的贴图,点击右下角后,开始转换;我复制了一下,一个默认没有LUT的效果,然后另外一个是加载2个LUT后的还原效果,和渲染的效果应该是没有区别的,至少我没有看出明显的区别;把需要转换的贴图拖拽到左侧,然后右面选择需要转换到的相对应的色彩空间;...

Yuulily 7993

硬件即代码:用软件工程思维拆解F450无人机装配的模块化设计哲学

本文探讨了如何用软件工程思维重构DJI-F450无人机的模块化设计,将硬件装配提升为可编程系统。通过硬件抽象层、控制系统分层架构和扩展槽位设计模式,展示了无人机装配的模块化哲学,并结合实际案例说明如何优化性能与安全性。

weixin_29294975的博客 386

数据结构C语言——队列的实现(数组、链表)

3 队列 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最...

baidu_39049318的博客 1297

20个闭环渗透测试项目:从漏洞发现到简历突围

渗透测试不仅是工具使用,更是对系统设计缺陷与实现偏差的深度推演。理解OWASP Top 10、Burp Suite等基础能力只是起点,真正具备工程价值的是能复现、可验证、可协作的完整攻击链。本文聚焦真实业务场景下的SSRF协议绕过、JWT签名机制缺陷、Redis未授权利用、Kong网关配置风险及etcd存储结构分析等核心热词,揭示漏洞本质在于架构决策与配置偏差的叠加态。适用于红队实战、甲方安全建设与乙方渗透审计等多类岗位,帮助从业者将技术动作升维为技术叙事。

weixin_32234493的博客 414

简洁且简单的去理解链表

简单数据结构—链表 目录: 一、链表理解及图示 二、链表的简单构造和代码实现 刚刚开始学习简单数据结构,看了许多大佬的链表仍然不是很懂,仔细想过之后终于明白,当作笔记记录一下 Ⅰ.链表理解: ①链表概念: 通俗意义上讲,链表就是链接起各个存储空间的线性表,特点就是单向链接可以逐级遍历(单项),一级一级将数据串联起来,使得数据具有连续性,但连续性为抽象上的连续而不是物理上的连续,例如第一个的内存空...

EightOsProj的博客 256

合宙ESP32C3实战:MPU6500六轴传感器数据读取与校准全解析

本文详细解析了如何使用合宙ESP32C3开发板读取和校准MPU6500六轴姿态传感器数据。从硬件接线、开发环境搭建到核心代码解析,提供了全面的实战指南,帮助开发者快速掌握传感器配置与数据处理技巧,适用于姿态控制、运动检测等应用场景。

weixin_27066963的博客 405

用LT1166+MOS管打造实验室级恒流源:闭环反馈与推挽驱动的深度调优

本文详细介绍了基于LT1166电流模式控制器与MOS管推挽架构的实验室级恒流源设计方法。通过闭环反馈调优和动态响应优化,实现带宽达100kHz、纹波低于0.1%的高性能恒流输出,适用于精密仪器校准和半导体测试等场景。重点解析了系统架构设计、MOS管选型策略以及频率响应测试等关键技术要点。

weixin_29290379的博客 205

C,C++单链表基本操作的实现

单链表的定义和表示 对于每一个数据元素 a1,除了要存储本身信息外,还要存储下一个数据元素的地址。这里就要用到结构指针。这两部分信息组成的数据元素 a1 的存储映像,称为结点,存储信息的域称为数据域;存储直接后继存储位置的称为指针域。指针域中存储的信息称作指针和链。n 个结点的链结成一个链表,即为线性表。 特点:用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)...

m0_46168903的博客 1820

一文读懂 CST 时/频域求解器

本文系统介绍了CST Studio Suite中的关键网格技术——六面体网格、四面体网格以及TLM求解器专用的八叉树非均匀网格技术。重点阐述了六面体网格的三项核心技术:理想边界拟合(PBA)技术可精确处理曲面边界,薄片技术(TST)能高效模拟薄层结构,自适应八叉树网格实现计算资源最优分配。同时详细对比了六面体网格与四面体网格的特点及适用场景,前者适用于系统级EMC/EMI分析等时域问题,后者擅长处理复杂曲面和异质材料的频域问题。

一只豌豆象的博客 464

C语言创建单链表

单链表 链表节点结构体 struct node { char name[10]; float score; } typedef struct node { struct node; struct node*next; }LinkList; 初始化一个链表 void InitLinkList(LinkList*&L) { L=malloc(sizeof(LinkList))...

BShanj的博客 4万+

Unlocking Decoding-time Controllability: Gradient-FreeMulti-Objective Alignment with Contrastive Pr

将基于庞大网络语料库训练的大型语言模型(LLMs)(OpenAI,2023;Touvron 等,2023;Google,2023)与人类偏好对齐,是减少产生不安全(Wei 等,2023)、幻觉(Zhang 等,2023b)和有偏见(Gallegos 等,2023)内容的重要一步。随着偏好学习技术(如 PPO(Schulman 等,2017)、DPO(Rafailov 等,2023)及其他变体(Azar 等,2023;Ethayarajh 等,2024;

qq_52053775的博客 1169

AI原生应用评测:主流大语言模型性能对比

任务适配性:是否匹配应用的核心任务(如代码生成需强逻辑推理,内容创作需强创意性);上下文能力:处理长序列(如10万+字文档)的理解与生成能力;可靠性:幻觉(Hallucination)率、事实准确性、安全合规性;性价比:API调用成本、延迟、 scalability(扩展能力)。AI原生应用的核心是LLM与应用场景的深度协同。

架构师的AI之路,分享AI应用开发架构的学习与实践。 507

C语言 链表逆置四种方法 超详细

链表逆置 C语言 创建所需的相关结构体 struct List { int date; struct List* next; }; 首先我们创建一个函数用于创建链表的。 建立创建链表的函数 struct List* writeList() { struct List* head = NULL, * current = NULL, * prev = NULL; int data; while (~scanf("%d", &data) && data != 0)//0为标记输

qascetic的博客 3万+

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

C语言链表

C语言链表链表的概念及结构概念结构链表的分类链表的实现双向链表的实现总结:链表和顺序表的区别 链表的概念及结构 概念 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。 结构 代码 struct Slist { int* a; struct Slist* next; }; 逻辑结构: 物理结构: 链表的分类 链表的实现 双向链表的实现 总结:链表和顺序表的区别 ...

qq_29468639的博客 1万+

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【C语言】 链表 超详细解析

【C语言】 链表 超详细解析

m0_56051805的博客 1万+

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C语言写链表思路及步骤详解

本人已经大二,大一第一学期就学习了C语言,链表也是那时候就学了。对于学过链表的人来说,很简单;但对于没学过的人来说,觉得概念很难理解。想起以前学习的过程,自学时在网上搜到的讲解,要么只讲代码,要么讲的思路很难理。为了赚积分升二级拿模板,从初学者的角度出发慢慢讲解,慢慢看。如有大神路过看见有误,还请大神指点一二。 1.重温结构体 我想既然你接触了指针,那就一定学过结构体了。下面定义了一个结构体,ty...

名狱的博客 3528

深度解析:全面掌握C语言链表的原理与应用

链表(Linked List)是一种线性数据结构,其中的元素通过指针或引用链接在一起。每个元素称为节点(Node),每个节点包含两部分:数据域(Data Field)和指针域(Pointer Field)。数据域用于存储实际数据,而指针域则用于指向链表中的下一个节点。在 C 语言中,可以使用结构体来定义链表节点。每个节点包含一个数据域和一个指针域。int data;// 数据域// 指针域} Node;int data;} DNode;int data;} CNode;

极客代码 1933

C语言链表详解

文章目录C语言链表详解链表基础链表的优点基本概念创建链表定义一个结构体创建一个链表插入节点删除节点修改节点输出节点完整代码 C语言链表详解 链表基础 链表的优点 n个节点离散分配 每一个节点之间通过指针相连 每一个节点有一个前驱节点和一个后继节点 首节点没有前驱节点,尾节点没有后继节点 基本概念 首节点:存放第一个有效数据的节点 头节点:在单链表的第一个结点之前附设一个结点,它没有直接前驱,称之为头结点,头结点的数据域可以不存储任何信息,指针域指向第一个节点(首节点)的地址。头结点的作用是使所有

一顿吃不饱的博客 9769

【数据结构】---单链表【C语言实现】

1. 单向链表 我们都熟悉数组,它作为一个顺序储存方式数据结构为我们的程序设计带来了大量的便利,几乎任何的高级程序设计,算法设计都离不开数组的灵活使用。 但是,数组最大的缺点就是我们的插入和删除时需要移动大量的元素,显然这需要消耗大量的时间。 数组找到指定元素很快,O(1)复杂度就可以,而链表只能是遍历,O(n)的复杂度。 数组是顺序存储的,链表是通过指针实现不连续的存储 相比起数组,链表解决了数组不方便移动,插入,删除元素的弊端,但相应的,链表付出了更加大的内存牺牲换来的这些功能的实现。 ...

mike_jun的博客 4709

C语言实现单链表

C语言实现单链表,详细图解让你更深层次的了解。

qq_43629857的博客 1万+

C语言实现链表(链式存储结构)

链表(链式存储结构)及创建 链表,别名链式存储结构或单链表,用于存储逻辑关系为 “一对一” 的数据。与顺序表不同,链表不限制数据的物理存储状态,换句话说,使用链表存储的数据元素,其物理存储位置是随机的。 例如,使用链表存储 {1,2,3},数据的物理存储状态如下图所示: 我们看到,上图 根本无法体现出各数据之间的逻辑关系。对此,链表的解决方案是,每个数据元素在存储时都配备一个指针,用于指向自己的...

BeiXi's Blog 4425

双链表及C语言实现

本博文介绍双链表,及其C语言的实现 目录双链表双链表的操作插入头节点插入尾节点插入指定位置插入删除头节点删除尾节点删除指定位置删除搜索遍历双链表的C语言实现 双链表 双链表的操作 插入 头节点插入 尾节点插入 指定位置插入 删除 头节点删除 尾节点删除 指定位置删除 搜索 遍历 双链表的C语言实现 才疏学浅,难免有错误和不当之处,欢迎交流批评指正! 同时有问题的话欢迎留言或邮箱联系(ljt_IT@163.com)。 创作不易,觉得写得不错就微信扫码奖励一下吧! ...

Jeaten 1777
上一篇: 用双指针法解决两道顺序表基础算法题(LeetCode 27 & 88)
下一篇: Python基础语法(1)
jinyishu_
博客等级 码龄1年 54粉丝 83原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值