单链表的应用

文章目录

  • 目录
    • 1. 单链表经典算法OJ题目
      • 1.1 [移除链表元素](https://leetcode.cn/problems/remove-linked-list-elements/description/)
      • 1.2 [链表的中间节点](https://leetcode.cn/problems/middle-of-the-linked-list/description/)
      • 1.3 [反转链表](https://leetcode.cn/problems/reverse-linked-list/description/)
      • 1.4 [合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/description/)
      • 1.5 [分割链表](https://leetcode.cn/problems/partition-list-lcci/description/)
      • 1.6 [环形链表的约瑟夫问题](https://www.nowcoder.com/practice/41c399fdb6004b31a6cbb047c641ed8a)
    • 2. 基于单链表再实现通讯录项目

目录

  • 单链表经典算法OJ题目
  • 基于单链表再实现通讯录项目

1. 单链表经典算法OJ题目

1.1 移除链表元素

移除链表元素

#include <stdio.h>typedef struct ListNode
{int val;struct ListNode* next;
}ListNode;struct ListNode* removeElements(struct ListNode* head, int val)
{//定义新链表的头尾指针ListNode* newHead, * newTail;newHead = newTail = NULL;ListNode* pcur = head;while (pcur){//不是val,尾插到新链表if (pcur->val != val){if (NULL == newHead){//链表为空newHead = newTail = pcur;}else{//链表不为空newTail->next = pcur;newTail = newTail->next;}pcur = pcur->next;}else{ListNode* del = pcur;pcur = pcur->next;free(del);del = NULL;}}if (newTail)//为了防止传过来的是空链表,newTail为空;或者链表中都是同一个值,而正好删除的是这个值,删完之后新链表中newTail依然是空{newTail->next = NULL;}return newHead;
}

1.2 链表的中间节点

链表的中间节点

typedef struct ListNode
{int val;struct ListNode* next;
}ListNode;struct ListNode* middleNode(struct ListNode* head)
{ListNode* slow, * fast;slow = fast = head;//满足任意一个条件就跳出循环while (fast && fast->next)//有一个为假都不应该进入循环{//慢指针每次走一步,快指针每次走两步slow = slow->next;fast = fast->next->next;}return slow;
}

1.3 反转链表

反转链表

#include <stdio.h>typedef struct ListNode
{int val;struct ListNode* next;
}ListNode;struct ListNode* reverseList(struct ListNode* head)
{//处理空链表if (NULL == head){return head;}//先创建三个指针ListNode* n1, * n2, * n3;n1 = NULL, n2 = head, n3 = head->next;//遍历原链表,修改节点指针的指向while (n2){//修改n2的指向n2->next = n1;//修改三个指针的位置n1 = n2;n2 = n3;if (n3){n3 = n3->next;}}return n1;
}

1.4 合并两个有序链表

合并两个有序链表

#include <stdio.h>typedef struct ListNode
{int val;struct ListNode* next;
}ListNode;struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{if (NULL == list1){return list2;}if (NULL == list2){return list1;}ListNode* l1, * l2;l1 = list1, l2 = list2;ListNode* newHead, * newTail;newHead = newTail = NULL;while (l1 && l2){if (l1->val < l2->val){//l1小,插入到新链表中if (NULL == newHead){//链表为空,头尾指针都指向该节点newHead = newTail = l1;}else{//链表不为空newTail->next = l1;newTail = newTail->next;}l1 = l1->next;}else{//l2小,插入到新链表中if (NULL == newHead){//链表为空newHead = newTail = l2;}else{//链表不为空newTail->next = l2;newTail = newTail->next;}l2 = l2->next;}}//跳出循环存在两种情况:要么l1走到空了l2不为空,要么l2走到空了l1不为空//不可能存在都为空的情况if (l1){newTail->next = l1;}if (l2){newTail->next = l2;}return newHead;
}

但是我们会发现以上代码在l1小或l2小时把数据插入到新链表中都要判断链表是否为空,出现了代码的重复,我们应该如何优化呢?

代码重复的根源在于链表可能会出现为空的情况,那么我们就创建一个头节点(这里的头就是带头链表中的头,是哨兵位,不存储有效的数值),让链表不可能存在为空的情况,就可以避免代码重复。

#include <stdio.h>
#include <stdlib.h>typedef struct ListNode
{int val;struct ListNode* next;
}ListNode;struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{if (NULL == list1){return list2;}if (NULL == list2){return list1;}ListNode* l1, * l2;l1 = list1, l2 = list2;ListNode* newHead, * newTail;newHead = newTail = (ListNode*)malloc(sizeof(ListNode));while (l1 && l2){if (l1->val < l2->val){//l1小,插入到新链表中newTail->next = l1;newTail = newTail->next;l1 = l1->next;}else{//l2小,插入到新链表中newTail->next = l2;newTail = newTail->next;l2 = l2->next;}}//跳出循环存在两种情况:要么l1走到空了l2不为空,要么l2走到空了l1不为空//不可能存在都为空的情况if (l1){newTail->next = l1;}if (l2){newTail->next = l2;}//malloc了空间,但是这块空间实际用不了,应该将其释放掉ListNode* ret = newHead->next;free(newHead);newHead = newTail = NULL;return ret;
}

1.5 分割链表

分割链表

#include <stdio.h>
#include <stdlib.h>typedef struct ListNode
{int val;struct ListNode* next;
}ListNode;struct ListNode* partition(struct ListNode* head, int x)
{if (NULL == head){return head;}//创建带头的大小链表ListNode* lessHead, * lessTail;ListNode* greaterHead, * greaterTail;lessHead = lessTail = (ListNode*)malloc(sizeof(ListNode));greaterHead = greaterTail = (ListNode*)malloc(sizeof(ListNode));//遍历原链表,将节点放到对应的新链表中ListNode* pcur = head;while (pcur){if (pcur->val < x){//放到小链表中lessTail->next = pcur;lessTail = lessTail->next;}else{//放到大链表中greaterTail->next = pcur;greaterTail = greaterTail->next;}pcur = pcur->next;}greaterTail->next = NULL;//大小链表进行首尾相连lessTail->next = greaterHead->next;ListNode* ret = lessHead->next;free(greaterHead);greaterHead = greaterTail = NULL;free(lessHead);lessHead = lessTail = NULL;return ret;
}

1.6 环形链表的约瑟夫问题

著名的Josephus问题:
据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39个犹太人与Josephus及他的朋友躲到⼀个洞中,39个犹太人决定宁愿死也不要被人抓到,于是决定了一个自杀方式,41个人排成⼀个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下⼀个重新报数,直到所有人都自杀身亡为止。然而Josephus和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

环形链表的约瑟夫问题

#include <stdio.h>
#include <stdlib.h>typedef struct ListNode
{int val;struct ListNode* next;
}ListNode;ListNode* BuyNode(int x)
{ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));if (NULL == newNode){perror("BuyNode");exit(1);}newNode->val = x;newNode->next = NULL;return newNode;
}ListNode* createList(int n)
{ListNode* phead = BuyNode(1);ListNode* ptail = phead;for (int i = 2; i <= n; i++){ptail->next = BuyNode(i);ptail = ptail->next;}//链表要首尾相连使其循环起来ptail->next = phead;return ptail;//返回ptail的目的是避免prev为空,解决m = 1时出现的问题;这样写既能知道第一个节点的前驱节点,也能够通过尾节点找到第一个节点
}int ysf(int n, int m)
{//创建不带头单向循环链表ListNode* prev = createList(n);//定义prev来接收尾节点指针//逢m删除节点ListNode* pcur = prev->next;int count = 1;while (pcur->next != pcur){if (m == count){//删除当前节点pcurprev->next = pcur->next;free(pcur);//删除pcur节点之后,要让pcur走到新的位置,count置为初始值pcur = prev->next;count = 1;}else{//pcur往后走prev = pcur;pcur = pcur->next;count++;}}//此时pcur节点就是幸存下来的唯一的一个节点return pcur->val;
}

2. 基于单链表再实现通讯录项目

这里基于单链表实现通讯录项目和之前基于顺序表实现通讯录项目的步骤大致相同,思路是相通的,因此可以参考之前顺序表的应用这篇文章。

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

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

相关文章

考研数学|《1800》《660》《880》如何选择和搭配?(附资料分享)

直接说结论&#xff1a;基础不好先做1800、强化之前660&#xff0c;强化可选880/1000题。 首先&#xff0c;传统习题册存在的一个问题是题量较大&#xff0c;但难度波动较大。《汤家凤1800》和《张宇1000》题量庞大&#xff0c;但有些题目难度不够平衡&#xff0c;有些过于简单…

使用 ECharts 绘制咖啡店各年订单的可视化分析

使用 ECharts 绘制咖啡店各年订单的可视化分析 在这篇博客中&#xff0c;我将分享一段使用 ECharts 库创建可视化图表的代码。通过这段代码&#xff0c;我们可以直观地分析咖啡店各年订单的情况。 饼图 这段代码包含了两个 ECharts 图表&#xff0c;一个是饼图&#xff0c;用…

Linux安装及应用管理

目录 一.Linux应用程序基础 应用程序与系统命令的关系​编辑 典型应用程序的目录结构 常见的软件包封装类型 二.rpm软件包操作管理 RPM Red-Hat Package Manager rmp命令的格式 rpm软件包操作管理 查询已安装的RPM软件信息 查询未安装的RPM软件包文件中信息 安装、升…

1.SCI各模块

1.学会“抄” 写论文&#xff0c;一定要学会“抄”&#xff01;这样才能事半功倍&#xff0c;尤其是对于初次写作的新手&#xff0c;否则写作过程一定会让你痛不欲生&#xff0c;而且写出来的东西就是一坨shi&#xff0c;不仅折磨自己&#xff0c;也折磨导师。 写论文与建大楼…

基于STC12C5A60S2系列1T 8051单片机的带字库液晶显示器LCD12864数据传输并行模式显示32行点x128列点字模串的应用

基于STC12C5A60S2系列1T 8051单片机的带字库液晶显示器LCD12864数据传输并行模式显示32行点x128列点字模串的应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍液晶显…

Linux ARM平台开发系列讲解(QEMU篇) 1.2 新添加一个Linux kernel设备树

1. 概述 上一章节我们利用QEMU成功启动了Linux kernel,但是细心的小伙伴就会发现,我们用默认的defconfig是没有找到设备树源文件的,但是又发现kernel启动时候它使用了设备树riscv-virtio,qemu,这是因为qemu用了一个默认的设备树文件,该章节呢我们就把这个默认的设备树文件…

vs配置opencv运行时“发生生成错误,是否继续并运行上次的成功生成”BUG解决办法

vs“发生生成错误&#xff0c;是否继续并运行上次的成功生成” 新手在用vs配置opencv时遇到这个错误时&#xff0c;容易无从下手解决。博主亲身经历很有可能是release/debug模式和配置文件不符的问题。 在配置【链接器】→【输入】→【附加依赖项】环节&#xff0c;编辑查看选择…

node.js服务器动态资源处理

一、node.js服务器动态资源处理与静态资源处理的区别&#xff1f; 静态与动态服务器主要区别于是否读取数据库&#xff0c;若然在数据库中的资料处理中将数据转换成可取用格式的结构&#xff0c;也就是说把对象转化为可传输的字节序列过程称为序列化&#xff0c;反之则为反序列…

密码学 | 椭圆曲线密码学 ECC 入门(一)

目录 正文 1 公共密钥密码学的兴起 2 玩具版 RSA 算法 2.1 RSA 基本原理 2.2 RSA 举例说明 1 加密 2 解密 3 不是完美的陷门函数 ⚠️ 原文地址&#xff1a;A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography ⚠️ 写在前面&#xff1…

RocketMQ:Windows下开发环境搭建

一、准备工作 从RockitMQ官网下载 | RocketMQ下载最新的release包。我这里下载的版本是v5.2.0 解压到本地目录&#xff0c;bin目录下存放可运行的脚本。 二、RocketMQ基本结构 在动手开发之前&#xff0c;我们需要了解一下RocketMQ的基本结构 如上图所示&#xff0c;一个正常…

终于把所有的Python库,都整理出来啦!

前排推荐下我自己花了一年时间整理的三本在线文档&#xff0c;适用于每一个 Python 工程师。 第一本&#xff1a; PyCharm 中文指南 2.0 第二本&#xff1a; Python黑魔法手册 - Python黑魔法手册 2.0 第三本&#xff1a; Python中文指南 - Python中文指南 以下是下文&a…

ABAP - 三代增强 BADI

SAP ERP提供了大量的标准功能&#xff0c;但是用户的需求是多种多样的&#xff0c;如何使SAP的标准功能适应用户的需求就变得非常重要&#xff0c;SAP Enhancement技术允许我们对SAP的标准功能进行扩展&#xff0c;以满足用户的个性化需求&#xff1b;SAP保证所有的BADI向上兼容…

UE5 HLSL 详细学习笔记

这里的POSITION是变量Position的语义&#xff0c;告诉寄存器&#xff0c;此变量的保存位置&#xff0c;通常语义用于着色器的输入和输出&#xff0c;以冒号“&#xff1a;”的方式进一步说明此变量&#xff0c;COLOR也类似 还有什么语义呢&#xff1f; HLSL核心函数&#xff1a…

web 学习第六次课程

文章目录 定位 定位 <body><div style"height:100px;width:100px;border:#F00 1px solid;"></div><div style"height:100px;width:100px;border: #00F 1px solid;"></div> </body><body><div style"pos…

【模拟】Leetcode 外观数列

题目讲解 38. 外观数列 算法讲解 我们可以看到将相同的划分为一组&#xff0c;使用双指针然后遍历区间 class Solution { public:string countAndSay(int n) {string ret "1";while(--n){string temp;int left 0, right 0;//相同的归为一组for(; right < …

Java中使用JTS对空间几何计算(距离、点在面内、长度、面积、相交等)模拟的大概写法

场景 基于GIS相关的集成系统&#xff0c;需要对空间数据做一些判断处理。比如读取WKT数据、点到点、点到线、点到面的距离&#xff0c; 线的长度、面的面积、点是否在面内等处理。 JTS (Java Topology Suite) Java拓扑套件&#xff0c;是Java的处理地理数据的API。 github地址&…

华为ensp中aaa(3a)实现telnet远程连接认证配置命令

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月14日18点49分 AAA认证的全称是Authentication、Authorization、Accounting&#xff0c;中文意思是认证、授权、计费。 以下是详细解释 认证&#xff08;Authentic…

查看TensorFlow已训模型的结构和网络参数

文章目录 概要流程 概要 通过以下实例&#xff0c;你将学会如何查看神经网络结构并打印出训练参数。 流程 准备一个简易的二分类数据集&#xff0c;并编写一个单层的神经网络 train_data np.array([[1, 2, 3, 4, 5], [7, 7, 2, 4, 10], [1, 9, 3, 6, 5], [6, 7, 8, 9, 10]]…

ActiveMQ 07 集群配置

Active MQ 07 集群配置 官方文档 http://activemq.apache.org/clustering 主备集群 http://activemq.apache.org/masterslave.html Master Slave TypeRequirementsProsConsShared File System Master SlaveA shared file system such as a SANRun as many slaves as requ…

代理知识科普:为什么有的代理IP速度比较慢呢?

代理IP在跨境业务中被广泛的应用&#xff0c;今天我们将一同深入探讨一个问题&#xff1a;“为什么有的IP代理速度比较慢&#xff1f;”随着数字化时代的不断发展&#xff0c;代理服务成为了许多网络操作的关键环节。然而&#xff0c;有时我们可能会遇到IP代理速度慢的问题&…