[数据结构习题]链表——单链表重排

news2024/11/23 9:32:53

[数据结构习题]链表——单链表重排



👉知识点导航💎:【数据结构】线性表——顺序存储

👉知识点导航💎:【数据结构】线性表——链式存储

👉[王道数据结构]习题导航💎: p a g e 41.25 page41.25 page41.25

本节为链表相关操作的习题

在这里插入图片描述



☀️题目描述:

在这里插入图片描述



🎇思路:单链表逆置

🔱思路分析:

题目解析:我们先分析题目,对于初始单链表 L ( a 1 , a 2 , a 3 , . . . , a n ) L(a1,a2,a3,...,an) L(a1,a2,a3,...,an)和目标单链表 L ′ ( a 1 , a n , a 2 , a n − 1 , . . . ) L'(a1,an,a2,a_{n-1},...) L(a1,an,a2,an1,...),不难发现 L ′ L' L是通过 L L L摘取第 1 1 1和第 n n n个元素,再摘取第 2 2 2和第 n − 1 n-1 n1元素,…,最后摘取第 k k k和第 n − k + 1 n-k+1 nk+1个元素(奇数个结点时也可能没有),最后拼接而成的单链表


即首尾对应依次取出,可以分为前后两段,一个指针不断向后,一个指针不断向前?
在这里插入图片描述

这就是这道题的关键问题:单链表只能从前向后找,而不能从后向前,且题目要求空间复杂度为 O ( 1 ) O(1) O(1),也就是不能构造辅助数组存储,那么应该怎么做呢?


既然不能从后向前,那我们就想办法让前段和后段在遍历时保持一致,可以通过对单链表后段进行逆置处理


step:

1. 找中间结点

要想逆置后段链表,则必须先找到前段和后段的分界点,所以我们第一步是找到中间结点

对于奇数个结点 ( 2 n + 1 ) (2n+1) (2n+1)的链表:我们需要找到第 n + 1 n+1 n+1个结点;对于偶数个结点 2 n 2n 2n的链表:我们需要找到第 n n n个结点


算法思路:

p移动1步,q移动2步(最后一步时,若为奇数个结点则移动1步),当q指向尾结点时,p正好指向中间结点:

  1. 设置两个指针 p , q p,q p,q,开始时,同时指向头结点,开始向后移动;
  2. 当q指向的下一个结点不为 N U L L NULL NULL时, p , q p,q p,q同时移动1步;
  3. 此时,继续判断q指向的下一个结点是否为 N U L L NULL NULL,若不为空,则再向后移动1步;若为空,则结束,此时的p即指向中间结点

①偶数个结点:
在这里插入图片描述

②奇数个结点:

在这里插入图片描述

key:q每走一步都要进行一次判空操作


代码实现:

	LNode* p = L, * q = L; //p,q初始都指向头结点
	while (q->next != NULL) {
		p = p->next;
		q = q->next;
		if (q->next != NULL) //q每走一步都要先判断
			q = q->next;
	}


2. 后段链表逆置

在找到中间结点后,我们就可以对结点后面的链表进行逆置处理啦~

对于单链表的逆置,其无法像数组一样随机访问,直接交换首尾的数据,所以我们的思路是:“让单链表的箭头反向”,再将中间结点连接至最后一个结点


算法思路:

  1. 先让指针 q q q指向后段的首结点,再将指向中间点的指针 p p p 指向 N U L L NULL NULL


    这里为什么要让指针 p p p 指向NULL呢?其实目的就是让前段和后段暂时断开

    图解:

    在这里插入图片描述


  1. q q q 不指向 N U L L NULL NULL时(即后段还有剩余结点未处理时),我们先记录 q q q 的下一个结点指针 r r r再让当前 q q q n e x t next next指向 p p p的下一个结点, q q q n e x t next next结点指向 p p p,最后移动 q q q r r r位置;


    这里我们要思考:

    1. q->next=p->next;p->next=q的含义是什么?
    p作为中间结点的指针,若要链表逆序,则最后p的next指针一定是要指向链表的尾结点的,所以,我们每扫到一个后段结点,都把他当作尾结点来看,则 q的next指针要指向上一轮 p的next指向的结点,这样就完成了箭头反向(因为上一轮p的next指向前一个结点),再让 p的next指向当前结点 q,即连接了表尾,实现了部分逆序

    2. 为什么要单独记录 q q q n e x t next next指针 r r r
    因为当q->next发生改变后,q之后的后段结点与当前逆序的部分断开,若不记录,则无法访问下一个结点


    图解:

    ①第一次连接:

    在这里插入图片描述

    ②第二次连接:

    在这里插入图片描述

    ③第三次连接:

    在这里插入图片描述

我们可以看到,这样就逐步实现了单链表的后段逆置操作


代码实现:

	q = p->next;  //q指向后段的首结点
	p->next = NULL;

	LNode* r; //每次都指向q的下一个结点
	while (q != NULL) {
		r = q->next; //记录
		q->next = p->next; //相当于将单链表箭头反向
		p->next = q;
		q = r; //移动至下一结点
	}


3. 重排单链表

在完成上述操作后,我们就可以对前段和后段进行交替插入,即完成单链表的重排啦~

算法思路:

  1. s s s指向前段的首结点, q q q指向后段的首结点,中间指针 p p p指向 N U L L NULL NULL

    注意:

    这里中间指针 p p p指向 N U L L NULL NULL的操作很重要!!由于中间结点(两个或一个)在重排后一定是不动的,所以中间结点或中间结点的 next在重排后会变为尾结点,因此必须使其指向 NULL,相当于特判,否则最后打印单链表时会进入死循环


  1. 接下来就是插入操作,即不断让当前 q q q指向的结点插入到 s s s结点后,直至 q q q指向 N U L L NULL NULL即后段结点全部处理完毕

    在这里插入图片描述


代码实现:

	q= p->next; //q重新指向重排后的后段首结点
	LNode* s = L->next; //s指向前段的首结点
	p->next = NULL; //这里很重要,让中间结点指向NULL,否则会进入死循环

	while (q != NULL) { //当后段还有结点没被重排
		r = q->next; //记录下一结点——防止重排后丢失
		//插入
		q->next = s->next;
		s->next = q;
		s = q->next; //s移动至下一个
		q = r; //q移动至下一个
	}


完整代码实现:

#include<iostream>
using namespace std;

typedef struct LNode {
	int data;
	struct LNode* next;
}LNode,*LinkList;

//0.初始化
void InitList(LinkList& L) {
	L = (LNode*)malloc(sizeof(LNode)); //定义头结点
	L->next = NULL;
	LNode* p = L;

	int x;
	while (cin >> x) {
		LNode* s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		p->next = s;
		p = s;
		if (cin.get() == '\n')
			break;
	}
	p->next = NULL;
}


//重排
void reset(LinkList& L) {
	//1.找到中间结点
	LNode* p = L, * q = L; //p,q初始都指向头结点
	while (q->next != NULL) {
		p = p->next;
		q = q->next;
		if (q->next != NULL) //q每走一步都要先判断
			q = q->next;
	}
	//最终p指向中点,q指向尾结点

	//2.单链表后段逆置
	q = p->next;  //q指向后段的首结点
	p->next = NULL;

	LNode* r; //每次都指向q的下一个结点
	while (q != NULL) {
		r = q->next; //记录
		q->next = p->next; //相当于将单链表箭头反向
		p->next = q;
		q = r; //移动至下一结点
	}

	//3.重排插入结点
	q= p->next; //q重新指向重排后的后段首结点
	LNode* s = L->next; //s指向前段的首结点
	p->next = NULL; //这里很重要,让中间结点指向NULL,否则会进入死循环

	while (q != NULL) { //当后段还有结点没被重排
		r = q->next; //记录下一结点——防止重排后丢失
		//插入
		q->next = s->next;
		s->next = q;
		s = q->next; //s移动至下一个
		q = r; //q移动至下一个
	}
}

void Print(LinkList& L) {
	LNode* p = L;
	while (p->next != NULL) {
		p = p->next;
		cout << p->data << " ";
	}cout << endl;
}

int main() {
	LinkList L;
	cout << "请输入单链表的元素值:" << endl;
	InitList(L);

	cout << "原始链表为:" << endl;
	Print(L);

	//重排
	reset(L);
	cout << "重排后链表为:" << endl;
	Print(L);

	system("pause");
	return 0;
}

输出结果:

在这里插入图片描述



🎇这是一道关于单链表操作的真题,很有思考价值,可以反复练习噢~🎇

如有错误,欢迎指正~!

在这里插入图片描述

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

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

相关文章

DAY02_MySQL高级-约束数据库设计多表查询事务

目录 1 约束1.1 概念1.2 分类1.3 非空约束1.4 唯一约束1.5 主键约束1.6 默认约束1.7 约束练习1.7.1 修改自增序列号 1.8 外键约束1.8.1 概述1.8.2 语法1.8.3 练习 2 数据库设计2.1 数据库设计简介2.2 表关系(一对多)2.3 表关系(多对多)2.4 表关系(一对一)2.5 数据库设计案例 3 …

kubernetes之client-go informer源码分析

一、概念 informer 是 client-go 中的核心工具包&#xff0c;在kubernetes中&#xff0c;各个组件通过HTTP协议跟 API Server 进行通信。如果各组件每次都直接和API Server 进行交互&#xff0c;会给API Server 和ETCD造成非常大的压力。在不依赖任何中间件的情况下&#xff0…

从零开始手写VIO 第3讲 基于优化的 IMU 与视觉信息融合

技巧性u初始值&#xff0c;更新的原因都不知道杂来的 F(x)是复杂的非线性函数&#xff0c;所以没法直接求导0得到最小值。所以展开 两种方法来下降&#xff0c;一种是先找一个方向&#xff0c;在确定一个步长line search。另一种是先确定区域&#xff0c;再找一个点。 J是FX的雅…

docker架构速看(1)-启动

Docker架构速看(1)-启动 ​ Docker是常用的容器管理工具&#xff0c;这篇文章对Docker架构结合源码做简要分析&#xff0c;由于也只使用过很少的命令&#xff0c;所以只分析image和container的相关部分。 源码准备 ​ Docker源码可以在github上找到&#xff0c;当前已更名为…

Vector-常用CAN工具 - VN5000接口以太网包过滤

目录 一、什么是硬件过滤&#xff1f; 1、什么时候应该过滤硬件&#xff1f; 2、需要注意什么&#xff1f; 3、如何过滤VN5000接口上的以太网报文&#xff1f; &#xff08;1&#xff09;Vector Hardware Manager &#xff08;2&#xff09;Vector Hardware Config 一、…

Benewake(北醒) 快速实现 TF03-485 与电脑通信操作说明

目录 一、前言二、工具准备1. USB-RS485 转接板或北醒 TF 系列专用转接板2. TF03-4853. PC&#xff1a;Windows 系统4. 串口助手软件、上位机 WINCC 三、连接方式方案一&#xff1a;USB-RS485 连接电脑与雷达(1) USB-RS485 转接板接口说明(2) TF03-485 引脚定义(3) 连接方式 方…

Go中的并发是困难的

我明白标题可能有些令人困惑&#xff0c;因为一般来说&#xff0c;Go被认为在并发方面有很好的内置支持。然而&#xff0c;我并不认为在Go中编写并发软件是容易的。让我向您展示我是什么意思。 使用全局变量 第一个例子是我们在项目中遇到的问题。直到最近&#xff0c;sarama…

【致敬未来的攻城狮计划】打卡1:rcsa+keil环境搭建

前言 这回参加的是csdn李肯老师的攻城狮计划&#xff0c;简单说就是我白嫖板子&#xff0c;输出学习笔记。 板子是瑞萨的CPK_RA2E1&#xff0c;还有触摸元件&#xff0c;看起来很有意思hh。 环境搭建 一开始决定采取vscode搭建的方式。后期进行到最后一步——cmake build的时…

SQL-计算留存率cohort

目录 1、留存率cohort介绍及其业务价值 2、计算思路 3、实操 3.1、日对日留存cohort 3.2、周对周留存cohort 3.3、月对月留存cohort 1、留存率cohort介绍及其业务价值 留存率cohort也叫做同期群留存分析&#xff0c;将同一时间范围内的用户分为一组&#xff0c;计算这批…

Linux命令(26)之uptime

Linux命令之uptime 1.uptime介绍 linux命令uptime是用来为用户提供系统从开启到当前运行uptime命令时系统已运行的时长信息&#xff0c;除此之外&#xff0c;还提了系统启动时间&#xff0c;当前登录用户&#xff0c;系统平均负载信息。 2.uptime用法 uptime [参数] uptime…

华为OD机试真题(Java),四则运算(100%通过+复盘思路)

一、题目描述 输入一个表达式&#xff08;用字符串表示&#xff09;&#xff0c;求这个表达式的值。 保证字符串中的有效字符包括[‘0’-‘9’],‘’,‘-’, ‘*’,‘/’ ,‘(’&#xff0c; ‘)’,‘[’, ‘]’,‘{’ ,‘}’。且表达式一定合法。 数据范围&#xff1a;表达…

gitlab记录

1、docker方式部署启动 参考文档&#xff1a; https://blog.csdn.net/weixin_53443677/article/details/125518696 https://blog.csdn.net/weixin_39034012/article/details/119211630 1.1、docker启动gitlab 前期准备 > # 拉镜像 > docker pull gitlab/gitlab-ce:late…

chatgpt赋能python:Python代码30行:提高网站SEO的最佳实践

Python 代码 30 行&#xff1a;提高网站 SEO 的最佳实践 搜索引擎优化&#xff08;SEO&#xff09;是网站成功的重要因素&#xff0c;它可以让网站排名更高并吸引更多的流量。Python 代码可以帮助您实现最佳的 SEO 实践&#xff0c;并提高网站的可见性和排名。下面是一个包含 …

Tugraph的设计和源码初步解析

1. Tugraph Tugraph是一款开源的性能优秀的图数据库&#xff0c;该图数据库使用多版本的BTree作为数据的存储引擎&#xff0c;同时设置了点边数据在这个存储引擎上的布局&#xff08;主要考虑数据的局部性&#xff09;&#xff0c;从而达到高性能查询的目的。本文主要从Tugrap…

ubuntu系统登录密码重置方法

公司搬家&#xff0c;需要更改git服务器地址&#xff0c;发现服务器密码也忘记了&#xff0c;折腾了下&#xff0c;通过如下方法修改成功。 一、重启计算机并进入GRUB菜单&#xff08;如果您的计算机没有显示GRUB菜单&#xff0c;请尝试按住Shift键或Esc键&#xff0c;直到出现…

手机安卓Termux搭建Hexo博客网站,并发布公网访问。

文章目录 1. 安装 Hexo2. 安装cpolar内网穿透3. 公网远程访问4. 固定公网地址 转载自cpolar极点云的文章&#xff1a;安卓手机使用Termux搭建Hexo个人博客网站【内网穿透公网访问】 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章&#…

DAY04_JDBC快速入门JDBC API详解SQL防注入数据库连接池JDBC综合练习

目录 1 JDBC1.1 JDBC概念1.2 JDBC本质 1.3 JDBC好处 2 JDBC快速入门2.1 编写代码步骤2.2 具体操作 3 JDBC API详解3.1 DriverManager3.2 Connection3.2.1 获取执行对象3.2.2 事务管理 3.3 Statement3.4 ResultSet3.4.1 ResultSet案例 3.5 PreparedStatement3.5.1 SQL注入3.5.2 …

基于opencv实现两路yuv数据拼接合成一张大图

背景 实时音视频通话&#xff08;RTC&#xff09;越来越注重安全审核&#xff0c;特别是在1v1娱乐社交场景中&#xff0c;对于视频反垃圾的需求也越来越大。随之而来的是客户对审核成本降低的诉求日益强烈。针对1v1场景&#xff0c;将两路视频拼接成一张图片进行审核相比于分别…

大数据Doris(三十一):Broker Load导入HDFS json格式数据和注意事项

文章目录 Broker Load导入HDFS json格式数据和注意事项 一、导入HDFS json格式数据 1、创建Doris表

nginx(八十一)rewrite模块指令再探之(三)重定向

一 return和rewrite重定向再探 ① 前言 多种重定向跳转方式的差异 nginx与Location响应头细节探讨 本为不涉及讨论如下的绝对重定向1) return 301 http://www.wzj.com:6443/url?namewzj2) rewrite ... http://www.wzj.com:6443/url 2) rewrite ... http://www.wzj.com:64…