[C语言][数据结构][链表] 双链表的从零实现!

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

目录

零.必备知识

0.1 一级指针 && 二级指针

0.2 双链表节点的成员列表

        a. 数据

        b. 后驱指针

        c. 前驱指针

0.3 动态内存空间的开辟

一. 双链表的实现与销毁

        1.1 节点的定义

        1.2 双向链表的初始化 && 创建新节点

        1.3 尾插 

        1.4 头插 

        1.5 尾删 

        1.6 头删

        1.7 在指定位置之后插入数据 

        1.8 删除指定位置的数据 

        1.9 销毁双链表

 二.双链表源码

List.h

List.c


零.必备知识

0.1 一级指针 && 二级指针

0.2 双链表节点的成员列表

        a. 数据

        b. 后驱指针

        c. 前驱指针

0.3 动态内存空间的开辟


一. 双链表的实现与销毁

此次实现的链表是带头双向循环链表.如图:

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

        1.1 节点的定义

后驱节点指向写一个节点.

前驱节点指向前一个节点.

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

        1.2 双向链表的初始化 && 创建新节点

初始化是指:创建了一个哨兵节点.

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

这个哨兵节点的作用是:避免双向链表死循环.

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法 

        1.3 尾插 

贯穿本文的核心要点是:先修改新节点中前驱,后驱指针的指向.再修改其余节点前驱,后驱指针的指向.

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

        1.4 头插 

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法 

        1.5 尾删 

尾删和接下来的头删,都是可以创建一个临时指针来指向要删除的节点.

这样看以来更直观,更重要的是方便进行空间的释放.

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

 [C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

        1.6 头删

 [C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法 

        1.7 在指定位置之后插入数据 

在指定位置之后插入数据:可以先实现一个查找函数,来自己指定pos.

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法 

        1.8 删除指定位置的数据 

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法 

        1.9 销毁双链表

 注意:此处传入的是一级指针,并没有真正的修改phead(哨兵位/头节点)中的值,如果要真正的销毁双链表,需要传入二级指针.

那么为什么我传的是一级指针呢?  答案:保持传入参数的一致性.

[C语言][数据结构][链表] 双链表的从零实现!,C语言阶段相关习题总览,数据结构,c语言,链表,开发语言,算法 文章来源地址https://www.toymoban.com/news/detail-854886.html

 二.双链表源码

List.h

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

// 单个节点的定义
typedef int LTDateType;
typedef struct List
{
	LTDateType date;
	struct List* next; // 后驱节点
	struct List* prev; // 前驱节点
}List;
// 节点的创建
List* LTBuyNode(LTDateType x);
// 双向链表的初始化
List* LTInit();
// 双向链表的展示
void LTPrint(List* phead);
// 尾插-头插
void LTPushBack(List* phead, LTDateType x);
void LTPushFront(List* phead, LTDateType x);
// 尾删-头删
void LTPopBack(List* phead);
void LTPopFront(List* phead);
// 查找指定数据
List* LTFind(List* phead, LTDateType x);
// 在指定位置之后插入数据
void LTInsertAfter(List* pos, LTDateType x);
// 删除指定位置的数据
void LTErase(List* phead, List* pos);
// 销毁双链表
void LTDestroy(List* phead);

List.c

#define  _CRT_SECURE_NO_WARNINGS
#include "List.h"
// 节点的创建
List* LTBuyNode(LTDateType x)
{
	List* newNode = (List*)malloc(sizeof(List));
	if (newNode == NULL) { // 创建失败
		perror("malloc fail!");
		exit(1);
	}
	newNode->date = x;
	newNode->next = NULL;
	newNode->prev = NULL;
	return newNode;
}
// 双向链表的初始化
List* LTInit()
{
	List* newNode = LTBuyNode(-1);
	newNode->next = newNode;
	newNode->prev = newNode;
	return newNode;
}
// 双向链表的展示
void LTPrint(List* phead)
{
	assert(phead);
	List* pcur = phead->next;
	while (pcur != phead) {
		printf("%d->", pcur->date);
		pcur = pcur->next;
	}
	printf("\n");
}
// 尾插
void LTPushBack(List* phead, LTDateType x)
{
	assert(phead);
	// 创建新节点
	List* newNode = LTBuyNode(x);
	// 先更改新节点的前驱后驱指针
	newNode->next = phead;
	newNode->prev = phead->prev;

	// 更改其余节点的前驱后驱指针
	phead->prev->next = newNode;
	phead->prev = newNode;
}
// 头插
void LTPushFront(List* phead, LTDateType x)
{
	assert(phead);
	List* newNode = LTBuyNode(x);
	// 更改newNode的前驱后驱指针
	newNode->next = phead->next;
	newNode->prev = phead;

	// 更改其余节点的指针指向
	phead->next->prev = newNode;
	phead->next = newNode;
}
// 尾删
void LTPopBack(List* phead)
{
	assert(phead);
	List* pcur = phead->prev;
	// 更改要删除的节点的前一个节点的指针指向
	pcur->prev->next = phead;
	
	// 更改哨兵位的指针指向
	phead->prev = pcur->prev;
	
	// 释放尾节点
	free(pcur);
	pcur = NULL;
}
// 头删
void LTPopFront(List* phead)
{
	assert(phead);
	List* pcur = phead->next;
	
	phead->next = pcur->next;
	pcur->next->prev = phead;

	// 销毁pcur节点
	free(pcur);
	pcur = NULL;
}
// 查找指定数据
List* LTFind(List* phead, LTDateType x)
{
	assert(phead);
	List* pcur = phead->next;
	while (pcur != phead) {
		if (pcur->date == x) {
			printf("找到了!\n");
			return pcur;
		}
		pcur = pcur->next;
	}
	printf("没有找到!\n");
	return NULL;
}
// 在指定位置之后插入数据
void LTInsertAfter(List* pos, LTDateType x)
{
	assert(pos);
	List* newNode = LTBuyNode(x);

	// 修改新节点的指向
	newNode->next = pos->next;
	newNode->prev = pos;

	// 修改其余节点的指向
	pos->next->prev = newNode;
	pos->next = newNode;
}
// 删除指定位置的数据
void LTErase(List* phead, List* pos)
{
	assert(phead && pos);

	pos->next->prev = pos->prev;
	pos->prev->next = pos->next;

	// 销毁pos节点
	free(pos);
	pos = NULL;
}
// 销毁双链表
void LTDestroy(List* phead)
{
	assert(phead);
	List* pcur = phead->next;
	while (pcur != phead) {
		List* prev = pcur;
		pcur = pcur->next;
		// 销毁 pcur的前一个节点
		free(prev);
		prev = NULL;
	}
	// 销毁哨兵位
	free(phead);
	phead = NULL; // 但是没有真正的改变哨兵位, 因为传的是一级指针
	              // 如果要真正的改变 phead的值,则需要传递二级指针
}

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

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

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

相关文章

  • 【数据结构】双链表的定义和操作

    目录 1.双链表的定义 2.双链表的创建和初始化 3.双链表的插入节点操作 4.双链表的删除节点操作 5.双链表的查找节点操作 6.双链表的更新节点操作 7.完整代码 🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助。 💡本文由Filotimo__✍️原创,首发于CS

    2024年02月03日
    浏览(87)
  • c语言数据结构——链表的实现及其基本操作

    顺序表的问题及思考 问题: 中间/头部的插入删除,时间复杂度为O(N) 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到 200,我们再继续插入了5个数据,后面没有数据插

    2023年04月09日
    浏览(85)
  • 【Java数据结构 -- 实现双链表的接口方法】

    双链表是一种数据结构,其中每个节点包含 一个指向前一个节点的指针和一个指向后一个节点的指针 。由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来,因此双链表可以任意且快速的插入和删除元素。 引用接口IList,在把

    2024年01月16日
    浏览(59)
  • 数据结构之双链表的相关知识点及应用

     找往期文章包括但不限于本期文章中不懂的知识点: 个人主页 :我要学编程(ಥ_ಥ)-CSDN博客 所属专栏 :数据结构 目录 双链表的实现  初始化双链表  在双链表中尾插数据  在双链表中尾删数据 在双链表中头插数据  在双链表中头删数据  在双链表中的指定位置之后插入

    2024年04月26日
    浏览(52)
  • Java 数据结构篇-实现双链表的核心API

    🔥博客主页:  小扳_-CSDN博客 ❤感谢大家点赞👍收藏⭐评论✍       文章目录         1.0 双链表的说明         1.1 双链表 - 创建         1.2 双链表 - 根据索引查找节点         1.3 双链表 - 根据索引插入节点         1.4 双链表 - 头插节点         1.5 双链表 - 尾插

    2024年02月04日
    浏览(59)
  • C语言---数据结构实验---顺序表的合并---链表的基本操作---重点解析约瑟夫问题

    实验的写法多种多样,但本文并未采用 #define 定义容量的写法,这样写已经是很老旧过时的写法。所有实验主体采用均为动态开辟,后续如果利用 C++ 来写或许会应用更多语法… 本篇展示数据结构的两个实验 其中,重点分析约瑟夫问题 实验中代码的命名风格等均与下方博客

    2024年02月16日
    浏览(70)
  • 数据结构_双链表、循环链表、静态链表

    目录 1. 双链表 1.1 双链表的初始化 1.2 双链表的插入操作 1.3 双链表的删除操作 1.4 双链表的遍历 2. 循环链表 2.1 循环单链表 2.2 循环双链表 3. 静态链表 4. 顺序表和链表的比较 5. 相关练习         单链表结点中只有一个指向其后继的指针,使得单链表只能从头结点依次顺序

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

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

    2024年03月10日
    浏览(87)
  • 【数据结构】链表(单链表与双链表实现+原理+源码)

    博主介绍:✌全网粉丝喜爱+、前后端领域优质创作者、本质互联网精神、坚持优质作品共享、掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战✌有需要可以联系作者我哦! 🍅附上相关C语言版源码讲解🍅 👇🏻 精彩专栏推荐订阅👇🏻 不然下次找

    2024年01月24日
    浏览(143)
  • 数据结构--线性表(顺序表、单链表、双链表、循环链表、静态链表)

    前言  学习所记录,如果能对你有帮助,那就泰裤辣。 目录 1.线性表概念 定义 基本操作 2.顺序表 定义 顺序表的实现--静态分配 动态分配 顺序表的特点 顺序表的插入和删除 顺序表的查找 按位查找  按值查找 3.单链表 定义 单链表的初始化 不带头节点的单链表 带头节点的单

    2024年02月11日
    浏览(63)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包