【数据结构】双向循环链表的使用

双向循环链表的使用

  • 1.双向循环链表节点设计
  • 2.初始化双向循环链表-->定义结构体变量 创建头节点
    • (1)示例代码:
    • (2)图示
  • 3.双向循环链表节点头插
    • (1)示例代码:
    • (2)图示
  • 4.双向循环链表节点尾插
    • (1)示例代码:
    • (2)图示
  • 5.双向循环链表节点中间插入
    • (1)示例代码:
    • (2)图示
  • 6.双向循环链表删除节点
    • (1)示例代码:
    • (2)图示
  • 7.双向循环链表修改节点数据
    • (1)示例代码:
  • 8.双向循环链表遍历
  • 9.完整示例代码

1.双向循环链表节点设计

typedef struct double_list{int data;struct double_list *next;struct double_list *prev;
}double_list_t;

2.初始化双向循环链表–>定义结构体变量 创建头节点

(1)示例代码:

double_list_t *double_list_init()
{double_list_t *head_node = malloc(sizeof(double_list_t));if (head_node != NULL){head_node->next = head_node;head_node->prev = head_node;}else{printf("[double_list_init]申请头节点失败\n");}return head_node;
}

(2)图示

在这里插入图片描述

3.双向循环链表节点头插

(1)示例代码:

int insert_list_head(int newdata, double_list_t *list)
{// 申请一个节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));if (new_node == NULL) {printf("[insert_list_head]申请新的节点失败\n");return -1; // 申请内存失败}// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// 当链表为空时if (list->next == list){list->next = new_node;new_node->next = list;new_node->prev = list;list->prev = new_node;// printf("[insert_list_head]当链表为空时\n");}// 链表不为空时else{// 插入节点new_node->next = list->next;list->next = new_node;new_node->next->prev = new_node;new_node->prev = list;// printf("[insert_list_head]当链表不为空时\n");}return 0;
}

(2)图示

在这里插入图片描述
在这里插入图片描述

4.双向循环链表节点尾插

(1)示例代码:

int insert_list_tail(int newdata, double_list_t *list)
{// 申请一个节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));if (new_node == NULL) {printf("[insert_list_tail]申请新的节点失败\n");return -1; // 申请内存失败}// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// 定义指针p去找到链表的尾部double_list_t *p = list;while (p->next != list){p = p->next;}// 此时p已经到最后一个节点的位置new_node->next = list;p->next = new_node;list->prev = new_node;new_node->prev = p;return 0;
}

(2)图示

在这里插入图片描述

5.双向循环链表节点中间插入

(1)示例代码:

int insert_list_mid(int olddata, int newdata, double_list_t *list)
{// 找到要插入的节点double_list_t *p = list;while (p->next != list){p = p->next;if (p->data == olddata){break;}}// 申请一个新的节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// p指向最后一个节点if (p->next == list){// 如果最后一个节点是要插入的数据if (p->data == olddata){new_node->next = p->next; p->next = new_node;  new_node->prev = p;}else{printf("[insert_list_mid]要插入的数据不存在\n");return -1;}}else // 遍历到中间找到需要插入的节点{new_node->next = p->next; p->next = new_node;   new_node->prev = p;   new_node->next->prev = new_node;}return 0;
}

(2)图示

在这里插入图片描述

6.双向循环链表删除节点

(1)示例代码:

int list_delnode(int deldata, double_list_t *list)
{// p指向链表的头节点double_list_t *p = list;while (p->next != list){// 找到要删除的节点并进行删除if (p->data == deldata){p->prev->next = p->next;     p->next->prev = p->prev;double_list_t *temp = p->next; // 将temp指针指向p的下一个节点 p->next = NULL;p->prev = NULL;free(p);    // 释放p后此时p是野指针p = temp;   // p往后移动}else{p = p->next;}  }// 遍历到最后一个节点if (p->next == list){// 若最后一个节点是要删除的节点,则删除if (p->data == deldata){p->prev->next = list;p->next = NULL;list->prev = p->prev;p->prev = NULL;free(p);}else{printf("[list_delnode]最后一个节点不是要删除的节点\n");return 0;}}
}

(2)图示

在这里插入图片描述
在这里插入图片描述

7.双向循环链表修改节点数据

(1)示例代码:

int list_update_node(int old_data, int new_data, double_list_t *list)
{double_list_t *p = list;while (p->next != list){p = p->next;  // p往后移动if (p->data == old_data){p->data = new_data;}}return 0;
}

8.双向循环链表遍历

int list_show(double_list_t *list)
{double_list_t *p = list; //p指向头结点while (p->next != list){p = p->next;printf("[list_show]当前p指向的节点数据:%d\n", p->data);}
}

9.完整示例代码

#include <stdio.h>
#include <stdlib.h>// 1.封装一个结构体来表示双向循环链表
typedef struct double_list{int data;struct double_list *next;struct double_list *prev;
}double_list_t;// 2.初始化双向循环链表-->定义结构体变量 创建头节点
double_list_t *double_list_init()
{double_list_t *head_node = malloc(sizeof(double_list_t));if (head_node != NULL){head_node->next = head_node;head_node->prev = head_node;}else{printf("[double_list_init]申请头节点失败\n");}return head_node;
}// 头插
int insert_list_head(int newdata, double_list_t *list)
{// 申请一个节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));if (new_node == NULL) {printf("[insert_list_head]申请新的节点失败\n");return -1; // 申请内存失败}// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// 当链表为空时if (list->next == list){list->next = new_node;new_node->next = list;new_node->prev = list;list->prev = new_node;// printf("[insert_list_head]当链表为空时\n");}// 链表不为空时else{// 插入节点new_node->next = list->next;list->next = new_node;new_node->next->prev = new_node;new_node->prev = list;// printf("[insert_list_head]当链表不为空时\n");}return 0;
}
/*@brief:3.插入数据-->尾插(在最后一个有效成员的后面插入数据)*@param(in):  newdata :待插入的数据  list:链表头节点*@param(out):  *@retval:    
*/
int insert_list_tail(int newdata, double_list_t *list)
{// 申请一个节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));if (new_node == NULL) {printf("[insert_list_tail]申请新的节点失败\n");return -1; // 申请内存失败}// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// 定义指针p去找到链表的尾部double_list_t *p = list;while (p->next != list){p = p->next;}// 此时p已经到最后一个节点的位置new_node->next = list;p->next = new_node;list->prev = new_node;new_node->prev = p;return 0;
}// 节点中间插入链表
int insert_list_mid(int olddata, int newdata, double_list_t *list)
{// 找到要插入的节点double_list_t *p = list;while (p->next != list){p = p->next;if (p->data == olddata){break;}}// 申请一个新的节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// p指向最后一个节点if (p->next == list){// 如果最后一个节点是要插入的数据if (p->data == olddata){new_node->next = p->next; p->next = new_node;  new_node->prev = p;}else{printf("[insert_list_mid]要插入的数据不存在\n");return -1;}}else // 遍历到中间找到需要插入的节点{new_node->next = p->next; p->next = new_node;   new_node->prev = p;   new_node->next->prev = new_node;}return 0;
}
// 删除节点
int list_delnode(int deldata, double_list_t *list)
{// p指向链表的头节点double_list_t *p = list;while (p->next != list){// 找到要删除的节点并进行删除if (p->data == deldata){p->prev->next = p->next;     p->next->prev = p->prev;double_list_t *temp = p->next; // 将temp指针指向p的下一个节点 p->next = NULL;p->prev = NULL;free(p);    // 释放p后此时p是野指针p = temp;   // p往后移动}else{p = p->next;}  }// 遍历到最后一个节点if (p->next == list){// 若最后一个节点是要删除的节点,则删除if (p->data == deldata){p->prev->next = list;p->next = NULL;list->prev = p->prev;p->prev = NULL;free(p);}else{printf("[list_delnode]最后一个节点不是要删除的节点\n");return 0;}}
}
// 修改节点
int list_update_node(int old_data, int new_data, double_list_t *list)
{double_list_t *p = list;while (p->next != list){p = p->next;  // p往后移动if (p->data == old_data){p->data = new_data;}}return 0;
}// 4.遍历链表,打印节点数据
int list_show(double_list_t *list)
{double_list_t *p = list; //p指向头结点while (p->next != list){p = p->next;printf("[list_show]当前p指向的节点数据:%d\n", p->data);}
}int main(int argc, char const *argv[])
{// 初始化单链表 ,指向链表的头节点double_list_t *my_list_head = double_list_init();// 往链表插入数据insert_list_head(2, my_list_head);insert_list_head(3, my_list_head);insert_list_head(4, my_list_head);insert_list_tail(15, my_list_head);insert_list_tail(16, my_list_head);insert_list_tail(17, my_list_head);insert_list_head(2, my_list_head);insert_list_tail(15, my_list_head);insert_list_tail(15, my_list_head);insert_list_tail(15, my_list_head);insert_list_mid(5, 6, my_list_head);insert_list_mid(2, 88, my_list_head);insert_list_mid(17, 15, my_list_head);printf("============插入的节点============\n");list_show(my_list_head);printf("============插入的节点============\n");// 删除节点list_delnode(25, my_list_head);list_delnode(15, my_list_head);list_delnode(2, my_list_head);printf("============删除后的节点============\n");list_show(my_list_head); // 打印数据printf("============删除后的节点============\n");// 修改数据list_update_node(16, 116, my_list_head);printf("============修改后的节点============\n");list_show(my_list_head); // 打印数据printf("============修改后的节点============\n");return 0;
}
/*
执行结果:
[insert_list_mid]要插入的数据不存在
============插入的节点============
[list_show]当前p指向的节点数据:2
[list_show]当前p指向的节点数据:88
[list_show]当前p指向的节点数据:4
[list_show]当前p指向的节点数据:3
[list_show]当前p指向的节点数据:2
[list_show]当前p指向的节点数据:15
[list_show]当前p指向的节点数据:16
[list_show]当前p指向的节点数据:17
[list_show]当前p指向的节点数据:15
[list_show]当前p指向的节点数据:15
[list_show]当前p指向的节点数据:15
[list_show]当前p指向的节点数据:15
============插入的节点============
[list_delnode]最后一个节点不是要删除的节点
[list_delnode]最后一个节点不是要删除的节点
============删除后的节点============
[list_show]当前p指向的节点数据:88
[list_show]当前p指向的节点数据:4
[list_show]当前p指向的节点数据:3
[list_show]当前p指向的节点数据:16
[list_show]当前p指向的节点数据:17
============删除后的节点============
============修改后的节点============
[list_show]当前p指向的节点数据:88
[list_show]当前p指向的节点数据:4
[list_show]当前p指向的节点数据:3
[list_show]当前p指向的节点数据:116
[list_show]当前p指向的节点数据:17
============修改后的节点============
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/64893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java设计模式-3】门面模式——简化复杂系统的魔法

在软件开发的世界里&#xff0c;我们常常会遇到复杂的系统&#xff0c;这些系统由多个子系统或模块组成&#xff0c;各个部分之间的交互错综复杂。如果直接让外部系统与这些复杂的子系统进行交互&#xff0c;不仅会让外部系统的代码变得复杂难懂&#xff0c;还会增加系统之间的…

Linux一些问题

修改YUM源 Centos7将yum源更换为国内源保姆级教程_centos使用中科大源-CSDN博客 直接安装包&#xff0c;走链接也行 Index of /7.9.2009/os/x86_64/Packages 直接复制里面的安装包链接&#xff0c;在命令行直接 yum install https://vault.centos.org/7.9.2009/os/x86_64/Pa…

HTML——57. type和name属性

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>type和name属性</title></head><body><!--1.input元素是最常用的表单控件--><!--2.input元素不仅可以在form标签内使用也可以在form标签外使用-…

uniapp本地加载腾讯X5浏览器内核插件

概述 TbsX5webviewUTS插件封装腾讯x5webview离线内核加载模块&#xff0c;可以把uniapp的浏览器内核直接替换成Android X5 Webview(腾讯TBS)最新内核&#xff0c;提高交互体验和流畅度。 功能说明 下载SDK插件 1.集成x5内核后哪些页面会由x5内核渲染&#xff1f; 所有plus…

设计模式 创建型 单例模式(Singleton Pattern)与 常见技术框架应用 解析

单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;旨在确保某个类在应用程序的生命周期内只有一个实例&#xff0c;并提供一个全局访问点来获取该实例。这种设计模式在需要控制资源访问、避免频繁创建和销毁对象的场景中尤为有用。 一、核心…

您的公司需要小型语言模型

当专用模型超越通用模型时 “越大越好”——这个原则在人工智能领域根深蒂固。每个月都有更大的模型诞生&#xff0c;参数越来越多。各家公司甚至为此建设价值100亿美元的AI数据中心。但这是唯一的方向吗&#xff1f; 在NeurIPS 2024大会上&#xff0c;OpenAI联合创始人伊利亚…

uniapp-vue3(下)

关联链接&#xff1a;uniapp-vue3&#xff08;上&#xff09; 文章目录 七、咸虾米壁纸项目实战7.1.咸虾米壁纸项目概述7.2.项目初始化公共目录和设计稿尺寸测量工具7.3.banner海报swiper轮播器7.4.使用swiper的纵向轮播做公告区域7.5.每日推荐滑动scroll-view布局7.6.组件具名…

使用 Python 实现随机中点位移法生成逼真的裂隙面

使用 Python 实现随机中点位移法生成逼真的裂隙面 一、随机中点位移法简介 1. 什么是随机中点位移法&#xff1f;2. 应用领域 二、 Python 代码实现 1. 导入必要的库2. 函数定义&#xff1a;随机中点位移法核心逻辑3. 设置随机数种子4. 初始化二维裂隙面5. 初始化网格的四个顶点…

活动预告 | Microsoft Power Platform 在线技术公开课:实现业务流程自动化

课程介绍 参加“Microsoft Power Platform 在线技术公开课&#xff1a;实现业务流程自动化”活动&#xff0c;了解如何更高效地开展业务。参加我们举办的本次免费培训活动&#xff0c;了解如何借助 Microsoft AI Builder 和 Power Automate 优化工作流。结合使用这些工具可以帮…

LLM(十二)| DeepSeek-V3 技术报告深度解读——开源模型的巅峰之作

近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;的发展突飞猛进&#xff0c;逐步缩小了与通用人工智能&#xff08;AGI&#xff09;的差距。DeepSeek-AI 团队最新发布的 DeepSeek-V3&#xff0c;作为一款强大的混合专家模型&#xff08;Mixture-of-Experts, MoE&a…

el-pagination 为什么只能展示 10 条数据(element-ui@2.15.13)

好的&#xff0c;我来帮你分析前端为什么只能展示 10 条数据&#xff0c;以及如何解决这个问题。 问题分析&#xff1a; pageSize 的值&#xff1a; 你的 el-pagination 组件中&#xff0c;pageSize 的值被设置为 10&#xff1a;<el-pagination:current-page"current…

TCP网络编程(一)—— 服务器端模式和客户端模式

这篇文章将会编写基本的服务器网络程序&#xff0c;主要讲解服务器端和客户端代码的原理&#xff0c;至于网络名词很具体的概念&#xff0c;例如什么是TCP协议&#xff0c;不会过多涉及。 首先介绍一下TCP网络编程的两种模式&#xff1a;服务器端和客户端模式&#xff1a; 首先…

在K8S中,如何部署kubesphere?

在Kubernetes集群中&#xff0c;对于一些基础能力较弱的群体来说K8S控制面板操作存在一定的难度&#xff0c;此时kubesphere可以有效的解决这类难题。以下是部署kubesphere的操作步骤&#xff1a; 操作部署&#xff1a; 1. 部署nfs共享存储目录 yum -y install nfs-server e…

树莓派之旅-第一天 系统的烧录和设置

自言自语&#xff1a; 在此记录一下树莓派的玩法。以后有钱了买点来玩啊草 系统的安装烧录 系统下载 树莓派官网&#xff1a;https://www.raspberrypi.com/ 首页点击SoftWare进入OS下载页面 这里是安装工具&#xff1a;安装工具负责将系统镜像安装到sd卡中 点击下载符合自己…

商用车自动驾驶,迎来大规模量产「临界点」?

商用车自动驾驶&#xff0c;正迎来新的行业拐点。 今年初&#xff0c;交通部公开发布AEB系统运营车辆标配征求意见稿&#xff0c;首次将法规限制条件全面放开&#xff0c;有望推动商用车AEB全面标配&#xff0c;为开放场景的商用车智能驾驶市场加了一把火。 另外&#xff0c;…

人工智能及深度学习的一些题目

1、一个含有2个隐藏层的多层感知机&#xff08;MLP&#xff09;&#xff0c;神经元个数都为20&#xff0c;输入和输出节点分别由8和5个节点&#xff0c;这个网络有多少权重值&#xff1f; 答&#xff1a;在MLP中&#xff0c;权重是连接神经元的参数&#xff0c;每个连接都有一…

Solon 加入 GitCode:助力国产 Java 应用开发新飞跃

在当今数字化快速发展的时代&#xff0c;Java 应用开发框架不断演进&#xff0c;开发者们始终在寻找更快、更小、更简单的解决方案。近期&#xff0c;Solon 正式加入 GitCode&#xff0c;为广大 Java 开发者带来全新的开发体验&#xff0c;尤其是在国产应用开发进程中&#xff…

VScode 只能运行c,运行不了c++的解决问题

原文链接&#xff1a;Vscode只能运行c&#xff0c;运行不了c的解决方法 VScode 只能运行c&#xff0c;运行不了c&#xff0c;怎么回事呢&#xff0c;解决问题&#xff1a; 在tasks.json中加上“"-lstdc"”&#xff0c; 这样之后 要重启VScode&#xff0c;点击链接…

SpringCloud系列教程:微服务的未来 (五)枚举处理器、JSON处理器、分页插件实现

在现代 Java 开发中&#xff0c;我们常常需要处理各种通用的功能和需求&#xff0c;诸如枚举的处理、JSON 数据处理&#xff0c;以及分页查询等。这些功能虽然看似简单&#xff0c;但在实际开发中往往涉及到许多细节和优化。为了提高开发效率、减少重复代码的编写&#xff0c;我…

游戏引擎学习第69天

回顾碰撞响应时我们停留的位置 从昨天的讨论开始&#xff0c;我们正准备处理碰撞响应的复杂性。具体来说&#xff0c;我们讨论的是&#xff0c;当两个实体在屏幕上发生碰撞时&#xff0c;如何回应这种情况。碰撞本身并不复杂&#xff0c;但要处理其后的反应和规则则更具挑战性…