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

在这里插入图片描述

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

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

  • 引言
    • 一 概念
      • 头节点(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释放动态开辟…

vue2 在循环里,给字体加上随机颜色并加上随机图标且少重复

在循环里&#xff0c;给字体加上随机颜色并加上随机图标且少重复 <template><div class"pbfb5"><el-row :gutter"32"><el-col :xs"6" :sm"6" :lg"6" style"margin-bottom:32px;" v-for&quo…

(四)相关性分析 学习简要笔记 #统计学 #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;我们需要使用一些专业的清理软件来定期扫描和清除这…

CentOS服务器安装宝塔(图文详解)

宝塔的操作其实就是类似于把linux的指令使用方式&#xff0c;通过宝塔这个第三方工具进行可视化展示&#xff0c;但其实&#xff0c;他还是在操作linux&#xff0c;只是不需要你去记那么多的指令&#xff0c;宝塔把大多数的工具都集成到自己里面&#xff0c;这样你就可以在宝塔…

信号量Semaphore

什么是信号量&#xff1f; C中的信号量&#xff08;Semaphore&#xff09;是一种同步对象&#xff0c;用于控制对共享资源的访问&#xff0c;以防止多个线程或进程同时访问同一资源&#xff0c;从而避免数据不一致的问题。信号量通过维护一个计数值来实现这一功能&#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;也需要双方同意。 线程 …

Java并发体系--atomic--字段类

atomic--字段类 Atomic字段类是一种原子操作类&#xff0c;用于实现多线程环境下对共享变量的原子操作。它可以确保在并发情况下&#xff0c;对共享变量的操作是原子性的&#xff0c;不会出现线程安全问题。 Atomic字段类提供了一些方法&#xff0c;比如get()和set()方法用…

【Linux学习】Linux权限(二)

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

Ubuntu22.04.4 - Redis - 笔记

一、安装 sudo apt update sudo apt install redis-serverrootzheng:/etc# redis-cli --version redis-cli 6.0.16二、配置文件修改 配置文件地址 /etc/redis/redis.conf 1、开启远程访问 # 注释掉绑定地址#bind 127.0.0.1&#xff0c;让Redis可远程访问 # bind 127.0.0.1 …

论系统的安全架构的三个论点写一篇论文

撰写一篇围绕系统的安全架构三个论点的论文能够提供深刻的见解关于如何构建一个既安全又可靠的系统。接下来&#xff0c;我们将详细探讨这三个论点&#xff0c;并提供一个论文大纲来指导你如何组织和展开你的论述。 论文大纲 1. 引言 简要介绍系统安全架构的重要性&#xff…

Linux 内核的汇编级别的系统调用

2024年4月19日&#xff0c;周五下午 Linux 内核支持多种汇编级别的系统调用&#xff0c;这些系统调用通常以软中断&#xff08;soft interrupt&#xff09;的方式实现。 这里列举了一些常见的汇编级别的系统调用&#xff1a; x86 架构下的 int 0x80 调用&#xff1a;在 x86 架…

网盘——私聊

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

TLV262x系列单电源运算放大器

这份文件是德州仪器&#xff08;Texas Instruments&#xff09;关于TLV262x系列单电源运算放大器的数据手册。以下是该文件的核心内容概要&#xff1a; 产品系列描述&#xff1a; TLV262x系列是德州仪器&#xff08;Texas Instruments&#xff09;推出的一系列低功耗、宽带宽的…

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

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

VScode 里面使用 python 去直接调用 CUDA

上一个 帖子主要分享了如何 去将 C 程序 打包成一个package。 我们最后的 目的实际上是想把 CUDA 的程序 打包成 一个 Package &#xff0c; C 程序只是起到了桥梁的作用&#xff1a; 首先&#xff1a;CUDA 程序 和 C 的程序一样&#xff0c; 都有一个 .cu 的源文件和 一个 .…

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

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