前序遍历:根左右

//用栈来实现非递归解法
/**
* 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) {
vector<int> res;
if(root == NULL)
return res;
stack<TreeNode*> stack;
stack.push(root); while(!stack.empty()){
TreeNode* c = stack.top();
stack.pop();
res.push_back(c->val);
if(c->right)
stack.push(c->right);
if(c->left)
stack.push(c->left);
}
return res;
}
};
//递归解法,注意res是全局的,要放在遍历函数外面
/**
* 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> res;
vector<int> preorderTraversal(TreeNode* root) { if(root){
res.push_back(root->val);
preorderTraversal(root->left);
preorderTraversal(root->right);
}
return res;
}
};

中序遍历:左根右

/**
* 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> inorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
if(root == NULL) return res; //若根节点为空则返回空
TreeNode* p = root;
while(p || !st.empty()){
while(p){
//先将根节点入栈,再将它所有的左节点入栈
st.push(p);
p = p->left;
} p = st.top();
st.pop();
res.push_back(p->val);
p = p->right;
}
return res;
}
};

后序遍历:左右根

可以使其遍历顺序为根左右,然后逆序插入vector中,即每次在vector的头部插入结点值。在压入栈时先压入右结点再压入左结点则在出栈时就是先左后右了。

//解法一
/**
* 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> postorderTraversal(TreeNode* root) {
if(!root) return {};
vector<int> res;
stack<TreeNode*> s{{root}};
while(!s.empty()){
TreeNode* t = s.top();
s.pop();
res.insert(res.begin(), t->val);
if(t->left) s.push(t->left);
if(t->right) s.push(t->right);
}
return res;
}
};

解法二:关键是判断当前这个结点:

1)它如果有左右结点是否已经入栈,若没有入栈则先将它的右结点入栈,再左结点入栈;如果它的左右结点已经入栈,则这个结点就可以直接加入容器vector里了。

2)如果它是叶子结点(没有左右结点),则直接加入vector中。

/**
* 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> postorderTraversal(TreeNode* root) {
if(!root) return {};
vector<int> res;
stack<TreeNode*> s{{root}};
TreeNode* head = root; //head初始化
while(!s.empty()){
TreeNode* t = s.top();
if((!t->left && !t->right) || t->left==head || t->right==head){
//当t为叶子结点 或t的左结点或右结点为head,即已经入栈了
res.push_back(t->val);
s.pop();
head = t;
}
else{
if(t->right) s.push(t->right);
if(t->left) s.push(t->left);
}
}
return res;
}
};

leetcode已经分别定义了类NestedInteger中的三个函数:

1)isInteger():若当前这个NestedInteger是单个整数返回true;

2)getInteger():返回当前这个单个的整数;

3)getList():返回当前这个列表。

/**
* // This is the interface that allows for creating nested lists.
* // You should not implement it, or speculate about its implementation
* class NestedInteger {
* public:
* // Return true if this NestedInteger holds a single integer, rather than a nested list.
* bool isInteger() const;
*
* // Return the single integer that this NestedInteger holds, if it holds a single integer
* // The result is undefined if this NestedInteger holds a nested list
* int getInteger() const;
*
* // Return the nested list that this NestedInteger holds, if it holds a nested list
* // The result is undefined if this NestedInteger holds a single integer
* const vector<NestedInteger> &getList() const;
* };
*/
class NestedIterator {
public:
stack<NestedInteger> s; NestedIterator(vector<NestedInteger> &nestedList) {
for(int i=nestedList.size()-; i>=; i--)
//倒序插入 是为了弹出时是正序的
s.push(nestedList[i]);
} int next() {
//返回下一项的值
NestedInteger t = s.top();
s.pop();
return t.getInteger(); //获取对应整数 } bool hasNext() {
//若下一项有值,返回true
while(!s.empty()){
NestedInteger t = s.top();
if(t.isInteger())
return true; //若下一个数是单个整数,返回true
s.pop();
//若下一个数是一个列表,使用getList()得到列表的每个整数倒序插入到栈中
for(int i=t.getList().size()-; i>=; i--)
s.push(t.getList()[i]);
}
return false;
}
}; /**
* Your NestedIterator object will be instantiated and called as such:
* NestedIterator i(nestedList);
* while (i.hasNext()) cout << i.next();
*/

栈和递归的关系 144:Binary Tree Preorder Traversal的更多相关文章

  1. C++版 - LeetCode 144. Binary Tree Preorder Traversal (二叉树先根序遍历,非递归)

    144. Binary Tree Preorder Traversal Difficulty: Medium Given a binary tree, return the preorder trav ...

  2. 二叉树前序、中序、后序非递归遍历 144. Binary Tree Preorder Traversal 、 94. Binary Tree Inorder Traversal 、145. Binary Tree Postorder Traversal 、173. Binary Search Tree Iterator

    144. Binary Tree Preorder Traversal 前序的非递归遍历:用堆来实现 如果把这个代码改成先向堆存储左节点再存储右节点,就变成了每一行从右向左打印 如果用队列替代堆,并且 ...

  3. 【LeetCode】144. Binary Tree Preorder Traversal (3 solutions)

    Binary Tree Preorder Traversal Given a binary tree, return the preorder traversal of its nodes' valu ...

  4. [LeetCode] 144. Binary Tree Preorder Traversal 二叉树的先序遍历

    Given a binary tree, return the preorder traversal of its nodes' values. For example:Given binary tr ...

  5. (二叉树 递归) leetcode 144. Binary Tree Preorder Traversal

    Given a binary tree, return the preorder traversal of its nodes' values. Example: Input: [1,null,2,3 ...

  6. Java [Leetcode 144]Binary Tree Preorder Traversal

    题目描述: Given a binary tree, return the preorder traversal of its nodes' values. For example:Given bin ...

  7. 144 Binary Tree Preorder Traversal(二叉树先序遍历Medium)

    题目意思:二叉树先序遍历,结果存在vector<int>中 解题思路:1.递归(题目中说用递归做没什么意义,我也就贴贴代码吧) 2.迭代 迭代实现: class Solution { pu ...

  8. 【LeetCode】144. Binary Tree Preorder Traversal

    题目: Given a binary tree, return the preorder traversal of its nodes' values. For example:Given binar ...

  9. 【LeetCode】144. Binary Tree Preorder Traversal 解题报告(Python&C++&Java)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 迭代 日期 题目地址:https://leetc ...

随机推荐

  1. SSL认证

    SSL认证 单向认证 1.发一串消息个对方 2.对方用私钥加密后返回 3.本方用对方的公钥解密,验证消息是否正确, 如果消息相同,则本方认可对方 双向认证 本方认证对方 对方认证本方

  2. 面试题:cook和session

    1.首先,Cookie与Session存在的目的是什么? 答:二者都是为了保持客户端访问用户与后台服务器的交互状态,之所以为了保持这种状态,一是为了方便一些业务的实现,另一方面就是为了简化后台服务端的 ...

  3. 19. AUTO INCREMENT 字段

    Auto-increment 会在新记录插入表中时生成一个唯一的数字. AUTO INCREMENT 字段 我们通常希望在每次插入新记录时,自动地创建主键字段的值. 我们可以在表中创建一个 auto- ...

  4. 推荐一款基于XNA的开源游戏引擎《Engine Nine》

    一.前沿导读 XNA是微软基于.Net部署的下一代3D/2D游戏开发框架,其实XNA严格来说类似下一代的DirectX,当然不是说XNA会取代DirectX,但是基于XNA我们对于面向XBOX360, ...

  5. 二度xml<一>

    又一次学习Xml,之前差不多都忘了,为了下半年的面试,为了工作重头来过....... 其实我觉得直接上代码来的更实际点,理论的东西,我们随便找点书看看就行. 下面的代码是为了打印出一个xml文件 xm ...

  6. 在IE11(Win10)中检查up6.2配置

      1.按F12,打开调试模式    2.打开调试程序选项卡 说明:在调试程序选项卡中可看到IE加载的脚本信息是否正确.因为IE有缓存,导致脚本有时不是最新的.    3.打开脚本,up6.js   ...

  7. switch case 判断是否为按钮、设置属性 Load Foreach 绑定事件

    private void button9_Click(object sender, EventArgs e) { foreach (Control CT in this.Controls) {//判断 ...

  8. Redis缓存穿透、缓存雪崩

    缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义. ...

  9. MongoDB单表导出与导入

    mongoexport -h -u dbAdmin -p L-$LpGQ=FJvSf*****([l --authenticationDatabase=project_core_db -d proje ...

  10. python字符串常用方法、分割字符串等

    一.字符串的常用方法 1.str.capitalize()  字符串首字母大写 2.str.center()  把字符串居中 3.str.isalnum() 判断字符串是否含有英文.数字,若有英文和数 ...