数据结构 链表2

目录

前言:

一,反转一个链表(迭代)

 二,打印一个链表(递归)

三,反转一个链表(递归)

四,双向链表

总结


前言:

我们根据 [文章  链表1] 可以知道链表相比较于数组的优缺点和计算机是如何管理内存的,然后介绍了链表的实现,头插法,任意节点插入,任意节点删除,接下来我们就来学习反转链表与打印链表的迭代和递归操作


 

一,反转一个链表(迭代)

反转一个链表并不是移动位置,而是改变输出方向,就好比如数组一样,我们打印一个反转的数组,就是for循环反着循环就好了,取决于下角标,而不是数据的位置,这里也是同理 

#include<iostream>
#include<new>
using namespace std;

struct Node {
	int data;
	Node* Next;
};

Node* head;


void reverse(){
	Node* current, * prev, * next;
	current = head;  prev = NULL;
	while (current != NULL) {
		next = current->Next;
		current->Next = prev;  //这里可以设置第一个节点为NULL
		prev = current;
		current = next;
	}
	head = prev;
}


void print() {
	Node* temp = head;
	while(temp!=NULL) {
		cout << temp->data << "  ";
		temp = temp->Next;
	}
}


int main() {
	head = NULL;
	Node* temp1 = new Node;
	temp1->data = 1;
	temp1->Next = NULL;

	Node* temp2 = new Node;
	temp2->data = 2;
	temp2->Next = NULL;

	Node* temp3 = new Node;
	temp3->data = 3;
	temp3->Next = NULL;

	Node* temp4 = new Node;
	temp4->data = 4;
	temp4->Next = NULL;

	temp1->Next = temp2;  temp2->Next = temp3;  temp3->Next = temp4;
	head = temp1;
	reverse();
	print();
}

这是反转一个链表的操作,然后我们来详细的看一下这个反转链表的函数

void reverse(){
	Node* current, * prev, * next;
	current = head;  prev = NULL;
	while (current != NULL) {
		next = current->Next;
		current->Next = prev;  //这里可以设置第一个节点为NULL
		prev = current;
		current = next;
	}
	head = prev;
}

这里就是反转链表的函数,我们反转链表主要就是利用改变后面的指向,使得输出方向发生变化,因为head永远都是这个链表的第一个节点的位置

这里设置了三个指针

prev:    先前的      这个是用来当current为空的时候,好用prev给head提供最好一个节点的位置,还有一个就是让current指向前一个

current:现在的      这个是用来表示现在这个节点的,利用current来来指向前一个

next:    下一个的   这个是用来为current提供下一个位置的

 二,打印一个链表(递归)

 这里就不讲解递归的思想了,可以去看我的文章函数的递归

我们根据这个思想来编写这个递归思想书写这个代码

#include<iostream>
#include<new>
using namespace std;

struct Node {
	int data;
	Node* Next;
};

Node* head;

void reverse(){
	Node* current, * prev, * next;
	current = head;  prev = NULL;
	while (current != NULL) {
		next = current->Next;
		current->Next = prev;  //这里可以设置第一个节点为NULL
		prev = current;
		current = next;
	}
	head = prev;
}

void print1(Node* p) {
	if (p == NULL) {
		return;
	}
	cout << p->data << " ";
	print1(p -> Next);
	cout << p->data << " ";
}

int main() {
	head = NULL;
	Node* temp1 = new Node;
	temp1->data = 1;
	temp1->Next = NULL;

	Node* temp2 = new Node;
	temp2->data = 2;
	temp2->Next = NULL;

	Node* temp3 = new Node;
	temp3->data = 3;
	temp3->Next = NULL;

	Node* temp4 = new Node;
	temp4->data = 4;
	temp4->Next = NULL;

	temp1->Next = temp2;  temp2->Next = temp3;  temp3->Next = temp4;
	head = temp1;
	reverse();
	print1(head);
}

这个里面有利用递归来书写的打印链表

if (p == NULL) {
	return;
}

这个为递归的基准条件,什么时候跳出递归进行反转

cout << p->data << " ";
print1(p -> Next);
cout << p->data << " ";

这个是递归的过程,上面的为正序打印,下面为逆序打印,至于为什么这样,看我的文章函数的递归

三,反转一个链表(递归)

#include<iostream>
#include<new>
using namespace std;

struct Node {
	int data;
	Node* Next;
};

Node* head;

void reverse1(Node*p){
	if (p->Next == NULL) {
		head = p;
		return;
	}
	reverse1(p->Next);
	Node* q = p->Next;
	q->Next = p;
	p->Next = NULL;
}

void print1(Node* p) {
	if (p == NULL) {
		return;
	}
	cout << p->data << " ";
	print1(p -> Next);
}

int main() {
	head = NULL;
	Node* temp1 = new Node;
	temp1->data = 1;
	temp1->Next = NULL;

	Node* temp2 = new Node;
	temp2->data = 2;
	temp2->Next = NULL;

	Node* temp3 = new Node;
	temp3->data = 3;
	temp3->Next = NULL;

	Node* temp4 = new Node;
	temp4->data = 4;
	temp4->Next = NULL;

	temp1->Next = temp2;  temp2->Next = temp3;  temp3->Next = temp4;
	head = temp1;
	reverse1(head);
	print1(head);
}

我们来看这个递归反转链表的代码

void reverse1(Node*p){
	if (p->Next == NULL) {
		head = p;
		return;
	}
	reverse1(p->Next);
	Node* q = p->Next;
	q->Next = p;
	p->Next = NULL;
}

这个相较于迭代,代码量少了很多

if语句是用来设置基准条件的,着p是为了寻找最后一个节点赋值给head,另外一个就是挖掘深度,提供可以改变指向的一个环境,后面就是递归完之后,我们知道这个如果是打印数字的话就是反着来的,所以我们就知道这个已经是到最后一个节点了,然后我们只需要改变指向

  1. 递归调用过程

    • 初始调用:reverse1(head),即 reverse1(A)

    • 递归调用:reverse1(B)

    • 递归调用:reverse1(C)

    • 递归调用:reverse1(D)

    • DNextNULL 时,设置 head = D,并返回。

 我们可以知道在D的时候,Next已经为空,则这个时候就开始return了,然后我们就进入C,我们以C为例子来讲解

这个就是过程,改变下一个,本个为空

四,双向链表

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

双向链表是由两个地址域的

优点:如果我们由指向任意节点的指针,那么我们是方便反向查询的(仅需一个指针)

缺点:代码量增加,占用内存 

 双向链表的实现跟单向链表很像,只是多了一个地址域而已,这里就不过多解释了,对于堆的数据,我们链表一般都是在堆的,在堆里面查找数据一般都是利用指针


总结

我们目前基本学习完了链表的全部知识

-----增删改查

-----打印链表(迭代,递归)

-----反转链表(迭代,递归)

增删改查:这个就是要注意指向问题,比如增加到中间的位置的时候,是需要找到前面那个节点进程处理的

递归        :需要注意的就是基准条件和过程,释放到入口的上面还是下面

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

curl简介与libcurl开源库的使用总结

curl工具和libcurl不是同一个东西&#xff0c;二者的关系主要体现在以下方面&#xff1a; 定义与性质 curl工具&#xff1a; 是一个利用URL语法在命令行下工作的文件传输工具&#xff0c;1997年首次发行。它支持多种协议&#xff0c;如HTTP、HTTPS、FTP、FTPS等&#xff0c;可用…

node.js 07.npm下包慢的问题与nrm的使用

一.npm下包慢 因为npm i 默认从npm官网服务器进行下包,但是npm官网服务器是海外服务器所以响应很慢. 于是我们通过npm下包的时候通常用淘宝镜像进行下包,下面是切换到淘宝镜像地址下包的操作. 二.nrm的使用 nrm是一个管理切换npm下包地址的工具,可以快速切换下包的地址. 安…

Flutter:carousel_slider 横向轮播图、垂直轮播公告栏实现

安装依赖 carousel_slider: ^5.0.01、垂直滚动公告栏 import package:carousel_slider/carousel_options.dart;// 垂直滚动公告栏Widget _buildNotice() {return <Widget>[<Widget>[TDImage(assetUrl: "assets/img/home11.png",width: 60.w,height: 60.w…

RavenMarket:用AI和区块链重塑预测市场

不论是美股市场还是加密市场&#xff0c;AI都是本轮周期里的最大叙事。本轮AI的最大受益者英伟达市值超越苹果一跃成为全球第一大公司&#xff0c;加密领域围绕着AI的创新也是层出不穷&#xff0c;很多项目方开始向着AI转型。 而近期币圈最热门的板块就是AI agent&#xff0c;…

【玩转全栈】----Django基本配置和介绍

目录 Django基本介绍&#xff1a; Django基本配置&#xff1a; 安装Django 创建项目 创建app 注册app Django配置路由URL Django创建视图 启动项目 Django基本介绍&#xff1a; Django是一个开源的、基于Python的高级Web框架&#xff0c;旨在以快速、简洁的方式构建高质量的Web…

学技术学英语:TCP的三次握手和四次挥手

单词 汉语意思 音标 acknowledge 承认&#xff0c;确认 /əkˈnɒl.ɪdʒ/ acknowledgment 确认&#xff0c;承认 /əkˈnɒl.ɪdʒ.mənt/ duplex 双向的 /ˈdjuː.pleks/ establish 建立 /ɪˈstb.lɪʃ/ handshake 握手&#xff0c;握手协议 /ˈhnd.ʃeɪk…

iconfont等图标托管网站上传svg显示未轮廓化解决办法

打开即时设计 即时设计 - 可实时协作的专业 UI 设计工具 导入图标后拖入画板里面&#xff0c;右键选择轮廓化 将图标导出

SpringBoot集成Flink-CDC,实现对数据库数据的监听

一、什么是 CDC &#xff1f; CDC 是Change Data Capture&#xff08;变更数据获取&#xff09;的简称。 核心思想是&#xff0c;监测并捕获数据库的变动&#xff08;包括数据或数据表的插入、 更新以及删除等&#xff09;&#xff0c;将这些变更按发生的顺序完整记录下来&…

豆包 MarsCode + 开源 = ?AI 助力开源社区新人成长

来源&#xff5c;豆包 MarsCode “开源” 这个词&#xff0c;对开发者来说&#xff0c;可能是入门时的第一步&#xff0c;也可能是追求极致技术的终点。无数优秀的开源项目不仅推动了技术的进步&#xff0c;也成为开发者学习和成长的宝藏&#xff0c;但同时也因为其规模庞大、代…

STM32-CAN总线

1.CAN总线简介 CAN总线是由BOSCH公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线 2.CAN总线特征 两根通信线&#xff08;CAN_H、CAN_L&#xff09;&#xff0c;线路少&#xff0c;无需共地差分信号通信&#xff08;相对的是单端信号&#xff09;&#…

机器学习-线性回归(简单回归、多元回归)

这一篇文章&#xff0c;我们主要来理解一下&#xff0c;什么是线性回归中的简单回归和多元回归&#xff0c;顺便掌握一下特征向量的概念。 一、简单回归 简单回归是线性回归的一种最基本形式&#xff0c;它用于研究**一个自变量&#xff08;输入&#xff09;与一个因变量&…

Linux 高级路由与流量控制-用 tc qdisc 管理 Linux 网络带宽

大家读完记得觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 此分享内容比较专业&#xff0c;很多与硬件和通讯规则及队列&#xff0c;比较底层需要有技术功底人员深入解读。 Linux 的带宽管理能力 足以媲美许多高端、专用的带宽管理系统。 1 队列&#xff0…

安装k8s前置操作(Ubuntu / CentOS)

本文将介绍在 Ubuntu 和 CentOS 系统上进行 Kubernetes 部署前的基本配置步骤。不同的操作系统有不同的配置方法&#xff0c;但大部分操作是相似的。本文章将分为两个部分&#xff1a;第一部分是 Ubuntu 前置操作&#xff0c;第二部分是 CentOS 前置操作。 第一节&#xff1a;U…

Flask简介与安装以及实现一个糕点店的简单流程

目录 1. Flask简介 1.1 Flask的核心特点 1.2 Flask的基本结构 1.3 Flask的常见用法 1.3.1 创建Flask应用 1.3.2 路由和视图函数 1.3.3 动态URL参数 1.3.4 使用模板 1.4 Flask的优点 1.5 总结 2. Flask 环境创建 2.1 创建虚拟环境 2.2 激活虚拟环境 1.3 安装Flask…

C语言教程——动态内存管理(2)

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据 总结 前言 我们之前学了动态内存管理分配函数&#xff0c;也是熟悉了动态内存分配函数&#xff0c;基于动态内存分配我把之前的通讯录做了修改&#xff0c;上传到了gitee上&#xff0c;这篇文章接着…

python学习笔记3-字符串常用的方法

一、判断&#xff08;9个&#xff09;&#xff1a; 二、查找和替换&#xff08;8个&#xff09; 三、⼤⼩写转换&#xff08;5个&#xff09; 四、⽂本对⻬&#xff08;3个&#xff09; 五、去除空⽩字符&#xff08;3个&#xff09; 六、拆分和连接 &#xff08;6个&#xff0…

MySQL主从配置

一、 主从原理 MySQL 主从同步是一种数据库复制技术&#xff0c;它通过将主服务器上的数据更改复制到一个或多个从服务器&#xff0c;实现数据的自动同步。主从同步的核心原理是将主服务器上的二进制日志复制到从服务器&#xff0c;并在从服务器上执行这些日志中的操作。 二、主…

【java数据结构】二叉搜索树

【java数据结构】二叉搜索树 一、二叉搜索树的概念二、二叉搜索树的操作2.1 插入2.2 查找2.3 删除&#xff08;重点以及难点&#xff09;2.3.1 删除节点的左边为null2.3.2 删除节点的右边为null2.3.3 删除的左右节点都不为空 三、二叉搜索树的性能分析3.1 最优情况3.2 最差情况…

【Maui】注销用户,采用“手势”点击label弹窗选择

文章目录 前言一、问题描述二、解决方案三、软件开发&#xff08;源码&#xff09;3.1 方法一&#xff1a;前端绑定3.2 方法二&#xff1a;后端绑定3.3 注销用户的方法 四、项目展示 前言 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架&#xff0c;用于使用 C# 和 XAML 创…

【JVM】垃圾收集器详解

你将学到 1. Serial 收集器 2. ParNew 收集器 3. Parallel Scavenge 收集器 4. Serial Old 收集器 5. Parallel Old 收集器 6. CMS 收集器 7. G1 收集器 在 Java 中&#xff0c;垃圾回收&#xff08;GC&#xff09;是自动管理内存的一个重要机制。HotSpot JVM 提供了多种…