当前位置: 首页 > news >正文

如何正确方便的理解双指针?力扣102 (二叉树的层序遍历)

双指针,顾名思义就是指针的指针。
在此之前我们需要先理解单指针 (简称为指针)。指针很简单,直接上例子:例:现有两个变量,a=10,b=20.
要求:交换他们的值,输出的结果应为a=20,b=10。

#include <bits/stdc++.h>
using namespace std;void swap(int a, int b) {int temp = a;a = b;b = temp;
}int main() {int a = 10, b = 20;swap(a, b);cout << a << " " << b << endl;return 0;
}

乍一看没问题,结果:在这里插入图片描述
交换失败。失败的原因是在函数swap(int a,int b)中,接收的a和b是两个整型的值而不是指针(换句话说,这里交换的是形式参数而非实际参数)。int a=10;int b=10;定义的是两个实际参数,swap(int a,int b)中的a和b是形式参数,形参的交换对实参的交换是没有影响的。因此要将void swap(int a, int b)修改为void swap(int &a, int &b)

#include <bits/stdc++.h>
using namespace std;
void swap(int &a, int &b) {int temp = a;a = b;b = temp;
}
int main() {int a = 10;int b = 20;swap(a, b);cout << a << " " << b << endl;return 0;
}

在这里插入图片描述
成功。这里的void swap(int &a, int &b)是引用传递,当你调用这个函数时交换操作会直接修改变量a和b的值。这意味着函数外部的变量a和b的值也会发生交换。
当你使用swap(int *a, int *b)函数时得出的结果和上述的引用传参是一样的,但是原理不同:此时参数a和b是指向整型的指针,函数内部通过指针操作来交换变量的值。

void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}它们的运行结果相同。总结:**引用方式和指针方式**的交换两个变量的值的区别:
1、语法:
引用方式:使用引用作为形式参数,在函数内部直接操作引用所绑定的变量。
指针方式:使用指针作为形式参数,在函数内部通过引用指针所指向的地址来修改变量的值。因此引用方式的执行效率更高。
2、调用方式:
**引用方式直接将变量作为实际参数传递给函数**,无需取地址操作。
**指针方式:将变量的地址作为实际参数传递给函数**,在调用时取地址操作符&。
3、影响范围:
引用方式通过**引用传递,函数内部的修改会直接影响到函数外部的变量**。
指针方式:通过**指针传递,函数内部的修改只影响指针所指向的内存地址**,不会修改指针外部的变量。*注意:在函数内部修改指针指向的值,则会影响函数外部的变量。*
4、错误处理:
**引用方式的引用必须绑定到一个已存在的对象,**所以在使用引用方式交换值时不需要考虑空指针或者野指针的可能性。
**指针方式:指针可以为NULL或者指向未知的内存地址**,所以在使用指针交换值时需要注意指针的有效性,避免空指针或者野指针的访问。# 因此:我们明白了:引用方式更为简洁和安全;指针方式更加灵活,可以处理更多的特殊情况,但是相对复杂。接下来就可以开始介绍:**双指针**```cpp
#include <bits/stdc++.h>
using namespace std;void swap(int **a, int **b) {int *temp = *a;*a = *b;*b = temp;
}int main() {int a = 10;int b = 20;int *str1 = &a;int *str2 = &b;swap(&str1, &str2);cout << *str1 << " " << *str2 << endl;return 0;
}

在这里插入图片描述
和单指针对比着看就很直观了!swap的形式参数的a和b各多了一颗“*”,整型变量temp多了一颗*。其余的没有变化。因此双指针就是给指针又套上了一个指针,并没有很复杂。学完了双指针,我们来做一题对应的习题:LeetCode102 二叉树的层次遍历
在这里插入图片描述
核心代码:

int **levealOrder(struct TreeNode *root, int *returnSize, int **returnColumnSizes) { //层序遍历函数int **ans = (int **)malloc(sizeof(int *) * 2000); //动态创建一个二维数组ans用于存储层序遍历的结果*returnSize = 0; //所在层数if (!root)return NULL;int columnSizes[2000];//存所在层的结点struct TreeNode *queue[2000];//用于存储结点的队列int rear = 0, head = 0; //表示队头和队尾的索引queue[rear++] = root; //将结点进入队列while (rear != head) {ans[(*returnSize)] = (int *)malloc(sizeof(int) * (rear - head)); //存储当前结点columnSizes[(*returnSize)] = rear - head; //存储当前层的结点数量int start = head; //当前层在队列中的起始位置head = rear; //头部索引变为尾部索引,表示将要开始遍历下一层for (int i = start; i < head; i++) { //遍历当前层的所有结点ans[(*returnSize)][i - start] = queue[i]->val;if (queue[i]->left)queue[rear++] = queue[i]->left;if (queue[i]->right)queue[rear++] = queue[i]->right;}(*returnSize)++;}*returnColumnSizes = (int *)malloc(sizeof(int) * (*returnSize));for (int i = 0; i < *returnSize; i++)(*returnColumnSizes)[i] = columnSizes[i];return ans;
}

该算法是一个层序遍历算法.层序遍历的过程用大白话描述就是:
if 无根结点,结束
else 有根结点
(1)先遍历根结点;
(2)若有左孩子,将左结点放入队列数组中;
(3)若有右孩子,将右结点放入队列数组中;
重复上述过程直到结点为NULL。

关于这个算法核心部分的解释:首先levealOrder函数的形式参数有3个,第一个是单指针指向(或者说引用)根结点root,
第二个是单指针指向层序遍历的初始层数,
第三个是双指针指向每层结点数量的数组。
该函数最终要返回一个存储层序遍历结果的二维数组ans[][].

int **ans指向一个动态创建的二维数组,用于存储层序遍历的结果:
行代表所在层,列代表所在层的结点位置。即ans[returnSize][rear-head].
(rear-head)是当前层的结点的位置。head和rear分别是队头和队尾的索引。
queue[]用于存储结点以方便遍历。
columnSize用于存储每层结点的数量;

完整代码:

#include <bits/stdc++.h>
using namespace std;typedef struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;
} TreeNode;TreeNode *createNode(int val) {TreeNode *newNode = (TreeNode *)malloc(sizeof(TreeNode));newNode ->val = val;newNode ->left = NULL;newNode ->right = NULL;return newNode;
}int **levealOrder(struct TreeNode *root, int *returnSize, int **returnColumnSizes) { //层序遍历函数int **ans = (int **)malloc(sizeof(int *) * 2000); //动态创建一个二维数组ans用于存储层序遍历的结果*returnSize = 0; //所在层数if (!root)return NULL;int columnSizes[2000];//存所在层的结点struct TreeNode *queue[2000];//用于存储结点的队列int rear = 0, head = 0; //表示队头和队尾的索引queue[rear++] = root; //将结点进入队列while (rear != head) {ans[(*returnSize)] = (int *)malloc(sizeof(int) * (rear - head)); //存储当前结点columnSizes[(*returnSize)] = rear - head; //存储当前层的结点数量int start = head; //当前层在队列中的起始位置head = rear; //头部索引变为尾部索引,表示将要开始遍历下一层for (int i = start; i < head; i++) { //遍历当前层的所有结点ans[(*returnSize)][i - start] = queue[i]->val;if (queue[i]->left)queue[rear++] = queue[i]->left;if (queue[i]->right)queue[rear++] = queue[i]->right;}(*returnSize)++;}*returnColumnSizes = (int *)malloc(sizeof(int) * (*returnSize));for (int i = 0; i < *returnSize; i++)(*returnColumnSizes)[i] = columnSizes[i];return ans;
}int main() {TreeNode *root = createNode(3);root->left = createNode(9);root->right = createNode(20);root->right->left = createNode(15);root->right->right = createNode(20);int returnSize;//记录当前层数int *returnColumnSizes;//存放当前层结点的数组int **result = levealOrder(root, &returnSize, &returnColumnSizes);for (int i = 0; i < returnSize; i++) {cout << "第" << (i + 1) << "层:";for (int j = 0; j < returnColumnSizes[i]; j++)cout << result[i][j] << " " ;cout << endl;}for (int i = 0; i < returnSize; i++)free(result[i]);//动态创建的空间用完之后要释放掉,避免内存泄漏的风险。free(result);free(returnColumnSizes);return 0;
}

结果:
在这里插入图片描述

相关文章:

如何正确方便的理解双指针?力扣102 (二叉树的层序遍历)

双指针&#xff0c;顾名思义就是指针的指针。 在此之前我们需要先理解单指针 &#xff08;简称为指针&#xff09;。指针很简单&#xff0c;直接上例子&#xff1a;例&#xff1a;现有两个变量&#xff0c;a10,b20. 要求&#xff1a;交换他们的值&#xff0c;输出的结果应为a20…...

Vue或uniapp引入自定义字体

一、为什么引入字体 对于大部分APP或网站而言&#xff0c;字体是很重要的一部分。在前端开发中&#xff0c;选用合适的字体往往会极大地提升网站的视觉体验。然而&#xff0c;网页中默认字体的种类和风格有限&#xff0c;且在不同的设备、浏览器上渲染效果不尽相同。因此&…...

​力扣:LCR 122. 路径加密​ 题目:剑指Offer 05.替换空格(c++)

本文章代码以c为例&#xff01; 力扣&#xff1a;LCR 122. 路径加密 题目&#xff1a; 代码&#xff1a; class Solution { public:string pathEncryption(string path) {for(int i0;i<path.size();i){if(path[i].){path[i] ;}}return path;} }; 难度升级&#xff08;原…...

cJson堆内存释放问题

cJSON_Delete()&#xff0c;是用来释放json对象的&#xff0c;释放父JSON对象后&#xff0c;子JSON对象也会被释放。 CJSON_free()&#xff0c;是用来释放其他对象的。 int main(void) {cJSON* cjson_test NULL;cJSON* cjson_address NULL;cJSON* cjson_skill NULL;char* s…...

论文阅读/写作扫盲

第一节&#xff1a;期刊科普 JCR分区和中科院分区是用于对期刊进行分类和评估的两种常见方法。它们的存在是为了帮助学术界和研究人员更好地了解期刊的学术质量、影响力和地位。 JCR分区&#xff08;Journal Citation Reports&#xff09;&#xff1a;JCR分区是由Clarivate Ana…...

一文拿捏对象内存布局及JMM(JAVA内存模型)

1 JMM(Java Memory Model) 1 概述 Java内存模型(Java Memory Model简称JMM)是一种抽象的概念&#xff0c;并不真实存在&#xff0c;它描述的一组规则或者规范。通过这些规则、规范定义了程序中各个变量的访问方式。jvm运行的程序的实体是线程&#xff0c;而每个线程运行时&am…...

Android组件通信——ActivityGroup(二十五)

1. ActivityGroup 1.1 知识点 &#xff08;1&#xff09;了解ActivityGroup的作用&#xff1b; &#xff08;2&#xff09;使用ActivityGroup进行复杂标签菜单的实现&#xff1b; &#xff08;3&#xff09;使用PopupWindow组件实现弹出菜单组件开发&#xff1b; 1.2 具体…...

js的继承的方式

1.对象冒充继承 使用 bind,call,apply 解决构造函数属性的继承 缺点:不能继承原型上的属性和方法 //-------------父类-------------function Person(name, age, sex) {this.name name;this.age age;this.sex sex;}Person.prototype.run function () {console.log(我${this…...

聊聊HttpClient的重试机制

序 本文主要研究一下HttpClient的重试机制 HttpRequestRetryHandler org/apache/http/client/HttpRequestRetryHandler.java public interface HttpRequestRetryHandler {/*** Determines if a method should be retried after an IOException* occurs during execution.**…...

北邮22级信通院数电:Verilog-FPGA(4)第三周实验:按键消抖、呼吸灯、流水灯 操作流程注意事项

北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章&#xff0c;请访问专栏&#xff1a; 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 目录 一.注意事项 二.按键消抖 2.1 LED_deboun…...

Ghidra101再入门(上?)-Ghidra架构介绍

Ghidra101再入门(上&#xff1f;)-Ghidra架构介绍 最近有群友问我&#xff0c;说&#xff1a;“用了很多年的IDA&#xff0c;最近想看看Ghidra&#xff0c;这应该怎么进行入门&#xff1f;“这可难到我了。。 我发现&#xff0c;市面上虽然介绍Ghidra怎么用的文章和书籍很多&…...

Vue3路由引入报错解决:无法找到模块“xxx.vue”的声明文件 xxx隐式拥有 “any“ 类型。

这类情况应该遇见过吧&#xff0c;这是因为 TypeScript只能理解 .ts 文件&#xff0c;无法理解 .vue 文件。 解决方法&#xff1a;在项目的根目录或者src文件夹下创建一个后辍为 文件名.d.ts 的文件&#xff0c;并写入一下内容&#xff1a; declare module *.vue {import { …...

基于若依ruoyi-nbcio支持flowable流程分类里增加流程应用类型

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 主要考虑到流程分很多种&#xff0c;普通的是OA流程&#xff0c;还有自定义业务流程&#xff0c;钉钉流程等…...

JS之同步异步promise、async、await

promise异步操作 Promise是异步编程的一种解决方案 JavaScript异步与同步解析 学习promise前我们先来了解下什么是异步&#xff1f; 基本概念&#xff1a; 消息队列中的任务分为宏任务与微任务;调用栈也可以称为主线程 首先我们要知道js是单线程语言&#xff0c;也就是说…...

【OpenCV • c++】自定义直方图 | 灰度直方图均衡 | 彩色直方图均衡

文章目录 一、什么是直方图二、自定义直方图三、灰度直方图均衡四、彩色直方图均衡一、什么是直方图 直方图广泛应用于很多计算机视觉处理当中。通过标记帧与帧之间显著的边缘和颜色的变化,可以检测视频中的场景变化。在每个兴趣点设置一个有相似特征的直方图所构成的“标签”…...

el-tree目录和el-table实现搜索定位高亮方法

需求&#xff1a;el-tree目录实现搜索查询el-table表格项&#xff0c;双击表格项根据yiZhuMLID||muLuID定位el-tree目录&#xff0c;并且高亮展示在可视化区域内&#xff0c;再重新根据el-tree目录的yiZhuMLID搜索刷新el-table表格&#xff0c;定位且高亮展示相对应的yiZhuMLID…...

linux常用指令

基础命令 cd&#xff1a;用于切换目录。例如&#xff0c;要从当前目录切换到/home/user目录&#xff0c;可以使用命令“cd /home/user”。ls&#xff1a;用于列出目录内容。例如&#xff0c;要列出当前目录的内容&#xff0c;可以使用命令“ls”。mkdir&#xff1a;用于创建目…...

C语言,指针的一些运算

若创建一个数组&#xff1a;int arr[10] 0; 用指针变量来储存数组首元素的地址&#xff1a;int* p arr,这里arr是数组名&#xff0c;表示首元素地址。 若p p 1或者p之后p本来指向数组首元素地址&#xff0c;就变成了指向第二个元素的地址&#xff0c;p n即指向第n 1个地…...

iPhone 如何强制重启

参考iPhone的官方使用手册 传送门 尤其当 iPhone 未响应&#xff0c;也无法将其关机再开机&#xff0c;此方法最有效&#xff1a; 按住调高音量按钮&#xff0c;然后快速松开。按住调低音量按钮&#xff0c;然后快速松开。按住侧边按钮。当 Apple 标志出现时&#xff0c;松开侧…...

数据结构--单链表操作

1.单链表的创建&#xff08;带头结点&#xff09; #include<stdlib.h> #define ElemType int typedef struct {//定义一个结点ElemType data;struct STU* next; }STU,*LinkList; bool InitList(LinkList& L) {L (STU*)malloc(sizeof(STU));//创建头结点if (L NUL…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...