考研408每周一题(2019 41)
2019年(单链表)
41.(13分)设线性表L=(a1,a2,a3,...,a(n-2),a(n-1),an)采用带头结点的单链表保存,链表中的结点定义如下:
typedef struct node {int data;struct node *next;
} NODE;
请设计一个空间复杂度为O(1)且时间上尽可能高效的算法,重新排列L中的各个结点,得到线性表L'=(a1,an,a2,a(n-1),a3,a(n-2),...)。要求:
(1)给出算法的基本设计思想
我们将n用数字代入进去,比如n=7,那么L也就是如下图所示
a1 | a2 | a3 | a4 | a5 | a6 | a7 |
重新排列组合之后的L'
a1 | a7 | a2 | a6 | a3 | a5 | a4 |
很容易就能发现一下规律,将链表L断开(断链),将链表尾进行反转(逆置),最后重新组合成一条新的链表。这个我们用三个函数(list_spilt、list_reverse、list_merge)来对链表L进行操作。
(2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释
环境:Visual Studio 2022
语言:C++
代码如下图所示:
链表断链
//链表断链
void list_spilt(LinkList L, LinkList& L2) {LinkList q, p;L2 = (LinkList)malloc(sizeof(Lnode));//将p和q进行初始化p = q = L->next;//需要对当前指针进行判断//如果当前指针为空的情况//开始遍历while (p) {p = p->next;//防止链表只有一个结点的情况if (p == NULL) {break;}p = p->next;//为了偶数个的情况进行判断if (p == NULL) {break;}q = q->next;}//L2的相关操作//将L2的链表头节点指向当前链表的中间结点qL2->next = q->next;//将中间结点q的next置为NULL(即为L链表的断链)q->next = NULL;
}
顾名思义就是将链表一分为二,这里我们用快慢指针,快指针p走两步,慢指针q走一步,保证快指针始p终走的比慢指针q多一个单位,因此 ,循环的条件就是快指针p不为空,考虑到p为空的情况,循环即结束。
当进入到第四次循环,也就是p->next==NULL的时候,此时q->next指向a4如上图所示。
从q这里断链,L2中的数据也就包含a5,a6,a7。
时间复杂度:因为p每次移动两步(即为两个结点),故其循环的次数就是n/2,忽略首项系数就是O(n)。
注意:但凡涉及到链表的结构修改操作,需要在函数的形参上加上&(取地址符),C++的引用操作
链表反转(逆置)
//链表反转(逆置)
void list_reverse(LinkList L2) {LinkList r, s, t;r = L2->next;//链表为空的情况if (r == NULL) return;s = r->next;//链表只有一个结点的时候if (s == NULL) return;t = s->next;while (t) {s->next = r;//指针反转r = s;s = t;t = t->next;}s->next = r;//逆置后,链表的第一个结点即为尾结点L2->next->next = NULL;//L2指向现链表的头结点sL2->next = s;
}
这里我们用三个指针操控,r,s,t。由于链表的特性,我们只需要改变指针的指向即可完成反转操作。需要判断两种情况。即链表为空的情况和链表只有一个结点的情况。直接返回即可。
这里我们用户距离最远的t作为循环的结束条件,只要t==NULL,循环即结束。
将s->next指向r,将s赋给r,t赋给s,t=t->next即可完成一次逆置操作,但因为一开始t是领先r两个位置的,故判断t==NULL循环结束时,实际上还有一次逆置操作没有完成,这里我们只需要将r的地址赋给s->next即可,这样便完成了逆置操作。剩下的就是些收尾工作。
时间复杂度:reverse函数只遍历了L2链表,遍历次数也是n/2,故时间复杂度为O(n)
注意:原先的链表头结点已经变成了尾结点,我们需要手动将其next置为空
而此时的链表头既是s,将s的地址赋给L2->next即可完成链表逆置的全部工作。
链表合并
//链表合并
void list_merge(LinkList L, LinkList L2) {LinkList p, q, pcur;p = L2->next;//p指L2的第一个结点pcur = L->next;//pcur始终指向组后的链表q = pcur->next;//q指向L1的第一个结点while (p && q) {pcur->next = p;p = p->next;pcur = pcur->next;pcur->next = q;q = q->next;pcur = pcur->next;}//任何一个链表都可能剩余一个结点,放进来即可if (p != NULL) {pcur->next = p;}if (q != NULL) {pcur->next = q;}
}
链表合并操作我们同样需要三个指针,一个指向L,一个指向L2,一个指向L’,循环的条件,判断L和L2链表当前不为空, 因为一开始即对pcur进行赋值为L->next,故往后操作只需要直接让其next指向L2->next也是p即可。个人感觉有点两个字符串交叉合并的意思。
一次操作:
pcur指向p(L2->next),p往后移动一步,再让pcur往后移动一步,让pcur指向q(L->next),q往后移一步,pcur再往后移动一步
- pcur->next = p;
- p = p->next;
- pcur = pcur->next;
- pcur->next = q;
- q = q->next;
- pcur = pcur->next;
时间复杂度:merge函数while的循环次数也是n/2,故时间复杂度为O(n)
即是以上六步,最后奇数个数据的链表会剩余一个结点的情况,我们直接将其放入新链表L’即可。
以下是全部代码:
#include<stdio.h>
#include<stdlib.h>
//考研链表题练习
typedef int ElemType;
typedef struct Lnode {ElemType data;struct Lnode* next;
}Lnode, * LinkList;//尾插法建立链表
void list_tail_insert(LinkList& L) {L = (LinkList)malloc(sizeof(Lnode));ElemType num;LinkList q, p;q = L;scanf_s("%d", &num);while (num != 9999) {p = (LinkList)malloc(sizeof(Lnode));p->data = num;q->next = p;q = p;scanf_s("%d", &num);}p->next = NULL;
}
//链表断链
void list_spilt(LinkList L, LinkList& L2) {LinkList q, p;L2 = (LinkList)malloc(sizeof(Lnode));//将p和q进行初始化p = q = L->next;//需要对当前指针进行判断//如果当前指针为空的情况//开始遍历while (p) {p = p->next;//防止链表只有一个结点的情况if (p == NULL) {break;}p = p->next;//为了偶数个的情况进行判断if (p == NULL) {break;}q = q->next;}//L2的相关操作//将L2的链表头节点指向当前链表的中间结点qL2->next = q->next;//将中间结点q的next置为NULL(即为L链表的断链)q->next = NULL;
}
//链表反转(逆置)
void list_reverse(LinkList L2) {LinkList r, s, t;r = L2->next;//链表为空的情况if (r == NULL) return;s = r->next;//链表只有一个结点的时候if (s == NULL) return;t = s->next;while (t) {s->next = r;//指针反转r = s;s = t;t = t->next;}s->next = r;//逆置后,链表的第一个结点即为尾结点L2->next->next = NULL;//L2指向现链表的头结点sL2->next = s;
}
//链表合并
void list_merge(LinkList L, LinkList L2) {LinkList p, q, pcur;p = L2->next;//p指L2的第一个结点pcur = L->next;//pcur始终指向组后的链表q = pcur->next;//q指向L1的第一个结点while (p && q) {pcur->next = p;p = p->next;pcur = pcur->next;pcur->next = q;q = q->next;pcur = pcur->next;}//任何一个链表都可能剩余一个结点,放进来即可if (p != NULL) {pcur->next = p;}if (q != NULL) {pcur->next = q;}
}//链表输出
void list_printf(LinkList L) {L = L->next;while (L) {printf("%3d ", L->data);L = L->next;}
}
int main() {//建立链表LinkList L, L2;//尾插法list_tail_insert(L);list_printf(L);//链表断链list_spilt(L, L2);printf("\n----------------list_spilt-----------------\n");list_printf(L2);//链表逆置list_reverse(L2);printf("\n----------------list_reverse---------------\n");list_printf(L2);//链表合并list_merge(L, L2);printf("\n----------------list_merge-----------------\n");list_printf(L);return 0;
}
代码效果:
偶数情况:
单数情况:
(3)说明你所设计的算法的时间复杂度
以上三个函数总的运行次数为(3/2)n,忽略首项系数,即为O(n)
相关文章:

考研408每周一题(2019 41)
2019年(单链表) 41.(13分)设线性表L(a1,a2,a3,...,a(n-2),a(n-1),an)采用带头结点的单链表保存,链表中的结点定义如下: typedef struct node {int data;struct node *next; } NODE; 请设计一个空间复杂度为O(1)且时间上尽可能高效的算法&…...

Angular学习笔记(一)
以下内容基于Angular 文档中文版的学习 目录 使用Angular CLI 工具创建项目 HTML标签中{{}}插入值,[]绑定属性,()绑定事件,[(ngModel)]双向绑定 绑定属性 类和样式绑定 事件绑定 双向绑定 循环 IF 定义输入属性 定义输出事件 特殊符号 模板引用变量 页面跳转(路由…...

Linux用户和权限 —— 操作演示
Linux用户和权限——操作演示认知root用户用户、用户组管理查看权限控制修改权限控制- chmod修改权限控制- chownLinux系列: Linux基本命令 —— 操作演示 认知root用户 root用户(超级管理员) 无论是Windows、MacOS、Linux均采用多用户的管理模式进行权限管理。…...

【华为OD机试真题2023 JAVA】单核CPU任务调度
华为OD机试真题,2023年度机试题库全覆盖,刷题指南点这里 单核CPU任务调度 知识点队列优先级队列 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 现在有一个CPU和一些任务需要处理,已提前获知每个任务的任务ID、优先级、所需执行时间和到达时间。 CPU同时只…...

News乐鑫科技亮相德国嵌入式展 Embedded World 2023!
3 月 14 日,德国纽伦堡嵌入式展 Embedded World 2023 火热启幕。本届 Embedded World 主题为 “embedded. responsible. sustainable”,乐鑫科技 (688018.SH) 携众多 AIoT 科技成果亮相展会,致力于打造更智能、更互联、更绿色的物联网未来。…...

java如何创建线程
java如何创建线程1. java如何创建线程1.1 通过继承Thread类来创建线程1.2 通过实现Runnable接口来创建线程1.3 通过匿名内部类来创建线程1.4 lambda表达式1.5 通过实现Runnable接口的方式创建线程目标类的优缺点1. java如何创建线程 一个线程在Java中使用一个Thread实例来描述…...

要是早看到这篇文章,你起码少走3年弯路,20年老程序员的忠告
文章目录前言一、程序员的薪资是怎么样的?二、我现在的情况适合做程序员吗?三、大学期间到底应该学些什么?四、工作还是考研?五、总结前言 我是龙叔,一名工作了20多年的退休老程序员。 如果你在工作之前看到这篇文章…...

IP地址的分类
1. 前言 最初设计互联网络时,为了便于寻址以及层次化构造网络,每个IP地址包括两个标识码(ID),即网络ID和主机ID。 同一个物理网络上的所有主机都使用同一个网络ID,网络上的一个主机(包括网络上工…...

win10下使用docker运行部署nginx,mysql
一、docker的步骤:1.进入docker官网下载安装包2.打开控制面板 - 程序和功能 - 启用或关闭Windows功能,勾选Hyper-V,然后点击确定即可,如图:3.重新启动电脑4.启动Docker在桌面找到Docker for Windows快捷方式࿰…...

sprinboot车辆充电桩
sprinboot车辆充电桩演示录像2022开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件:ecli…...

仿京东放大镜效果的实现
仿京东放大镜 (1) 整个案例可以分为三个功能模块 (2) 鼠标经过小图片盒子, 黄色的遮挡层 和 大图片盒子显示,离开隐藏2个盒子功能 (3)黄色的遮挡层跟随鼠标功能。 (4&…...

ESP32设备驱动-LM35温度传感器驱动
LM35温度传感器驱动 文章目录 LM35温度传感器驱动1、LM35介绍2、硬件准备3、软件准备4、驱动实现1、LM35介绍 LM35 系列是精密集成电路温度传感器,其输出电压与摄氏(摄氏度)温度成线性比例。 因此,LM35 优于以开尔文校准的线性温度传感器,因为用户无需从其输出中减去较大…...

基于深度学习的犬种识别软件(YOLOv5清新界面版,Python代码)
摘要:基于深度学习的犬种识别软件用于识别常见多个犬品种,基于YOLOv5算法检测犬种,并通过界面显示记录和管理,智能辅助人们辨别犬种。本文详细介绍博主自主开发的犬种检测系统,在介绍算法原理的同时,给出Py…...

【IDEA插件开发】环境搭建
基础信息 GRADLE 7.5.1 IDEA IntelliJ IDEA 2020.1.1 (Ultimate Edition) Build #IU-201.7223.91, built on April 30, 2020 Licensed to https://zhile.io You have a perpetual fallback license for this version Subscription is active until July 8, 2089 Runtime ve…...

【蓝桥杯专题】 DP(C++ | 洛谷 | acwing | 蓝桥)
菜狗现在才开始备战蓝桥杯QAQ 文章目录【蓝桥杯专题】 DP(C | 洛谷 | acwing | 蓝桥)AcWing 1205. 买不到的数目Acwing 1216. 饮料换购【模拟】01背包271. 杨老师的照相排列最长公共上升子序列PPPPPPPP总结【蓝桥杯专题】 DP(C | 洛谷 | acwi…...

咪咕MGV3201_ZG_GK国科6323_UWE5621DS_免拆卡刷固件包
咪咕MGV3201_ZG_GK国科6323_UWE5621DS_免拆卡刷固件包 特点: 1、适用于对应型号的电视盒子刷机; 2、开放原厂固件屏蔽的市场安装和u盘安装apk; 3、修改dns,三网通用; 4、大量精简内置的没用的软件,运行…...

重构数据-Change Value to Reference将实值对象改为引用对象三
重构数据-Change Value to Reference将实值对象改为引用对象三 1.将实值对象改为引用对象 1.1.实值对象和引用对象区别 下面通过客户Customer和订单Order两个对象介绍下它们的区别 值对象:当一个客户Customer下了多个订单Order后,每个订单类都将创建一…...

计算机网络——通信专业面试问题学习笔记
文章目录1、计算机网络这门课学了什么?目录里有多少章?2、Internet的概念与发展史3、什么是交换?三种交换方式4、OSI的七层协议, TCP/IP的四层协议, 五层协议5、WAN 、LAN 、MAN、PAN这些能分的清楚吗?全称分别都是什么࿱…...

代码随想录算法训练营第三十天 | 332.重新安排行程 51. N皇后 37. 解数独 总结
打卡第30天,回溯算法第二刷。 今日任务 332.重新安排行程51.N皇后37.解数独总结 332.重新安排行程 给你一份航线列表 tickets ,其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票都属于一个从…...

Windows权限提升—MySQL数据库提权
Windows权限提升—MySQL数据库提权1. 前言2. 数据库提权介绍2.1. 常见数据库端口2.2. MySQL数据库提权条件2.3. MySQL数据库提权类型3. MySQL中UDF提权3.1. UDF提权介绍3.2. UDF提权思路3.3. UDF提权步骤3.3.1. 获取外连数据库3.3.1.1. 外连数据库3.3.1.2. 连接数据库3.3.1.3. …...

使用旧电脑玩Linux
今天给大家讲讲使用旧电脑玩Linux,大家应该都知道旧电脑的硬件一般比较落后,特别是一些非常老的电脑,目前还在使用的是机械硬盘,如是要跑windows可想而知,但是Linux系统对硬件性能的要求可比windows低的多了࿰…...

Linux安装EMQX(简洁版)
安装目录 mkdir /opt/emqx && cd /opt/emqx 安装包下载 yum -y install wget && wget https://www.emqx.com/zh/downloads/broker/5.0.20/emqx-5.0.20-el7-amd64.tar.gz 注意:https://www.emqx.com/zh/downloads/broker获取下载链接并替换(后缀&…...

基于STM32 + FPGA 的软体机器人的 CAN总线运动控制器的设计
针对在软体机器人控制时,多电机协同控制过程中难度大、通用性差、协同性差等缺点,设计了基于 ARM和 FPGA的软体机器人的控制器局域网络 ( controller area network,CAN) 总线运动控制器,采用 ARMCortex-M4 …...

ROC曲线和AUC值
ROC曲线(Receiver Operating Characteristic,受试者工作特征)评价分类模型的可视化工具,是一条横纵坐标都限制在0-1范围内的曲线横坐标是假正率FPR,错误地判断为正例的概率纵坐标是真正率TPR,正确地判断为正…...

【vue.js】在网页中实现一个金属抛光质感的按钮
文章目录前言效果电脑效果手机效果说明完整代码index.html前言 诶?这有一个按钮(~ ̄▽ ̄)~,这是一个在html中实现的具有金属质感并且能镜面反射的按钮~ 效果 电脑效果 手机效果 说明 主要思路是使用 navig…...

android实现评论区功能
效果 activity_detail.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto"xmlns:tools"http…...

Java每日一练(20230319)
目录 1. 最大矩形 🌟🌟🌟 2. 回文对 🌟🌟🌟 3. 给表达式添加运算符 🌟🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练…...

Redis缓存双写一致性
目录双写一致性Redis与Mysql双写一致性canal配置流程代码案例双写一致性理解缓存操作细分缓存一致性多种更新策略挂牌报错,凌晨升级先更新数据库,在更新缓存先删除缓存,在更新数据库先更新数据库,在删除缓存延迟双删策略总结双写一致性 Redis与Mysql双写一致性 canal 主要是…...

【2023-Pytorch-检测教程】手把手教你使用YOLOV5做交通标志检测
项目下载地址:YOLOV5交通标志识别检测数据集代码模型教学视频-深度学习文档类资源-CSDN文库 交通标志的目标检测算法在计算机视觉领域一直属于热点研究问题,改进的优化算法不断地被提出。国内外许多学者针对现有的目标检测方法中网络结构、目标定位、损…...

Java中的二叉树
文章目录前言一、树形结构(了解)1.1 概念1.2 概念(重要)1.3 树的表示形式(了解)1.4 树的应用二、二叉树(重点)2.1 概念2.2 两种特殊的二叉树2.3 二叉树的性质2.5 二叉树的存储2.5 二…...