带头双向循环链表各种接口的实现(C)

《AI应用架构师必学:企业AI能力地图构建的高级技巧》 企业AI能力地图,简单来说,是一种可视化工具,它展示了企业在AI领域所具备的各种能力及其相互关系。就如同城市地图展示城市的街道、建筑和设施一样,AI能力地图呈现了企业在数据处理、模型开发、算法应用等多个方面的能力布局。 阅读详情

链表分类

单向或双向
![[Pasted image 20240918102853.png]]
带头或不带头
![[Pasted image 20240918102902.png]]
循环或非循环
![[Pasted image 20240918102912.png]]
合计有八种

带头双向循环链表

![[Pasted image 20240918103005.png]]
结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。使用代码实现,结构会带来很多优势,实现反而简单了。
![[Pasted image 20240918222332.png]]

创建新节点
LTNode* BuyNode(LTDataType x)
{
	LTNode* node = (LTNode*)malloc(sizeof(LTNode));
	if (node == NULL)
	{
		perror("malloc fail");
		exit(-1);	
	}

	node->data = x;
	node->next = NULL;
	node->prev = NULL;

	return node;
}
初始化
LTNode* LTInit()
{
	LTNode* phead = BuyLTNode(-1);
	phead->next = phead;
	phead->prev = phead;
	return phead;
}

初始化会修改结构体的内容,所以需要结构体指针,也可以用返回值来解决

  1. 通过BuyLTNode创建一个新节点
  2. 将phead节点的next指向自己
  3. prev指向自己
    ![[Pasted image 20240918222347.png]]
打印链表
void LTPrint(LTNode* phead)
{
	assert(phead);

	printf("phead<=>");
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		printf("%d<=>", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

通过assert断言,判断phead是否合法

  1. 创建一个cur结构体指针,把phead->next赋给cur,也就是cur指向第一个节点
    ![[Pasted image 20240918223548.png]]

  2. 把cur->next赋给cur,也就是cur指向cur的下一个节点,循环遍历直到cur等于头节点停止
    ![[Pasted image 20240918223700.png]]

只有头节点就不进入循环

尾插

尾插的时候不需要找尾节点,双向循环链表,头节点的prev指向尾节点,尾节点的next指向头节点
tail的next指向newnode,newnode的prev指向tail,newnode的next指向phead,phead的prev指向newnode

void LTPushBack(LTNode* phead, LTDataType x)
{
	assert(phead);

	LTNode* tail = phead->prev;
	LTNode* newnode = BuyLTNode(x);

	newndode->prev = tail;
	tail->next = newnode;
	
	newnode->next = phead;
	phead->prev = newnode;

}

通过assert判断phead指针是否为空

  1. 创建tail指针,通过phead的prev指针,找到最后一个节点
    ![[Pasted image 20240918224853.png]]

  2. 通过BuyLTNode,malloc一个新的链表节点
    ![[Pasted image 20240918224946.png]]

  3. 将newnode节点与tail节点连接,将newnode的prev指向tail,tail的next指向newnode
    ![[Pasted image 20240918225816.png]]

  4. 将newnode节点与phead节点连接,将newnode的next指向phead,phead的prev指向newnode
    ![[Pasted image 20240918225944.png]]

只有一个头节点的情况:

  1. 创建tail指针,malloc新节点
    ![[Pasted image 20240919082022.png]]

  2. tail和phead是同一个节点,直接连接
    ![[Pasted image 20240919082247.png]]

尾删
void LTPopBack(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);

	LTNode* tail = phead->prev;
	LTNode* tailPrev = tail->prev;
	free(tail);
	
	tailPrev->next = phead;
	phead->prev = tailPrev;
	
}

通过assert判断phead是否为空,是否只有phead一个节点,是个空链表

  1. 创建tail节点,通过phead->prev,找到最后一个节点
    ![[Pasted image 20240919082749.png]]

  2. 创建tailPrev节点,通过tail->prev,找到倒数第二个节点
    ![[Pasted image 20240919082824.png]]

  3. 释放tial节点
    ![[Pasted image 20240919082850.png]]

  4. 连接tailPrev节点和phead
    ![[Pasted image 20240919082931.png]]

头插
void LTPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);

	LTNode* newnode = BuyLTNode(x);

	newnode->next = phead->next;
	phead->next->prev = newnode;

	phead->next = newnode;
	newnode->prev = phead;
}

先将newnode连接到第一个节点,再连接头节点和新节点newnode,不能更改顺序,否则会丢掉后面的链表
头插是在第一个节点的前面插入,不是在哨兵位的前面插入
通过assert判断phead是否为空

  1. 创建一个newnode节点
    ![[Pasted image 20240919083214.png]]

  2. 将newnode与第一个节点连接
    ![[Pasted image 20240919083421.png]]

  3. 将newnode与phead
    ![[Pasted image 20240919083455.png]]

只有一个phead节点的情况
由于phead和phead->prev是同一个节点,所以直接连接phead和newnode节点

  1. 创建一个newnode节点
    ![[Pasted image 20240919083832.png]]

  2. newnode的next指向phead,phead的prev指向newnode
    ![[Pasted image 20240919084009.png]]

  3. phead的next指向newnode,newnode的prev指向phead
    ![[Pasted image 20240919084133.png]]

通过创建一个first节点来代表第一个节点,这样连接就不用在意连接顺序,不怕丢掉后续链表

void LTPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);

	LTNode* newnode = BuyLTNode(x);
	LTNode* first = phead->next;

	phead->next = newnode;
	newnode->prev = phead;
	newnode->next = first;
	first->prev = newnode;
	
}
  1. 创建newnode和first,将phead->next赋给first,first指向第一个节点
    ![[Pasted image 20240919084316.png]]

  2. 再继续连接phead和newnode,newnode和first,同上

头删
void LTPopFront(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);

	LTNode* first = phead->next;
	LTNode* second = first->next;

	free(first);

	phead->next = second;
	second->prev = phead;
}

通过assert判断phead是否为空,是否为空链表

  1. 创建first和second指针,分别指向第一个和第二个节点
    ![[Pasted image 20240919084535.png]]

  2. 释放掉first,连接phead和second
    ![[Pasted image 20240919084635.png]]

返回大小
int LTSize(LTNode* phead)
{
	assert(phead);

	LTNode* cur = phead->next;
	while (cur != phead)
	{
		++size;
		cur = cur->next;
	}
	return size;
}
  1. assert判断phead是否合法
  2. 通过cur指针遍历链表
  3. 每遍历一个节点,size++,直到cur为phead
  4. 最后返回size
    可以在哨兵位节点的data里存放size,插入时data++,删除时data–,求大小时,直接返回phead的data
    但是只有确定链表的data数据类型是int才可以使用,其他数据类型无法实现
    如果真要用size来记录,应该在函数外定义
查找x
LTNode* LTFind(LTNode* phead, LTDataType x)
{
	assert(phead);

	STNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
			return cur;

		cur = cur->next;
	}

	return NULL;	
}
  1. 通过assert判断phead是否为空
  2. 通过cur指针遍历链表
  3. 当cur指向节点的data等于x,返回cur指针
  4. 如果没找到,返回NULL
pos之前插入x
void LTInsert(LTNode* pos, LTDataType x)
{
	assert(pos);

	LTNode* posPrev = pos->prev;
	LTNode* newnode = BuyLTNode(x);

	posPrev->next = newnode;
	newnode->prev = posPrev; 
	newnode->next = pos;
	pos->prev = newnode;
}
  1. assert判断pos指针是否合法

  2. 将pos->prev赋给posPrev指针,找到pos前一个节点

  3. newnode一个节点
    ![[Pasted image 20240919085232.png]]

  4. 连接newnode与posPrev节点
    ![[Pasted image 20240919085315.png]]

  5. 连接pos和newnode
    ![[Pasted image 20240919085356.png]]

之前的头插尾插都可以用Insert复用

	LTInsert(phead->next, x);   //头插
	LTInsert(phead, x);         //尾插
删除pos位置
void LTErase(LTNode* pos)
{
	assert(pos);
	
	LTNode* posPrev = pos->prev;
	LTNode* posNext = pos->next;

	free(pos);

	posPrev->next = posNext;
	posNext->prev = posPrev;
}
  1. assert判断pos是否为空

  2. 创建posPrev和posNext找到pos前一个和后一个节点
    ![[Pasted image 20240919085552.png]]

  3. 释放掉pos
    ![[Pasted image 20240919085609.png]]

  4. 连接posPrev和posNext
    ![[Pasted image 20240919085627.png]]

	LTErase(phead->next);    //头删
	LTErase(phead->prev);    //尾删
销毁
void LTDestroy(LTNode* phead)
{
	assert(phead);

	STNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;
		free(cur);
		
		cur = next;
	}

	free(phead);
	
}
  1. assert判断phead是否为空
  2. 通过cur指针遍历整个链表
  3. 每次循环,创建一个next指针,指向cur节点的下一个,释放掉cur节点,将cur指针指向next,当cur为phead时结束
  4. 最后释放掉phead节点
    函数内没有用到二级指针,形参不能改变实参,可以在函数外调用后再phead置空

顺序表和链表的区别

![[Pasted image 20240918215558.png]]

![[Pasted image 20240918220042.png]]

存储器层次结构

声明定义分离实现

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int LTDataType;
typedef struct ListNode
{
	struct ListNode* next;
	struct ListNode* prev;
	LTDataType data;
}LTNode;

LTNode* BuyNode(LTDataType x);
LTNode* LTInit();
void LTPrint(LTNode* phead);
void LTPushBack(LTNode* phead, LTDataType x);
void LTPopBack(LTNode* phead);
void LTPushFront(LTNode* phead, LTDataType x);
void LTPopFront(LTNode* phead);
int LTSize(LTNode* phead);
//pos之前插入xLTNode* LTFind(LTNode* phead, LTDataType x);
void LTInsert(LTNode* pos, LTDataType x);
//删除pos位置
void LTErase(LTNode* pos);
void LTDestroy(LTNode* phead);
include "List.h"

LTNode* BuyNode(LTDataType x)
{
	LTNode* node = (LTNode*)malloc(sizeof(LTNode));
	if (node == NULL)
	{
		perror("malloc fail");
		exit(-1);	
	}

	node->data = x;
	node->next = NULL;
	node->prev = NULL;

	return node;
}

LTNode* LTInit()
{
	LTNode* phead = BuyLTNode(-1);
	phead->next = phead;
	phead->prev = phead;
	return phead;
}

void LTPrint(LTNode* phead)
{
	assert(phead);

	printf("phead<=>");
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		printf("%d<=>", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

void LTPushBack(LTNode* phead, LTDataType x)
{
	assert(phead);

	LTNode* tail = phead->prev;
	LTNode* newnode = BuyLTNode(x);

	newndode->prev = tail;
	tail->next = newnode;
	
	newnode->next = phead;
	phead->prev = newnode;
}

void LTPopBack(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);

	LTNode* tail = phead->prev;
	LTNode* tailPrev = tail->prev;
	free(tail);
	
	tailPrev->next = phead;
	phead->prev = tailPrev;
	
}

void LTPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);

	LTNode* newnode = BuyLTNode(x);

	newnode->next = phead->next;
	phead->next->prev = newnode;

	phead->next = newnode;
	newnode->prev = phead;
}

void LTPopFront(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);

	LTNode* first = phead->next;
	LTNode* second = first->next;

	free(first);

	phead->next = second;
	second->prev = phead;
}

int LTSize(LTNode* phead)
{
	assert(phead);

	LTNode* cur = phead->next;
	while (cur != phead)
	{
		++size;
		cur = cur->next;
	}
	return size;
}

LTNode* LTFind(LTNode* phead, LTDataType x)
{
	assert(phead);

	STNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
			return cur;

		cur = cur->next;
	}

	return NULL;	
}

void LTInsert(LTNode* pos, LTDataType x)
{
	assert(pos);

	LTNode* posPrev = pos->prev;
	LTNode* newnode = BuyLTNode(x);

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

void LTErase(LTNode* pos)
{
	assert(pos);
	
	LTNode* posPrev = pos->prev;
	LTNode* posNext = pos->next;

	free(pos);

	posPrev->next = posNext;
	posNext->prev = posPrev;
}

void LTDestroy(LTNode* phead)
{
	assert(phead);

	STNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;
		free(cur);
		
		cur = next;
	}

	free(phead);
	
}
面经-2023-联发科MTK-数字芯片设计 阅读详情

相关推荐

48V电气架构全面科普和解析:下一代智能电动汽车核心驱动

随着电动汽车(EV)技术的不断发展,传统的12V电力系统已经逐渐无法满足日益增长的功率需求,尤其是在电动汽车中,48V电气系统的引入成为了一种理想的解决方案。在电动汽车中,48V系统与Zonal架构的结合,不仅有效提升了车辆电力系统的能效,还为未来的技术升级提供了灵活的设计基础。随着电动汽车(EV)技术的发展,车辆电气系统的工作电压逐步从传统的12V系统向更高的电压过渡。随着电动汽车技术的不断进步,传统的12V电气系统逐渐无法满足现代高性能电动汽车的需求,而48V电力系统的引入成为一种理想的解决方案。

weixin_43199439的博客 7810

【C语言】带头双向循环链表实现及接口解析~

在上一篇博文中,我详细地讲解了无头单向不循环链表的实现,也提到了链表有八种分类,那么难道每种分类都要去学一遍吗?并不是的!我们只需要学习其中最常用的两种链表即可,即是上篇的无头单向不循环链表与本篇的带头双向循环链表,简称单链表与双链表,当我们将这两种链表掌握之后,自然就能独立实现其它链表了。话不多说,直接开始进入正文吧!目录前言(1)带头(2)循环(3)双链表双链表的结构双链表的实现(1)头文件实现1))创建单个双链表节点结构2))接口声明(2)源文件1))初始化链表2)) 打印链表3))尾插。

careathers的博客 268

别再瞎猜了!三角形接法PMSM的相电流到底怎么算?实测线电流转换公式与避坑指南

本文深入解析三角形接法永磁同步电机(PMSM)在FOC控制中的相电流计算误区,提供实测线电流转换公式与避坑指南。针对矢量控制系统中常见的√3换算错误,详细阐述正确的电流重构算法、硬件采样要点及软件优化技巧,帮助工程师实现精确控制并避免电机损坏。

weixin_30367873的博客 466

(C语言)实现带头双向循环链表的接口

各函数功能如下 申请空间 ListNode* BuyListNode(LTDataType x) { ListNode* node = (ListNode*)malloc(sizeof(ListNode)); node->next = NULL; node->prev = NULL; node->data = x; return node; } 初始化 ListNode* ListInit() { ListNode* phead = BuyListNode(0); phea

weixin_45266788的博客 400

Unity游戏开发客户端Unity基础

Unity游戏开发客户端面经 之 Unity 篇

Sea3752的博客 2万+

深入IR2104数据手册:被忽略的SD引脚用法和死区时间调节实战

本文深入解析IR2104半桥驱动芯片的SD引脚用法和死区时间调节技巧,帮助硬件工程师优化电机控制和电源转换系统。通过详细的电路设计、实测数据和调试方法,揭示SD引脚的多重保护机制和死区时间的精密调节策略,提升系统安全性和效率。

weixin_30342363的博客 391

数据结构——单向链表和双向链表的实现(C语言版)

这篇文章关于链表的介绍,还有单向链表和双向链表的C语言实现,内容干货满满,建议边看边上手敲代码!通过这篇文章,相信你已经对链表这个数据结构有了一定的了解,可以开始刷一些链表的OJ题目。如果只是看了一遍,建议上手敲敲代码,实践出真知。创作不易,希望这篇文章能给你带来启发和帮助,如果喜欢这篇文章,请留下你的三连哦,你的支持的我最大的动力!!!

2301_79171011的博客 3798

LWIP协议栈在STM32H7上的内存优化实战:如何用32KB RAM实现稳定千兆以太网通信

本文深入探讨了在STM32H7微控制器上,如何通过内存优化策略,在仅32KB的D2 SRAM中稳定运行LWIP协议栈以实现千兆以太网通信。文章详细分析了STM32H7的内存架构、LWIP的内存消耗瓶颈,并提供了从描述符表与PBUF池精确分配、链接脚本修改到MPU区域划分的一整套实战优化方案,旨在解决大数据量传输卡死等常见配置问题。

gg901的博客 603

外强中干——双向带头循环链表

听着名字或许挺唬人的,但实际上双向带头循环链表实现起来比结构最简单的单向不带头不循环链表简单的多,是个“外强中干”的链表。

qq_73390155的博客 1093

tkinter动态表格 - 实时更新数据(TkinterTable)

tkinter动态表格 - 实时更新数据(TkinterTable) 参考 [TkinterTable] Tkinter上的表格GUI】 https://github.com/dmnfarrell/tkintertable/wiki/Usage https://github.com/dmnfarrell/tkintertable/issues/47 python使用tkinter编写一个数据显示窗口(实时显示更新的数据) 首先安装TkinterTable,即pip install tki

qq_33934427的博客 1万+

TMC2240 芯片数据手册解读|第十三篇 StallGuard4负载测量(StallGuard4 Load Measurement)

摘要: TMC2240的StallGuard4技术专为StealthChop2静音模式设计,通过SG4_RESULT实时测量电机负载,实现堵转检测、无传感器回零和CoolStep节能。其核心原理基于负载角检测,通过SG4_THRS阈值调节灵敏度,并支持四通道独立测量(SG4_IND_0~3)优化相位平衡。独特功能包括无抖动模式切换补偿(sg_angle_offset),解决StealthChop2与SpreadCycle切换时的电流突变问题。调优时需结合SG4_THRS设定与DIAG验证,确保堵转精准触发。

BackCatK Chen的博客 302

初阶数据结构(C语言实现)——3.4带头双向循环链表详解(定义、增、删、查、改)

学习带头双向循环链表之前,建议先学习下顺序表,和单向不带头不循环链表。这是博主之前的文章,欢迎学习交流。

graceyun的博客 1427

PX4从放弃到精通(二十二):日志

文章目录前言一、下载日志二、ulog转CSV三、利用flightplot软件分析PX4的ulog日志1 windos安装2 ubuntu18.04安装四、使用PlotJuggler分析PX4日志五、设置日志记录条件六、添加自定义日志消息 前言 PX4 1.10以上固件 QGC 一、下载日志 将飞控链接地面站,在下图页面点击“刷新”,即可看到保存的日志(前提是要有TF卡) 选择需要下载的日志,点击右侧的“下载”,然后选择目录即可进行下载,如果想擦除所有的日志,可以点击右侧的“擦除全部” 二、ulog转CS

超维空间科技的博客 6795

【玩转链表③】碾压单链表之双向带头循环链表

双向带头循环链表这么香,不来学一下吗?

罅隙的博客 1102

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

手撕数据结构 —— 带头双向循环链表(C语言讲解)

什么是带头:带头的意思是链表多申请一个结点放在链表的起始位置,该结点并不存储有效元素。上图中的head结点就是头结点,该结点也往往称之为哨兵位。带头的作用:该结点的主要作用是为了方便实现链表和操作链表。主要体现在两个方面:1、提供统一的操作方式。2、避免二级指针的使用。提供统一的操作方式。因为操作没有头结点的链表的时候,往往需要记录当前结点的上一个结点,但是第一个结点是没有上一个结点的,就需要特殊处理,设置哨兵位的头结点可以对所有存储有效元素的结点提供统一的操作方式。避免二级指针的使用。

知其然 知其所以然 1446

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

数据结构:(c实现)双向带头循环链表。双向,带头,循环分别代表什么? 链表的基本操作接口实现,头增,头删,尾增,尾删,任意位置数据的插入删除(内附详细代码与图解)

一:如何实现双向带头循环链表 (1)链表单个结点的结构 (2)带头??头是什么 (3)双向??互相指向。 (4)循环??尾结点与哨兵位互相指向。 二:各种链表接口函数的实现 (1)创建哨兵位结点的函数 (2)尾插函数实现 (3)尾删函数实现 (4)头增函数实现 (5)头删函数实现 (6)查询函数的实现 (7)任意位置插入函数 (8)删除任意结点 内附详细代码与图解

qq_51004011的博客 448

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

C语言实现链表常用接口(双向带头循环链表)

链表常用接口的实现

faerfwedw的博客 436

初阶数据结构【双链表及其接口的实现】

前面我们介绍了数据结构中的链表,并实现了我们在实际中最常用的两个链表之一——无头单向非循环链表,这期我们继续来用C语言实现第二个常用链表——带头双向循环链表;26考研一战成硕!

吴先生的博客 1128

数据结构——双向循环链表的结构与实现(C语言)

C语言实现带头双向循环链表一、双向链表的结构与实现1.1 带头双向循环链表1.2 带头双向循环链表的实现二、双向链表的接口实现2.1 创建双向链表2.2 双向链表销毁2.3 双向链表在pos的前面进行插入2.4 双向链表删除pos位置的节点2.5 双向链表打印2.5 双向链表尾插2.6 双向链表尾删2.7 双向链表头插2.8 双向链表头删2.9 双向链表查找三、代码清单3.1 List.h3.2 List.c3.3 test.c四、测试结果 一、双向链表的结构与实现 1.1 带头双向循环链表 结构最复杂,

2792

链接未来:深入理解链表数据结构(二.c语言实现带头双向循环链表)

双向带头循环链表是一种特殊的双向链表。它与普通双向链表的不同之处在于:它有两个指针分别指向链表的头节点和尾节点,并且链表中的最后一个节点的指针指向头节点,形成循环。 这种链表的特性允许在操作上更加灵活,可以快速地在链表的前后进行插入和删除操作,同时循环特性也使得在遍历链表时更为方便

qq_74415153的博客 2238

【数据结构】链表

在的实现中,我们发现顺序表的存在以下缺点:1.中间头部插入删除数据,需要挪动数据,效率低下O(N)2.空间不够,扩容。扩容需要申请新空间,拷贝数据,释放旧空间,会有一定的消耗,其次还可能会有一定的空间浪费。而链表就很好的弥补了这些缺点。

lzb_kkk的博客 1708

《数据结构学习笔记---第四篇》---带头双向循环链表具体实现

带头双向循环链表

yl1509797225的博客 533

数据结构--带头双向循环链表(C语言实现)

在实现链表功能前,我们先定义节点结构和数据类型#pragma once // 防止头文件重复包含// 重定义链表存储的数据类型,方便后期修改类型(如改为char/double)// 带头双向循环链表节点结构// 节点存储的数据// 前驱指针:指向当前节点的上一个节点// 后继指针:指向当前节点的下一个节点}LTNode;核心结构说明:使用typedef重定义数据类型,后期只需修改这一行,就能让链表存储任意类型数据;prev指针:双向链表核心,让每个节点能快速找到前驱节点;next。

Siri_s12的博客 1078

C语言详解双向链表的基本操作

双链表的定义与接口函数 定义双链表 接口函数 详解接口函数的实现 创建新节点(BuyLTNode) 初始化双链表(ListInit) 双向链表打印(ListPrint) 双链表查找(ListFind) 双链表销毁(ListDestory) 1、双链表pos位置之前插入(ListInsert) 2、双链表删除pos位置(ListEarse) 3、双向链表尾插(ListPushBack) 4、双向链表头插(ListPu

weixin_73961973的博客 1786

数据结构:链表-C语言实现

数据结构:链表-C语言实现,写得非常详细,内容丰富,注解周全。

柿子__ 2506

揭开线性表的神秘面纱——双向链表

在单链表那篇文章中我们使用c语言实现了无头单向非循环链表,本文将实现带头双向循环链表,在诸多链表结构中,上述两种链表在实际生活与面试题中最为常见。1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单。

weixin_60358305的博客 212
上一篇: 单链表各种接口的实现(C)
下一篇: 栈的各种接口的实现(C)
ChoSeitaku
博客等级 码龄5年 3452粉丝 557原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值