持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
一、题目
#include <vector>
#include <iostream>
using namespace std;
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
vector<int> preorderErgodic(TreeNode* root){
}
int main(int, char**)
{
TreeNode root(1);
TreeNode node1(2);
TreeNode node2(3);
root.right = &node1;
node1.left = &node2;
vector<int> res = preorderErgodic(&root);
for(int data : res){
cout << data << ' ';
}
cout << endl;
return 0;
}
二、分析
根据题意可知,这是一道经典的先序遍历题。
所谓先序遍历也叫做先根遍历、前序遍历,遍历顺序为根左右。
首先访问根结点,然后访问左子树,最后访问右子树。在访问左、右子树时,也是先去访问根结点,然后访问左子树,最后访问右子树,如此周而复始直至节点为空。
题中规定返回类型是vector,众所周知,vector的膨胀是极消耗的。
vector动态内存增长的过程如下:
1. 申请一块更大的内存空间以存储新数据。
2. 将数据从旧内存空间拷贝到新内存空间。
3. 析构旧内存空间中的对象。
4. 释放旧内存空间。
每一次内存不足,都会重复上诉过程,消耗大的同时,申请两倍空间没用完也是一种浪费。
如果要预先申请内存,就需要遍历一次,获取总节点数,这也是一种消耗。
但是由于题目中规定了节点数不超过100,所以这里我们两相权衡之下,可以直接申请100的内存,便可以保证空间够用了,没有用完的空间也不多。
vector是用reserve来提前申请内存空间,这样我们就避免了重复的内存申请和拷贝。
三、实现
void preorder(vector<int> &res, TreeNode* root){
if(!root) return;
res.push_back(root->val);
preorder(res, root->left);
preorder(res, root->right);
}
vector<int> preorderErgodic(TreeNode* root){
vector<int> res;
res.reserve(100);
preorder(res, root);
return res;
}
四、结言
经典的先序遍历算法是每个程序员都应该熟练掌握的经典算法之一,和中序,后序,对二叉树的处理上天生一对。
创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!