每日一算法题-先序遍历

128 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

一、题目

image.png

#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;
}

四、结言

经典的先序遍历算法是每个程序员都应该熟练掌握的经典算法之一,和中序,后序,对二叉树的处理上天生一对。

创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!