C、C++常用数据结构:链表
文章目录
- 基本概念
- 链表的创建
- 链表结点定义
- 链表创建
- 链表遍历
- 链表释放
- 链表查找
- 链表删除
- 链表插入
- 测试用例
基本概念
参考:链表基础知识详解(非常详细简单易懂)-CSDN博客
- 链表是一种线性存储结构,链表在物理存储上是非连续的,数据元素的逻辑顺序通过链表中的指针链接
- 链表由一系列的结点组成,每个节点主要包含两个部分:数据域+指针域
- 数据域存放实际的数据;指针域存放下一个节点的地址(首地址)
- 链表分为单向链表和双向链表:单向链表由一个指针next,存放下一个节点的首地址;双向链表由next和previous,分别存放下一个节点和上一个节点的首地址
- 常见面试题:链表和数组的对比。链表的内存是不连续的,链表通过节点把离散的数据链接成一个表;而数组是通过开辟一段连续的内存来存储数据。数组成员和链表节点的数据类型可以是标准的C类型或者是用户自定义的类型。数组有起始地址和结束地址,链表没有明确的起始地址和结束地址,为了方便操作,可能会人为规定一个根节点(当然这是对于双向链表来说的,单向链表还是有头尾之分的)
以下代码只针对单链表
链表的创建
链表结点定义
// 定义一个链表节点结构体
typedef struct listNode
{int val;struct listNode *next;
} listNode;
链表创建
/*** 创建链表* 用到了二级指针要改变指针指向的值,传入指针要改变指针的指向(指针本身),传入二级指针*/
void listCreate(listNode **p_head, listNode *p_new)
{listNode *p_move = *p_head;if (*p_head == NULL){*p_head = p_new;}else{while (p_move->next != NULL){p_move = p_move->next;}p_move->next = p_new;p_new->next = NULL;}
}
链表遍历
/*** 遍历链表*/
void listPrint(listNode *head)
{if (head == NULL){cout << "list is NULL" << endl;return;}listNode *p = head;while (p != NULL){cout << p->val << " ";p = p->next;}cout << endl;
}
链表释放
/*** 释放链表*/
void listFree(listNode **head)
{listNode *p = *head;while (*head != NULL){p = *head;*head = (*head)->next;free(p);p = NULL; // 防止野指针}cout << "list free" << endl;
}
链表查找
/*** 链表查找*/
void listFind(listNode *head, int val)
{if (head == NULL)return;listNode *p = head;while (p != NULL){if (p->val == val){cout << "I find " << p->val;}p = p->next;}cout << endl;
}
链表删除
/*** 链表删除*/
void listDelete(listNode **head, int val)
{if (*head == NULL){return;}listNode *slow = NULL;listNode *fast = *head;while (fast != NULL){if (fast->val == val){if (fast == *head){*head = (*head)->next;free(fast);cout << "delete done" << endl;fast = *head;}else{slow->next = fast->next;free(fast);cout << "delete done" << endl;fast = slow->next;}}else{slow = fast;fast = fast->next;}}
}
链表插入
/*** 链表插入* 根据val值来判断插入位置(从小到大)*/
void listInsert(listNode **head, listNode *p_new)
{// 如果链表为空,则插入的结点为头结点if (*head == NULL){*head = p_new;p_new->next = NULL;return;}// 定义快慢指针listNode *slow = NULL;listNode *fast = *head;while (p_new->val >= fast->val && fast->next != NULL){slow = fast;fast = fast->next;}if (p_new->val < fast->val) // 如果找到了大于新结点val的结点,则新结点插入该结点左边{if (fast == *head){p_new->next = *head;*head = p_new;}else{p_new->next = slow->next;slow->next = p_new;}}else // 没有找到就插入右边{fast->next = p_new;p_new->next = NULL;}
}
测试用例
#include <iostream>
#include <vector>
#include <cstdio>using namespace std;// 定义一个链表节点结构体
typedef struct listNode
{int val;struct listNode *next;
} listNode;/*** 创建链表* 用到了二级指针要改变指针指向的值,传入指针要改变指针的指向(指针本身),传入二级指针*/
void listCreate(listNode **p_head, listNode *p_new)
{listNode *p_move = *p_head;if (*p_head == NULL){*p_head = p_new;}else{while (p_move->next != NULL){p_move = p_move->next;}p_move->next = p_new;p_new->next = NULL;}
}/*** 遍历链表*/
void listPrint(listNode *head)
{if (head == NULL){cout << "list is NULL" << endl;return;}listNode *p = head;while (p != NULL){cout << p->val << " ";p = p->next;}cout << endl;
}/*** 释放链表*/
void listFree(listNode **head)
{listNode *p = *head;while (*head != NULL){p = *head;*head = (*head)->next;free(p);p = NULL; // 防止野指针}cout << "list free" << endl;
}/*** 链表查找*/
void listFind(listNode *head, int val)
{if (head == NULL)return;listNode *p = head;while (p != NULL){if (p->val == val){cout << "I find " << p->val;}p = p->next;}cout << endl;
}/*** 链表删除*/
void listDelete(listNode **head, int val)
{if (*head == NULL){return;}listNode *slow = NULL;listNode *fast = *head;while (fast != NULL){if (fast->val == val){if (fast == *head){*head = (*head)->next;free(fast);cout << "delete done" << endl;fast = *head;}else{slow->next = fast->next;free(fast);cout << "delete done" << endl;fast = slow->next;}}else{slow = fast;fast = fast->next;}}
}/*** 链表插入* 根据val值来判断插入位置(从小到大)*/
void listInsert(listNode **head, listNode *p_new)
{// 如果链表为空,则插入的结点为头结点if (*head == NULL){*head = p_new;p_new->next = NULL;return;}// 定义快慢指针listNode *slow = NULL;listNode *fast = *head;while (p_new->val >= fast->val && fast->next != NULL){slow = fast;fast = fast->next;}if (p_new->val < fast->val) // 如果找到了大于新结点val的结点,则新结点插入该结点左边{if (fast == *head){p_new->next = *head;*head = p_new;}else{p_new->next = slow->next;slow->next = p_new;}}else // 没有找到就插入右边{fast->next = p_new;p_new->next = NULL;}
}int main(int argc, char const *argv[])
{listNode *head = NULL, *p_new = NULL;int num = 0;for (int i = 0; i < 10; i++){p_new = (listNode *)malloc(sizeof(listNode));p_new->val = i;listCreate(&head, p_new);}listPrint(head);listFind(head, 3);listDelete(&head, 3);listPrint(head);cout << "结点插入测试" << endl;listNode *p_insert = (listNode *)malloc(sizeof(listNode));p_insert->val = 3;listInsert(&head, p_insert);listPrint(head);listFree(&head);return 0;
}
相关文章:

C、C++常用数据结构:链表
文章目录 基本概念链表的创建链表结点定义链表创建 链表遍历链表释放链表查找链表删除链表插入测试用例 基本概念 参考:链表基础知识详解(非常详细简单易懂)-CSDN博客 链表是一种线性存储结构,链表在物理存储上是非连续的…...

【devops】devops-ansible之剧本变量使用
本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》:python零基础入门学习 《python运维脚本》: python运维脚本实践 《shell》:shell学习 《terraform》持续更新中:terraform_Aws学习零基础入门到最佳实战 《k8》从问题中去学习k8s 《docker学习》暂未更…...

《Linux从小白到高手》理论篇:一文概览常用Linux重要配置文件
List item 今天继续宅家,闲来无事接着写。本篇是《Linux从小白到高手》理论篇的最后一篇了。本篇集中介绍所有常用的Linux重要配置文件。 用这个命令可以查看配置文件所在的位置:如上图 locate "*.conf" "*.ini" "*.cfg&quo…...

采购管理流程:掌握最后阶段的关键要点
采购管理流程是企业运作中的核心职能之一,涵盖了获取商品和服务的一系列步骤,旨在以高效率和经济效益的方式进行。深入理解该流程的每个环节极为关键,特别是最后阶段,这可确保所有采购活动的圆满完成以及与供应商维持良好关系。 …...

cherry-markdown开源markdown组件详细使用教程
文章目录 前言开发定位目标调研技术方案前提工作量安排数据库表设计实现步骤1、引入依赖2、实现cherry-markdown的vue组件(修改上传接口路径)3、支持draw.io组件4、支持展示悬浮目录toc前端使用:编辑状态使用cherry-markdown的vue组件前端使用…...

Android SystemUI组件(10)禁用/重启锁屏流程分析
该系列文章总纲链接:专题分纲目录 Android SystemUI组件 本章关键点总结 & 说明: 说明:本章节持续迭代之前章节的思维导图,主要关注左侧上方锁屏分析部分 应用入口处理流程解读 即可。 在 Android 系统中,禁用锁屏…...

【Geeksend邮件营销】外贸邮件中的一些常用语
外贸邮件中的相关术语丰富多样,涉及邮件的开头、正文、结尾以及特定的商务用语。以下是一些常用的外贸邮件术语及其解释: 一、邮件开头用语 1、问候语: Dear [收件人姓名], Trust this email finds you well. How are you? …...

配置静态ip
背景:因业务需要需要将一台服务器从机房搬到实验室,机房是光纤,实验室是网线,需要重新配置下静态ip 确认网络配置文件(网上没找到,不清楚一下方法对不对) 先随便一个网口连接网线,执行 ifconfig -a 找到带“RUNNING”的(lo不是哈)----eno1 到/etc/sysconfig/network…...

[LeetCode] LCR170. 交易逆序对的总数
题目描述: 在股票交易中,如果前一天的股价高于后一天的股价,则可以认为存在一个「交易逆序对」。请设计一个程序,输入一段时间内的股票交易记录 record,返回其中存在的「交易逆序对」总数。 示例 1: 输入:…...

大开眼界,原来指针还能这么玩?
文章目录 第一阶段:基础理解目标:内容:题目:答案解析: 第二阶段:指针与数组目标:内容:题目:答案解析: 第三阶段:指针与字符串目标:内容…...

揭秘选择知识产权管理系统的常见误区,避免踩坑
在当今知识经济时代,知识产权管理对于企业的发展至关重要。为了提高管理效率和效果,许多企业纷纷选择采用知识产权管理系统。然而,在选择过程中,存在着一些容易陷入的误区。 误区一:只关注功能,忽视用户体验…...

计算机组成原理之存储器的分类
1、按存储介质分类: 半导体存储器:使用半导体器件作为存储元件,如TTL和MOS存储器。这类存储器体积小、功耗低、存取时间短,但断电后数据会丢失。 磁表面存储器:使用磁性材料涂覆在金属或塑料基体表面作为存储介质&…...

Linux(不同版本系统包含Ubuntu)下安装mongodb详细教程
一、下载MongoDB 在MongoDB官网下载对应的MongoDB版本,可以点击以下链接快速跳转到下载页面: mongodb官网下载地址 注意选择和自己操作系统一致的platform,可以先查看自己的操作系统 查看操作系统详情 命令: uname -a 如图:操…...

如何扫描HTTP代理:步骤与注意事项
HTTP代理是一个复杂的过程,通常用于寻找可用的代理服务器,以便在网络中实现匿名或加速访问。虽然这个过程可以帮助用户找到适合的代理,但也需要注意合法性和道德问题。本文将介绍如何扫描HTTP代理,并提供一些建议和注意事项。 什…...

【分布式微服务云原生】gRPC与Dubbo:分布式服务通信框架的双雄对决
目录 引言gRPC:Google的高性能RPC框架gRPC通信流程图 Dubbo:阿里巴巴的微服务治理框架Dubbo服务治理流程图 表格:gRPC与Dubbo的比较结论呼吁行动Excel表格:gRPC与Dubbo特性总结 摘要 在构建分布式系统时,选择合适的服务…...

Python | Leetcode Python题解之第450题删除二叉搜索树中的节点
题目: 题解: class Solution:def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:cur, curParent root, Nonewhile cur and cur.val ! key:curParent curcur cur.left if cur.val > key else cur.rightif cur i…...

[Linux]从零开始的网站搭建教程
一、谁适合本次教程 学习Linux已经有一阵子了,相信大家对LInux都有一定的认识。本次教程会教大家如何在Linux中搭建一个自己的网站并且实现内网访问。这里我们会演示在Windows中和在Linux中如何搭建自己的网站。当然,如果你没有Linux的基础,这…...

牛客——xay loves or与 __builtin_popcount的使用
xay loves or 题目描述 登录—专业IT笔试面试备考平台_牛客网 运行思路 题目要求我们计算有多少个正整数 yy 满足条件 x \text{ OR } y sx OR ys。这里的“OR”是指按位或运算。为了理解这个问题,我们需要考虑按位或运算的性质。 对于任意两个位 a_iai 和 b_…...

Docker学习和部署ry项目
文章目录 停止Docker重启设置开机自启执行docker ps命令,如果不报错,说明安装启动成功2.然后查看数据卷结果3.查看数据卷详情结果4.查看/var/lib/docker/volumes/html/_data目录可以看到与nginx的html目录内容一样,结果如下:5.进入…...

Linux中设置cd命令后直接显示当前目录下的所有文件
Linux中cd命令后默认是不显示该目录下的文件的,略微不方便。换个环境经常遇到需要重新设置的情况,网上已有很多发帖了,这里主要汇总下比较简单且常见的bash与csh下的设置方法。 实现的本质就是将"cd" 与 "ls"组合起来&am…...

【RTCP】报文学习笔记
在学习中,发现每一篇都只能窥探其中一部分内容。因此学习了多个大神的文章,记录如下: 参考希望_睿智 大神的文章:从零开始精通RTSP之深入理解RTCP协议, 大神对于细节表述非常到位。 read_book/RTP_RTCP /RTP_RTCP协议内容–精选自译.md 大神提供了更多更为详细的信息。 ZL…...

Solidity优质例子(二)物流的增删改查智能合约(附truffle测试)
本合约非常适合新手学习,其包含了基本的增删改查功能以及各个方式的不同之处的总结,本套合约我也编写了truffle测试,学习truffle测试的小伙伴也有福了~ 该合约的主要作用是通过区块链技术实现物流追踪系统的透明化、自动化与防篡改特性&#…...

对android binder的一些疑问及解答
1上层做了那么多封装是否是过度了,难度增加就在于上层的一层层的封装。 最底层直接ioctl和binder驱动交互(单纯c语言实现binder交互) 第一层:IPCThreadState.transatct封装了对驱动的请求和接受 第二层封装用IBinder.h里面…...

主流麦克风阵列有哪些?
麦克风阵列在HiFi音频方案中是非常重要的一种方案。它的重要性主要体现在音质提升、环境适应性、噪声处理和空间感创造等方面。以下是它的核心作用: 1. 高精度的声音捕捉 在HiFi音频解决方案中,清晰而高保真的声音捕捉是至关重要的。麦克风阵列可以通过…...

几个快速压缩图片大小的方法!
几个快速压缩图片大小的方法!在当今这个视觉主导的时代,图片已成为我们日常生活中不可或缺的一部分,它们承载着从壮丽风景到办公文档的各类信息,每个人的电子设备中,往往都保存着海量的图片文件,然而&#…...

怎么避免在pod产生-派生炸弹(Fork Bomb)? k8s(kubernetes)
通过修改kubelet的配置,限制每个pod能用的pid数量即可解决此问题。 kubelet 可以通过设置PodPidsLimit参数来限制每个容器内的进程数量。 1.【kubelet节点】 /var/lib/kubelet/config.yaml文件中添加如下的内容 # 500仅仅是举例 podPidsLimit: 5002.【kubelet节点…...

MySQL中的嵌套查询
1. 嵌套查询的定义 嵌套查询指在一个查询语句的某个部分嵌入一个子查询。 嵌套查询的执行过程遵循“先子查询、后外层查询”的逻辑。首先,子查询执行并返回一个结果集,可能是一个值、一行或多行数据。接着,外层查询使用子查询的结果继续对数…...

win10 提示pl2303hxa已停产,请联系供货商解决方案
1. 下载驱动 需要下载老版的驱动,下载地址:https://www.pcsoft.com.cn/soft/211569.html 选择普通下载 或者从CSDN下载: 2. 安装驱动 下载完成后安装下载好的驱动文件,安装后更新pl2303的驱动,如下:…...

浙大数据结构:07-图5 Saving James Bond - Hard Version
这道题也是很有难度,我最开始尝试用Dijkstra来做,发现不是很好处理,用bfs还不错。 机翻: 1、条件准备 n为鳄鱼数量,jump为跳跃距离,headjump为第一次跳跃距离,包括了岛的半径。 isalive标识…...

【Verilog学习日常】—牛客网刷题—Verilog企业真题—VL69
脉冲同步器(快到慢) 描述 sig_a 是 clka(300M)时钟域的一个单时钟脉冲信号(高电平持续一个时钟clka周期),请设计脉冲同步电路,将sig_a信号同步到时钟域 clkb(100M&…...