如何在 C 语言中实现链表?

C语言

🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!
📙C 语言百万年薪修炼课程 通俗易懂,深入浅出,匠心打磨,死磕细节,6年迭代,看过的人都说好。

分割线

文章目录

  • C 语言中链表的实现
  • 一、链表的基本概念
  • 二、单向链表的节点结构
  • 三、创建链表节点
  • 四、向链表中插入节点
    • 4.1 头插法
    • 4.2 尾插法
  • 五、遍历链表
  • 六、删除链表节点
    • 6.1 删除头节点
    • 6.2 删除指定节点
  • 七、查找链表节点
  • 八、完整的示例代码

分割线


C 语言中链表的实现

链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。在 C 语言中实现链表可以让我们更灵活地管理数据。

一、链表的基本概念

链表中的节点通常由两部分组成:数据部分和指针部分。数据部分用于存储实际的数据,而指针部分用于指向下一个节点。

链表分为单向链表、双向链表和循环链表等类型。在本教程中,我们将重点介绍单向链表。

二、单向链表的节点结构

在 C 语言中,我们可以使用结构体来定义链表节点的结构:

typedef struct Node {int data;struct Node* next;
} Node;

在上述代码中,data 字段用于存储节点的数据,next 指针用于指向下一个节点。

三、创建链表节点

要创建一个新的链表节点,可以使用以下函数:

Node* createNode(int data) {Node* newNode = (Node*)malloc(sizeof(Node));if (newNode == NULL) {printf("内存分配失败\n");return NULL;}newNode->data = data;newNode->next = NULL;return newNode;
}

这个函数首先使用 malloc 函数在内存中分配一个新节点所需的空间。如果内存分配失败,返回 NULL 。然后,将传入的数据赋值给节点的数据字段,并将 next 指针初始化为 NULL

四、向链表中插入节点

4.1 头插法

头插法是将新节点插入到链表的头部。

void insertAtHead(Node** head, int data) {Node* newNode = createNode(data);newNode->next = *head;*head = newNode;
}

在这个函数中,首先创建一个新节点,然后让新节点的 next 指针指向当前的头节点,最后更新头节点指针,使其指向新节点。

4.2 尾插法

尾插法是将新节点插入到链表的尾部。

void insertAtTail(Node** head, int data) {Node* newNode = createNode(data);if (*head == NULL) {*head = newNode;return;}Node* curr = *head;while (curr->next!= NULL) {curr = curr->next;}curr->next = newNode;
}

这个函数首先创建一个新节点。如果链表为空,直接将新节点作为头节点。否则,遍历链表找到尾节点,然后将新节点连接到尾节点的后面。

五、遍历链表

遍历链表用于访问链表中的每个节点并处理其数据。

void traverseList(Node* head) {Node* curr = head;while (curr!= NULL) {printf("%d ", curr->data);curr = curr->next;}printf("\n");
}

在这个函数中,从链表的头节点开始,依次访问每个节点并打印其数据,直到遇到 NULL 指针,表示链表结束。

六、删除链表节点

6.1 删除头节点

void deleteHead(Node** head) {if (*head == NULL) {printf("链表为空,无法删除头节点\n");return;}Node* temp = *head;*head = (*head)->next;free(temp);
}

这个函数首先检查链表是否为空。如果不为空,保存头节点的指针,更新头节点指针指向下一个节点,然后释放原来头节点所占用的内存。

6.2 删除指定节点

void deleteNode(Node** head, int data) {Node* curr = *head;Node* prev = NULL;if (curr!= NULL && curr->data == data) {*head = curr->next;free(curr);return;}while (curr!= NULL && curr->data!= data) {prev = curr;curr = curr->next;}if (curr == NULL) {printf("未找到要删除的节点\n");return;}prev->next = curr->next;free(curr);
}

这个函数用于删除指定数据的节点。首先处理头节点,如果头节点的数据就是要删除的数据,更新头节点指针并释放头节点内存。然后遍历链表,找到要删除的节点,更新前一个节点的 next 指针,使其跳过要删除的节点,最后释放要删除节点的内存。

七、查找链表节点

Node* searchNode(Node* head, int data) {Node* curr = head;while (curr!= NULL) {if (curr->data == data) {return curr;}curr = curr->next;}return NULL;
}

这个函数从链表的头节点开始遍历,直到找到数据匹配的节点并返回其指针,如果未找到则返回 NULL

八、完整的示例代码

#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("内存分配失败\n");return NULL;}newNode->data = data;newNode->next = NULL;return newNode;
}// 头插法
void insertAtHead(Node** head, int data) {Node* newNode = createNode(data);newNode->next = *head;*head = newNode;
}// 尾插法
void insertAtTail(Node** head, int data) {Node* newNode = createNode(data);if (*head == NULL) {*head = newNode;return;}Node* curr = *head;while (curr->next!= NULL) {curr = curr->next;}curr->next = newNode;
}// 遍历链表
void traverseList(Node* head) {Node* curr = head;while (curr!= NULL) {printf("%d ", curr->data);curr = curr->next;}printf("\n");
}// 删除头节点
void deleteHead(Node** head) {if (*head == NULL) {printf("链表为空,无法删除头节点\n");return;}Node* temp = *head;*head = (*head)->next;free(temp);
}// 删除指定节点
void deleteNode(Node** head, int data) {Node* curr = *head;Node* prev = NULL;if (curr!= NULL && curr->data == data) {*head = curr->next;free(curr);return;}while (curr!= NULL && curr->data!= data) {prev = curr;curr = curr->next;}if (curr == NULL) {printf("未找到要删除的节点\n");return;}prev->next = curr->next;free(curr);
}// 查找节点
Node* searchNode(Node* head, int data) {Node* curr = head;while (curr!= NULL) {if (curr->data == data) {return curr;}curr = curr->next;}return NULL;
}int main() {Node* head = NULL;insertAtTail(&head, 10);insertAtTail(&head, 20);insertAtTail(&head, 30);insertAtHead(&head, 5);printf("链表元素: ");traverseList(head);Node* foundNode = searchNode(head, 20);if (foundNode!= NULL) {printf("找到节点: %d\n", foundNode->data);} else {printf("未找到节点\n");}deleteNode(&head, 20);printf("删除节点 20 后链表元素: ");traverseList(head);deleteHead(&head);printf("删除头节点后链表元素: ");traverseList(head);return 0;
}

在上述示例中,我们首先创建了一个空链表,然后通过头插法和尾插法向链表中插入节点。接着遍历链表,查找特定节点,删除指定节点和头节点,并再次遍历链表以验证操作结果。

希望这个详细的解释和示例能帮助您理解如何在 C 语言中实现链表。链表是一种基础但重要的数据结构,掌握它对于进一步学习更复杂的数据结构和算法非常有帮助。


分割线

🎉相关推荐

  • 📙C 语言百万年薪修炼课程 通俗易懂,深入浅出,匠心打磨,死磕细节,6年迭代,看过的人都说好。
  • 🍅博客首页-关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!
  • 📙CSDN专栏-C语言修炼
  • 📙技术社区-墨松科技

分割线



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

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

相关文章

vue子组件调用父组件方法

父组件 页面<popoverss ref"pop" :goodspop"goodspop"></popoverss>子组件components: {"popoverss": () > import(../comm/popover.vue)},方法goodspop(e){console.log(e"----")return 9999;},子组件 方法props:[go…

习题练习以

题意&#xff1a;求i&M的popcount的和&#xff0c;i属于0……N 主要思路还是变加为乘。 举个例子N22&#xff0c;即10110 假设M的第3位是1&#xff0c;分析N中&#xff1a; 00110 00111 00100 00101 发现其实等价于 0010 0011 0000 0001 也就是左边第4位和第5…

《AIGC:智能创作时代》:AI创作革命来临,你准备好了吗?

想象一下&#xff0c;你正在欣赏一幅精美的画作&#xff0c;惊叹于其细腻的笔触和独特的构图。然而&#xff0c;当你得知这幅作品是由人工智能创作时&#xff0c;你会作何感想&#xff1f;这不再是科幻小说中的场景&#xff0c;而是我们正在经历的现实。 在这个AI技术飞速发展的…

QListWidget、QTreeWidget、QTableWidget的拖放

QListWidget、QTreeWidget、QTableWidget的拖放实验 QAbstractItemView::DragDropMode 的枚举值 QAbstractItemView::NoDragDrop0组件不支持拖放操作QAbstractItemView::DragOnly1组件只支持拖动操作QAbstractItemView::DropOnly 2组件只支持放置操作QAbstractItemView::DragDr…

AI 图像处理 --CodeFormer 简介

CodeFormer是一款基于深度学习技术&#xff0c;特别是利用自动编码器和VQGAN&#xff08;Vector Quantised Generative Adversarial Network&#xff09;进行人脸修复和视频增强的强大人工智能工具。它通过高分辨率重建和细节修复&#xff0c;显著提升了图像和视频的质量和视觉…

Django 视图 - FBV 与 CBV

Django 视图 - FBV 与 CBV 在 Django 框架中,视图是处理 Web 请求和返回 Web 响应的核心组件。Django 提供了两种主要的视图编写方式:函数基础视图(Function-Based Views,简称 FBV)和类基础视图(Class-Based Views,简称 CBV)。这两种方式各有特点,适用于不同的场景。…

WPF设置全局样式

目的 创建一个资源字典&#xff0c;自动引入到各个Window或者UserControl中&#xff0c;可以随意使用。或者引入多个控件包&#xff0c;为了做兼容&#xff0c;保证可以引用多个控件库。 1. 定义资源字典 首先&#xff0c;你需要创建一个XAML文件来定义你的资源字典&#xf…

Python中JSON处理技术的详解

引言 JSON&#xff08;JavaScript Object Notation&#xff09;作为当前最流行的数据传输格式&#xff0c;在Python中也有多种实现方式。由于JSON的跨平台性和简便易用性&#xff0c;它在数据交互中被广泛应用。本文将重点讨论如何熟练应用Python的JSON库&#xff0c;将JSON数…

生日判断星座【GO】

文章目录 星座列表生日转换为星座 星座列表 const (Aries "aries"Taurus "taurus"Gemini "gemini"Cancer "cancer"Leo "leo"Virgo "virgo"Libra "libra&q…

小红书后端

牛客网 - 找工作神器|笔试题库|面试经验|实习招聘内推&#xff0c;求职就业一站解决_牛客网 (nowcoder.com) 小红书推荐系统 题目&#xff1a; 思路&#xff1a; 尝试&#xff08;标题4&#xff09; import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息…

FFmpeg 实现从麦克风获取流并通过RTMP推流

使用FFmpeg库实现从麦克风获取流并通过RTMP推流&#xff0c;FFmpeg版本为4.4.2-0。RTMP服务器使用的是SRS&#xff0c;我这边是跑在Ubuntu上的&#xff0c;最好是关闭掉系统防火墙。拉流端使用VLC。如果想要降低延时&#xff0c;请看我另外一篇博客&#xff0c;里面有说降低延时…

github 下载提速的几种方法

1. 代理下载&#xff08;无需注册&#xff09; //toolwa.com/github/ //d.serctl.com/2. 转入 Gitee 加速 将项目镜像到 Gitee 中下载加速 3. 使用 Watt Toolkit 加速 Watt Toolkit //steampp.net/选择合适的版本下载 选择 github&#xff0c;一键加速 4.CDN 加速 (修改…

html转markdown nodejs实现

用到了jsdom库&#xff0c;直接现成处理html标签结构&#xff0c;只需要关心format格式化样式即可。 比较简易&#xff0c;待后续优化&#xff0c;目前只是短时间批量转换html文件。 const { JSDOM } require(jsdom);const getText (htmlString) > {if (!htmlString) re…

浏览器开发者视角及CSS表达式选择元素

点击想要查看的接口&#xff0c;然后点击检查&#xff0c;便可以切换到该接口对应的html代码 如果F12不起作用的话&#xff0c;点击更多工具&#xff0c;然后选择开发者工具即可 ctrlF可以去查阅相关的CSS表达式选择元素 如果没有加#t1&#xff0c;那么表示的是选择所有的p 使用…

图解HTTP(5、与 HTTP 协作的 Web 服务器 6、HTTP 首部)

5、与 HTTP 协作的 Web 服务器 一台 Web 服务器可搭建多个独立域名的 Web 网站&#xff0c;也可作为通信路径上的中转服务器提升传输效率。 用单台虚拟主机实现多个域名 在相同的 IP 地址下&#xff0c;由于虚拟主机可以寄存多个不同主机名和域名的 Web 网站&#xff0c;因此…

Linux-多线程

线程的概念 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“一个进程内部的控制序列”一切进程至少都有一个执行线程线程在进程内部运行&#xff0c;本质是在进程地址空间内运行在Linux系统中&#xff0c;在CPU眼中…

Labview_压缩文件

调用顺序 源文件 生成后的文件 1.新建ZIP文件 生成ZIP文件的路径&#xff1a;为最终生成ZIP文件的路径&#xff0c;需要提供ZIP文件的名称和类型 2.添加文件到压缩文件 源文件路径&#xff1a;为需要压缩的文件路径&#xff0c;非文件夹路径 生成ZIP文件时的路径&#x…

Elasticsearch 缓存策略详解:优化你的搜索体验

目录 1. Elasticsearch缓存机制概述 2. 缓存机制的详细解析 2.1 节点查询缓存 2.2 分片请求缓存 2.3 字段数据缓存 2.4 分片查询缓存 3. 合理缓存比例设置 3.1 节点查询缓存 3.2 分片请求缓存 3.3 字段数据缓存 3.4 分片查询缓存 4. 缓存监控与调优 5.实战调优 5…

区域特征检测工具的使用

区域特征检测工具的使用 选择区域-》右键-》工具->特征检测

实践致知第12享:如何新建一个Word并设置格式

一、背景需求 小姑电话说&#xff1a;要新建一个Word文档&#xff0c;并将每段的首行设置空2格。 二、解决方案 1、在电脑桌面上空白地方&#xff0c;点击鼠标右键&#xff0c;在下拉的功能框中选择“DOC文档”或“DOCX文档”都可以&#xff0c;如下图所示。 之后&#xff0…