【数据结构】单链表的头节点与尾节点

在这里插入图片描述

🎈个人主页:豌豆射手^
🎉欢迎 👍点赞✍评论⭐收藏
🤗收录专栏:数据结构
🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步!

【数据结构】单链表的头节点与尾节点

  • 引言
    • 一 概念
      • 头节点(Head Node)
        • 头节点的作用:
      • 尾节点(Tail Node)
        • 尾节点的作用:
      • 总结
    • 二 代码
  • 总结

在这里插入图片描述

引言

一 概念

在数据结构中的单链表中,头节点(Head Node)和尾节点(Tail Node)是两个特殊的节点,它们在链表结构中扮演着不同的角色。

头节点(Head Node)

头节点是链表中的第一个节点,它通常用于简化对链表的操作。头节点并不总是包含实际的数据,有时候它只是一个哨兵节点(Dummy Node),用于指向链表中的第一个实际数据节点。头节点的存在可以使得链表的操作更加统一和方便,特别是在进行插入、删除和遍历操作时。

头节点的作用:
  1. 简化插入操作:当需要在链表头部插入新节点时,如果链表有头节点,就可以直接将新节点的指针指向头节点原本指向的节点,然后将头节点的指针指向新节点。如果没有头节点,就需要处理一些特殊情况,比如判断链表是否为空。
  2. 简化删除操作:类似地,当需要删除链表头部的节点时,如果有头节点,只需要将头节点的指针指向下一个节点即可。如果没有头节点,则需要特别注意链表是否为空,以及如何处理删除后的链表头部。
  3. 统一链表操作:有了头节点,无论是链表的头部还是尾部,都可以使用统一的操作方式,这使得代码更加简洁和易于维护。

尾节点(Tail Node)

尾节点是链表中的最后一个节点。在单链表中,每个节点都包含一个指向下一个节点的指针,而尾节点的这个指针通常设置为 NULL,表示链表的结束。

尾节点的作用:
  1. 标记链表结束:通过尾节点的 NULL 指针,可以方便地知道链表何时结束,这是遍历链表时的重要标识。
  2. 简化插入操作:当需要在链表尾部插入新节点时,只需要将尾节点的指针指向新节点,然后将新节点的指针设置为 NULL。这样可以避免从头节点开始遍历整个链表来找到最后一个节点。

总结

头节点和尾节点在单链表中的作用主要体现在简化链表操作和提高代码的可读性和可维护性。它们使得链表的插入、删除和遍历等操作更加高效和一致。然而,并不是所有的单链表实现都会使用头节点,这取决于具体的应用场景和需求。在某些情况下,为了节省内存空间或简化数据结构,可能会选择不使用头节点。

二 代码

在C语言中实现单链表的头节点和尾节点,我们需要首先定义链表节点的结构体,然后编写创建链表、添加节点等函数。下面是一个简单的示例,它展示了如何创建一个包含头节点和尾节点的单链表,并向其中添加数据节点。

#include <stdio.h>
#include <stdlib.h>// 定义链表节点结构体
typedef struct Node {int data;           // 节点存储的数据struct Node* next; // 指向下一个节点的指针
} Node;// 创建新节点
Node* createNode(int data) {Node* newNode = (Node*)malloc(sizeof(Node)); // 为新节点分配内存if (newNode == NULL) {printf("Memory allocation failed!\n");exit(1); // 如果内存分配失败,退出程序}newNode->data = data;    // 设置节点的数据newNode->next = NULL;    // 新节点的next指针初始化为NULLreturn newNode;          // 返回新创建的节点
}// 在链表尾部添加节点
void appendNode(Node** head, Node** tail, int data) {Node* newNode = createNode(data); // 创建新节点if (*head == NULL) {             // 如果链表为空(即头节点为空)*head = newNode;             // 新节点成为头节点*tail = newNode;             // 新节点也成为尾节点} else {(*tail)->next = newNode;    // 将新节点添加到当前尾节点的后面*tail = newNode;             // 更新尾节点为新节点}
}// 打印链表
void printList(Node* head) {Node* current = head;while (current != NULL) {printf("%d ", current->data);current = current->next;}printf("\n");
}// 释放链表内存
void freeList(Node* head) {Node* temp;while (head != NULL) {temp = head;head = head->next;free(temp);}
}int main() {Node* head = NULL;    // 初始化头节点为NULLNode* tail = NULL;    // 初始化尾节点为NULL// 向链表尾部添加节点appendNode(&head, &tail, 10);appendNode(&head, &tail, 20);appendNode(&head, &tail, 30);// 打印链表printList(head);// 释放链表内存freeList(head);return 0;
}

下面是对代码的详细解释:

  1. 定义链表节点结构体 Node,包含 datanext 两个成员。

  2. createNode 函数用于创建新节点,并初始化其 datanext 成员。如果内存分配失败,则打印错误信息并退出程序。

  3. appendNode 函数用于在链表尾部添加新节点。它接受头节点和尾节点的地址作为参数,以便在添加新节点时能够更新这两个指针。

    • 如果链表为空(即头节点为 NULL),新节点既是头节点也是尾节点。
    • 如果链表不为空,将新节点添加到当前尾节点的后面,并更新尾节点为新节点。
  4. printList 函数用于打印链表的内容。从头节点开始,遍历链表直到 NULL 指针,并打印每个节点的数据。

  5. freeList 函数用于释放链表占用的内存。从头节点开始,逐个释放每个节点所占用的内存。

  6. main 函数中,我们初始化头节点和尾节点为 NULL,然后调用 appendNode 函数向链表尾部添加几个节点。接着,我们调用 printList 函数打印链表的内容。最后,调用 freeList 函数释放链表占用的内存。

注意:在这个示例中,我们并没有显式地创建一个头节点来存储链表信息,而是将头节点作为链表的一部分,它同时存储数据和指向下一个节点的指针。如果你需要一个只包含指针而不包含数据的头节点,你需要在创建链表时单独处理它,并更新相关的逻辑。

另外,上面的代码示例没有包含错误处理逻辑,比如检查 malloc 调用是否成功。在实际编程中,你应该总是检查内存分配是否成功,并在必要时采取适当的错误处理措施。

总结

这篇文章到这里就结束了

谢谢大家的阅读!

如果觉得这篇博客对你有用的话,别忘记三连哦。

我是豌豆射手^,让我们我们下次再见

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

玄子Share-计算机网络参考模型

玄子Share-计算机网络参考模型 分层思想 利用七层参考模型&#xff0c;便于在网络通信过程中&#xff0c;快速的分析问题&#xff0c;定位问题并解决问题 将复杂的流程分解为几个功能相对单一的子过程 整个流程更加清晰&#xff0c;复杂问题简单化 更容易发现问题并针对性的…

【Java开发指南 | 第十七篇】Java 方法

读者可订阅专栏&#xff1a;Java开发指南 |【CSDN秋说】 文章目录 简介语法实例构造方法 简介 Java中的方法是用来执行特定任务的一组语句&#xff0c;可以重复使用。它们包含在类或对象中&#xff0c;并通过调用来执行。 举个例子&#xff0c;println() 是一个方法&#xff…

动态内存管理 柔性数组

文章目录 动态内存函数 malloc freecallocrealloc 重新开辟空间realloc 也可以第一个参数为NULL&#xff0c;则是直接开辟内存&#xff0c;类似于malloc用法 常见的动态内存错误对空指针进行解引用操作对开辟的内存越界访问对非动态开辟的内存使用free释放使用free释放动态开辟…

(四)相关性分析 学习简要笔记 #统计学 #CDA学习打卡

目录 一. 相关性分析简介 二. 相关性分析方法 1&#xff09;连续型变量vs连续型变量&#xff1a;Pearson/Spearman &#xff08;a&#xff09;Pearson &#xff08;b&#xff09;Spearman等级相关系数 2&#xff09;二分类变量&#xff08;自然&#xff09;vs连续型变量&…

macos知名的清理软件 cleanmymac和腾讯柠檬哪个好 cleanmymacx有必要买吗

MacOS是一款优秀的操作系统&#xff0c;但是随着使用时间的增加&#xff0c;它也会产生一些不必要的垃圾文件&#xff0c;占用磁盘空间和内存资源&#xff0c;影响系统的性能和稳定性。为了保持MacOS的清洁和高效&#xff0c;我们需要使用一些专业的清理软件来定期扫描和清除这…

【Golang】Gin教学-获取请求信息并返回

安装Gin初始化Gin处理所有HTTP请求获取请求的URL和Method获取请求参数根据Content-Type判断请求数据类型处理JSON数据处理表单数据处理文件返回JSON响应启动服务完整代码测试 Gin是一个用Go&#xff08;又称Golang&#xff09;编写的HTTP Web框架&#xff0c;它具有高性能和简洁…

Event loop(Message loop)

事件循环&#xff08;消息循环&#xff09; 浏览器的进程模型 进程 程序运行需要有它自己专属的内存空间&#xff0c;可以把这块内存空间简单的理解为进程 每个应用至少有一个进程&#xff0c;进程之间相互独立&#xff0c;即使要通信&#xff0c;也需要双方同意。 线程 …

【Linux学习】Linux权限(二)

文章目录 &#x1f680;Linux权限管理&#x1f680;修改文件的所有者&#x1f680;修改文件或目录的所属组&#x1f680;同时修改为念的拥有者与所属组&#x1f680;文件类型&#x1f680;file指令&#x1f680;目录权限&#x1f680;umask指令&#x1f680;粘滞位 &#x1f68…

网盘——私聊

在私聊这个功能实现中&#xff0c;具体步骤如下&#xff1a; 1、实现步骤&#xff1a; A、客户端A发送私聊信息请求&#xff08;发送的信息包括双方的用户名&#xff0c;聊天信息&#xff09; B、如果双方在线则直接转发给B&#xff0c;不在线则回复私聊失败&#xff0c;对方…

Sping源码(七)—ConfigurationClassPostProcessor创建流程

序言 前两篇文章介绍了invokeBeanFactoryPostProcessors的执行流程&#xff0c;和自定义实现BeanDefinitionRegistryPostProcessor类的方式方法。 这篇文章会主要介绍Spring启动加载xml时&#xff0c;ConfigurationClassPostProcessor类是如何加载到Spring中&#xff0c;并且…

【数学建模】最优旅游城市的选择问题:层次分析模型(含MATLAB代码)

层次分析法&#xff08;The analytic hierarachy process&#xff0c;简称AHP&#xff09;是一种常用的决策分析方法&#xff0c;其基本思路是将复杂问题分解为多个组成部分&#xff0c;然后对这些部分进行逐一评估和比较&#xff0c;最后得出最优解决方案。&#xff08;例如&a…

JVM知识点总结二

参考文章&#xff1a;【Java面试题汇总】JVM篇&#xff08;2023版&#xff09;_jvm面试题2023-CSDN博客 1、说说你了解的JVM内存模型&#xff1a; JVM由三部分组成&#xff1a;类加载子系统、运行时数据区、执行引擎 JVM内存模型&#xff1a; 内存模型里的运行时数据区&#…

ruby 配置代理 ip(核心逻辑)

在 Ruby 中配置代理 IP&#xff0c;可以通过设置 Net::HTTP 类的 Proxy 属性来实现。以下是一个示例&#xff1a; require net/http// 获取代理Ip&#xff1a;https://www.kuaidaili.com/?refrg3jlsko0ymg proxy_address 代理IP:端口 uri URI(http://www.example.com)Net:…

机器学习 | 使用Scikit-Learn实现分层抽样

在本文中&#xff0c;我们将学习如何使用Scikit-Learn实现分层抽样。 什么是分层抽样&#xff1f; 分层抽样是一种抽样方法&#xff0c;首先将总体的单位按某种特征分为若干次级总体&#xff08;层&#xff09;&#xff0c;然后再从每一层内进行单纯随机抽样&#xff0c;组成…

Django项目使用uwsgi+nginx部署上线

Django项目使用uwsginginx部署上线 前言settings 配置安装uwsgi 和配置uwsgi推荐配置文件启用wsgi不使用nginx的配置&#xff08;不推荐&#xff09;使用nginx的配置 安装 nginx和配置niginx 配置 运行参考资料 前言 代码已经开发完成&#xff0c;正式部署上线 settings 配置…

Redmi Turbo 3新品发布,天星金融(原小米金融)优惠加持护航新机体验

Redmi新十年使命不变&#xff0c;挑战不断升级。Redmi Turbo 3&#xff0c;作为Turbo系列的开篇之作&#xff0c;将自身定位为新生代性能旗舰&#xff0c;决心重塑中端性能新格局。据悉&#xff0c;Redmi Turbo 3于4月10日已正式发布。预售期间更是连续数日&#xff0c;蝉联小米…

SSL证书在HTTP与HTTPS中的角色差异是什么?

在互联网的广泛应用背景下&#xff0c;随着网络攻击和数据泄露事件频发&#xff0c;保障用户的数据安全已成为至关重要的议题。传统的HTTP协议在传输数据时不进行加密处理&#xff0c;导致数据在传输过程中暴露于潜在的窃听和篡改风险中&#xff0c;安全性薄弱。而通过引入SSL/…

解决Keil V5.38 和 ST-Link V3 Debug不能运行问题

目录 概述 1 问题描述 1.1 情况一 1.2 情况二 1.3 情况三 2 解决方法 2.1 认识Keil Mico Lib 2.2 使能Keil Mico Lib 3 验证 3.1 进入C程序Main验证 3.2 断点验证 3.3 上电重启验证 4 结论 笔者使用的验证代码下载地址&#xff1a; stm32-freeRTOS-queue资源-CSD…

微信小程序日期增加时间完成订单失效倒计时(有效果图)

效果图 .wxml <view class"TimeSeond">{{second}}</view>.js Page({data: {tiem_one:,second:,//倒计时deadline:,},onLoad(){this.countdown();},countdown(){let timestamp Date.parse(new Date()) / 1000;//当前时间戳let time this.addtime(2024…

k8s 部署 kube-prometheus监控

一、Prometheus监控部署 1、下载部署文件 # 使用此链接下载后解压即可 wget https://github.com/prometheus-operator/kube-prometheus/archive/refs/heads/release-0.13.zip2、根据k8s集群版本获取不同的kube-prometheus版本部署 https://github.com/prometheus-operator/k…