外贸网站运营推广,周口市住房和城乡建设局门户网站,wordpress同分类文章列表,科技公司建设网站公司双指针#xff0c;顾名思义就是指针的指针。 在此之前我们需要先理解单指针 #xff08;简称为指针#xff09;。指针很简单#xff0c;直接上例子#xff1a;例#xff1a;现有两个变量#xff0c;a10,b20. 要求#xff1a;交换他们的值#xff0c;输出的结果应为a20…双指针顾名思义就是指针的指针。 在此之前我们需要先理解单指针 简称为指针。指针很简单直接上例子例现有两个变量a10,b20. 要求交换他们的值输出的结果应为a20b10。
#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 a10;int b10;定义的是两个实际参数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;
}结果