由于之前看了牛客网的数据结构和算法的课程知道了左神,现在找到了这本书当作入门书做做吧,虽然书的题解都是java实现的,但好在用c++实现难度不大
第三章 二叉树问题
第一题:递归与非递归实现二叉树三序遍历
前序遍历首先访问根结点,然后遍历左子树,最后遍历右子树。
中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。
后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点。
本质是中左右遍历第几次经过头结点罢了。
递归版本
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int>* a = new vector<int>;
preorderRecur(root, *a);
return *a;
}
void preorderRecur(TreeNode* root,vector<int> &a) {
if (root == nullptr)return;
a.push_back(root->val);
preorderRecur(root->left,a);//递归不是压栈,先左递归再右
preorderRecur(root->right, a);
}
};
另外两个的递归版本只需要将push_back的位置换一下就行了这里不再写出
其实用递归方法解决的问题都能用非递归的方法实现。这是因为递归方法无非就是利用函数来保存信息,如果用自己申请的数据结构来代替函数栈,也可以实现相同的功能,无非就是麻烦了些,因为递归可以将整个函数的信息都保留,而手动非递归想做到那么精细就很麻烦。
先序非递归遍历版本
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
if(root==nullptr)return *(new vector<int>);
vector<int>* a = new vector<int>;
preorderRecur(root, *a);
return *a;
}
void preorderRecur(TreeNode* root, vector<int> &a) {
stack<TreeNode*> stack1;
stack1.push(root);
while (!stack1.empty())//从栈中弹出栈顶节点,记为cur,然后打印cur的值,再将节点的右孩子(不为空的话)先压入栈中,最后将cur的左孩子(不为空的话)压入栈中。
{
TreeNode* cur = stack1.top();
a.push_back(cur->val);
stack1.pop();
if (cur->right != nullptr)
stack1.push(cur->right);//先压右再压左
if (cur->left != nullptr)
stack1.push(cur->left);
}
}
};
中序非递归遍历版本
#include "pch.h"
#include <iostream>
#include<vector>
#include<stack>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int>* a = new vector<int>;
inorderRecur(root, *a);
return *a;
}
void inorderRecur(TreeNode* root, vector<int> &a) {
stack<TreeNode*> stack1;
TreeNode* cur= root;
while (!stack1.empty()||cur!=nullptr)//从栈中弹出栈顶节点,记为cur,然后打印cur的值,再将节点的右孩子(不为空的话)先压入栈中,最后将cur的左孩子(不为空的话)压入栈中。
{
if (cur != nullptr) {//一棵树可以看成三角形以右下角为顶点然后从这个三角形的左下角开始遍历
stack1.push(cur);
cur = cur->left;
}
else {//第二次回到当前节点
a.push_back(stack1.top()->val);
cur = stack1.top()->right;
stack1.pop();
}
}
}
};
后序非递归遍历版本
先序遍历是中左右,先将它改成中右左的版本,再使用一个辅助栈将先序出来的再反转一遍就可以做到左右中即后序遍历了
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
if (root == nullptr)return *(new vector<int>);
vector<int>* a = new vector<int>;
preorderRecur(root, *a);
return *a;
}
void preorderRecur(TreeNode* root, vector<int> &a) {
stack<TreeNode*> stack1;
vector<int> tmp;
stack1.push(root);
while (!stack1.empty())//从栈中弹出栈顶节点,记为cur,然后打印cur的值,再将节点的左孩子(不为空的话)先压入栈中,最后将cur的右孩子(不为空的话)压入栈中。
{
TreeNode* cur = stack1.top();
tmp.push_back(cur->val);
stack1.pop();
if (cur->left != nullptr)
stack1.push(cur->left);//先序是先压右再压左,这里为了改成后序变成先压左再压右
if (cur->right != nullptr)
stack1.push(cur->right);
}
for (int i = tmp.size(); i>0; i--) {
a.push_back(tmp[i - 1]);
}
}
};