当前位置: 首页> 汽车> 维修 > 常见的渠道推广方式有哪些_手机平板购物网站的设计背景_关键词上首页的有效方法_海南seo排名优化公司

常见的渠道推广方式有哪些_手机平板购物网站的设计背景_关键词上首页的有效方法_海南seo排名优化公司

时间:2025/8/2 14:57:21来源:https://blog.csdn.net/weixin_54946088/article/details/146141402 浏览次数: 1次
常见的渠道推广方式有哪些_手机平板购物网站的设计背景_关键词上首页的有效方法_海南seo排名优化公司

内存模型

一.内存中有代码区;栈区;数据段 堆区 

1、栈区存放了函数所有局部变量和形参;

它的局限在于:局部变量和形参的生存期;即函数返回后对象就会被回收

解决方案是:1)使用全局变量 (存放在在数据段)2) 使用堆空间

2.&的作用是什么?

==>在定义语句中应用表示定义了一个引用;在非定义语句中表示取地址;

int main(){int i=10;int *p;//p是一个指针变量,打算指向一个int变量p=&i;//取出i的地址 放入p中++* p;//根据p找到指向的数据,再对数据做一个自增
}

3.指针变量是一个存储地址的变量;

注意:不要返回局部变量的地址;因为可能指针最终指向的内存空间已被释放而不存在;

故我们需要使用堆空间:使用new delete 来进行申请空间和释放空间.他们的语法如下:

注意:我们不推荐使用new的动态数组,而推荐优先使用局部变量/全局变量/vector

new type;//int,float/double/自定义
new type[length];// 申请长度为length的动态数组(不推荐使用)

我们来举个例子介绍再函数中使用new,delete;然后返回指针的用法:

int* func(){
int* p=new int;
*p=10;
return p;
}
​
int main(){
int* p;
p1=func();
++* p1;
delete p1;
return 0;
}

代码分析:以上的代码的示意图如下,由于我们的整数是在堆区中开辟的一段内存,func()和main()传递的有只有指针,所以尽管func()的声明周期结束了;堆区的这块区域也不会消失;且main()中的p1指针仍然在指着它。

二叉树(层序建树)

树在内存的存储有两种形式:

顺序存储:只适用于一些特殊的树,例如,完全二叉树

链式存储:每一个节点有数据域和指针域(left,right,parent等)

struct可以自定义类型

往树种插入节点的方式不唯一,以下的例子我们使用层序建树。

先分析以下,若给定序列abc##de#g##f###(空域表示为#),我们怎么进行建树呢?

==》层序建树需要使用一个队列维持记录插入的信息;

1.我们会有一个proot指针指向根节点,我们这里的根节点是a。

所以在一开始,我们要先创建树节点a,作为根节点插入;即

TreeNode a;
proot=&a;

2、因为a的两个指针现在还没有连上其他的节点,但它将来有机会去连其他的节点;故当a节点插入时,我们就将其left和right的位置入队再来新的数据(若不是#),创建树节点,获取队首,出队,以让新节点插入到这个位置。再让这个新节点的左右指针入队;

3.若数据是一个#,则直接让队首出队;(以表示其连的是一个空域)

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<set>
#include<algorithm>
#include<queue>
using namespace std;
​
struct TreeNode {int data;TreeNode* left;//这里必须使用指针,指针的长度我们是知道的TreeNode* right;
};
​
​
//队列成员
struct  QueueNode {TreeNode* parent;//用来表示这个节点保存的位置的左孩子是否为空bool isLeft;
};
​
​
​
void BuildTree(TreeNode*& proot, queue< QueueNode*>& pos, char data) {//判断data是否为就#if (data != '#') {//申请一个树节点TreeNode* pNew = new TreeNode;//修改数据域//(*pNew).data = data;//.的优先级高于*pNew->data = data;//->和(*).是等价//申请一个队列节点QueueNode* pQueueNode = new QueueNode;pQueueNode->parent = pNew;//在队列节点中,保存刚创建的新节点的位置pos.push(pQueueNode);//插入//若为根节点if (proot == NULL) {proot = pNew;}else {//若不为根节点;则从队列中找到这个节点要插入的位置QueueNode* pCur = pos.front();if (pCur->isLeft == false) {pCur->parent->left = pNew;pCur->isLeft = true;}else {pCur->parent->right = pNew;pos.pop();delete pCur;}}}else {//若当前根节点为空,直接无需理会;若不为空,则得到队列中弹出一个保存的地址,令其左域或右域指向为空。if (proot != NULL) {QueueNode* pCur = pos.front();if (pCur->isLeft == false) {pCur->parent->left = NULL;pCur->isLeft = true;}else {pCur->parent->right = NULL;pos.pop();delete pCur;}}}
}
​
​
int main() {TreeNode* proot = NULL;// 有一个指向根节点的指针//若proot为NULL,说明这是一个空树char data;while (1) {scanf("%c", &data);if (data == '\n') {break;}queue<QueueNode*> pos;BuildTree(proot, pos, data);}return 0;
}

代码分析:

1.上述使用QueueNode表示队列节点,是可以被插入队列queue中的,为什么queue中要保存的是QueueNode的指针,而不直接是QueueNode节点?

1)避免拷贝开销:指针的大小是固定的(通常为 4 或 8 字节),拷贝指针的开销远小于拷贝整个 QueueNode 对象的开销。

2)动态内存管理:通过指针,可以动态地创建和销毁 QueueNode 对象,而不需要依赖 queue 的生命周期。

3)共享数据:指针可以指向同一个 QueueNode 对象,从而在多个地方共享数据,而不需要复制数据。

因此,存储 QueueNode* 指针是一种更高效、更灵活的方式。

2.QueueNode中的parent保存的是节点的地址;以至于我们可以使用

pCur->parent->left 来表示其左指针域指向

pCur->parent->right 来表示其右指针域指向

请品味这里的parent保存节点的地址的好处?

==>因为我们要实现的是让队列中的节点能够使得节点a的左指针域进而右指针域在某一时刻被赋值,故队列节点保存节点a的地址是最好的。因为这样我们就可以使用指针来达到我们的效果。

3.在输入不是#时,我们要从队列中弹出一个位置,以让新节点插入这个位置的左指针域或右指针域,这时需要判断队列是否为空。即代码应该补上!pos.empty()

  if (proot != NULL && !pos.empty()) {

树的遍历

树的遍历分为2种,即广度优先(层序遍历,需要辅助队列)和深度优先(更常见,需要借助递归机制实现)

深度优先中根据遍历顺序分为:先序,中序和后序

层序遍历

void levelOrder(TreeNode* proot){
//简历一个队列
queue<TreeNode*>pos;
//先将根节点的指针入队
pos.push(proot);
//循环条件:队列不为空
while(pos.empty()==false){//获取当前队首元素TreeNode* pCur=pos.front();//弹出队首元素,并打印输出,并将其左右孩子的指针入队pos.pop();printf("%c",pCur->data);if(pCur->left!=NULL){pos.push(pCur->left);}if(pCur->right!=NULL){pos.push(pCur->right);}
}printf("\n");  }

代码分析:

上述想要层序遍历树;使用了辅助队列;存储的依然是指针;即存储的是 TreeNode* 指针,而不是 TreeNode 对象本身。(想象一下,一个个的节点是实体,但是都由一个个的指针指着,而我们操作的就是这一个个的指针的指向,而不动实体,实在是一种很轻巧的操作)

这样做的好处我们上面已经分析过了。

先序遍历

参数:根节点指针

返回值:无

处理:递归进行树的遍历

1)出口:当前指向为空域

2)工作:打印当前节点,再递归遍历其左子树;再递归遍历其右子树

void preOrder(TreeNode* proot){
if(proot==NULL){return;
}else{printf("%c",proot->data);preOrder(proot->left);preOrder(proot->right);
}
}

效果:输入abc##de#g##f###

可有:abcdgfe

中序遍历

void InOrder(TreeNode* proot){
if(proot==NULL){return;
}else{preOrder(proot->left);printf("%c",proot->data);preOrder(proot->right);
}
}

后序遍历

void PostOrder(TreeNode* proot){
if(proot==NULL){return;
}else{preOrder(proot->left);preOrder(proot->right);printf("%c",proot->data);
}
}

关键字:常见的渠道推广方式有哪些_手机平板购物网站的设计背景_关键词上首页的有效方法_海南seo排名优化公司

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: