要求

  • 二叉树的前序遍历

实现

  • 递归

  • 栈模拟

        

  • 定义结构体 Command 模拟指令,字符串s描述命令,树节点node为指令作用的节点
  • 定义栈 Stack 存储命令
 1 #include <iostream>
2 #include <vector>
3 #include <stack>
4 #include <cassert>
5
6 using namespace std;
7
8 struct TreeNode{
9 int val;
10 TreeNode* left;
11 TreeNode* right;
12 TreeNode(int x): val(x), left(NULL), right(NULL){}
13 };
14
15 //模拟指令,go--访问,print--输出
16 struct Command{
17 string s;
18 TreeNode* node;
19 Command(string s, TreeNode* node):s(s), node(node){}
20 };
21
22 class Solution{
23 public:
24 vector<int> preorderTraversal(TreeNode* root){
25 vector<int> res;
26 if( root == NULL )
27 return res;
28
29 stack<Command> stack;
30 stack.push( Command("go",root) );
31
32 while( !stack.empty() ){
33
34 Command command = stack.top();
35 stack.pop();
36
37 if( command.s == "print" )
38 res.push_back( command.node -> val);
39 else{
40 assert( command.s == "go" );
41 if( command.node -> right )
42 stack.push( Command("go",command.node->right));
43 if( command.node -> left)
44 stack.push( Command("go",command.node->left));
45 stack.push( Command("print",command.node));
46 }
47 }
         return res;
48 }
49 };
50
51 void print_vec(const vector<int>& vec){
52 for(int e:vec)
53 cout<<e<<" ";
54 cout<<endl;
55 }
56
57 int main(){
58 TreeNode* root = new TreeNode(1);
59 root->right = new TreeNode(2);
60 root->right->left = new TreeNode(3);
61 vector<int> res = Solution().preorderTraversal(root);
62 print_vec(res);
63
64 return 0;
65 }

结果

1-2-3

总结

  • 模拟了操作系统中方法栈的实现
  • 入栈顺序与实际执行顺序相反
  • 操作指令,而不是操作对象,把对象的指针封装在指令中
  • LeetCode 94为模拟中序遍历,145为模拟后序遍历
  • 本程序可以很容易地改写为中序和后序,而课本中的写法很难改写

-----------------------------------------------

栈模拟中序遍历

  • Python
 1 class Stack(object):
2 def __init__(self, size_limit = None):
3 self._size_limit = size_limit
4 self.elements = []
5 self._size = 0
6
7 def push(self, value):
8 if self._size_limit is not None and len(self.elements) > self._size_limit:
9 raise IndexError("Stack is full")
10 else:
11 self.elements.append(value)
12 self._size += 1
13
14 def top(self):
15 return self.elements[-1]
16
17 def pop(self):
18 val = self.elements.pop()
19 self._size -=1
20 return val
21
22 def is_empty(self):
23 return self._size == 0
24
25
26 class Node:
27 def __init__(self, val):
28 self.val = val
29 self.lchild = None
30 self.rchild = None
31 self.flag = True
32
33 def dfs(node):
34 if node is None:
35 return
36 dfs(node.lchild)
37 print(node.val)
38 dfs(node.rchild)
39
40 def dfs1(node):
41 stack = Stack()
42 stack.push(node)
43 while not stack.is_empty():
44 tmp = stack.top()
45 while tmp.flag and tmp.lchild is not None:
46 tmp.flag = False
47 stack.push(tmp.lchild)
48 tmp = tmp.lchild
49 tmp = stack.pop()
50 print(tmp.val)
51 if tmp.rchild is not None:
52 stack.push(tmp.rchild)
53
54 def dfs2(node):
55 stack = Stack()
56 tmp = node
57 while tmp is not None or not stack.is_empty():
58 while tmp is not None:
59 stack.push(tmp)
60 tmp = tmp.lchild
61 tmp = stack.pop()
62 print(tmp.val)
63 tmp = tmp.rchild
64
65 root = Node(0)
66 node1 = Node(1)
67 root.lchild = node1
68 node2 = Node(2)
69 root.rchild = node2
70 node3 = Node(3)
71 node1.lchild = node3
72 node4 = Node(4)
73 node1.rchild = node4
74 node5 = Node(5)
75 node2.rchild = node5
76
77 dfs(root)
78 dfs1(root)
79 dfs2(root)

>> 3 1 4 0 2 5

    • dfs是常规递归思路
    • dfs1增加了一个flag变量,判断节点是否访问过,不加会导致死循环
    • dfs2调整了思路,不用flag变量
  • c++方法1
 1 class Solution {
2
3 public:
4 vector<int> inorderTraversal(TreeNode* root) {
5
6 vector<int> res;
7 if( root == NULL )
8 return res;
9
10 stack<TreeNode*> stack;
11 TreeNode* cur = root;
12 while(cur != NULL || !stack.empty()){
13
14 if(cur != NULL){
15 stack.push(cur);
16 cur = cur->left;
17 }
18 else {
19 cur = stack.top();
20 stack.pop();
21 res.push_back(cur->val);
22 cur = cur->right;
23 }
24 }
25 return res;
26 }
27 };
  • c++方法2
 1 class Solution {
2
3 public:
4 vector<int> inorderTraversal(TreeNode* root) {
5
6 vector<int> res;
7 if( root == NULL )
8 return res;
9
10 stack<TreeNode*> stack;
11 TreeNode* cur = root;
12 while(cur != NULL || !stack.empty()){
13
14 while(cur != NULL){
15 stack.push(cur);
16 cur = cur->left;
17 }
18
19 cur = stack.top();
20 stack.pop();
21 res.push_back(cur->val);
22 cur = cur->right;
23
24 }
25 return res;
26 }
27 };

总结

  • 默认的访问顺序是从左到右,意味着左节点优先访问
  • 中序遍历的定义是,从左节点返回时输出,这就意味着如果都是左节点,节点是从下到上输出的(后进先出),故想到利用栈实现;如果都是右节点,则节点从上到下输出,此时需控制栈,使元素不堆积
  • 想清楚了怎么处理左节点,怎么处理右节点,如何移动指针,如何利用栈,就可以写代码了
  • 左节点优先访问反映在代码上就是指针指向左节点的语句在指针指向右节点之前,中序遍历反映在代码上就是节点先入栈出栈再输出
  • 方法2表面上是两层循环,其实内外循环执行次数加起来和方法1是一样的,两种算法时间复杂度取决于节点个数,都是O(n)
  • 方法1的逻辑更顺畅,方法2利用了左节点优先的规则,将左节点连续出现的循环内移,在左节点连续出现的情况下执行效率更高(少一次判断),可看做方法1的优化

[刷题] 144 Binary Tree Preorder Traversal的更多相关文章

  1. 二叉树前序、中序、后序非递归遍历 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 前序的非递归遍历:用堆来实现 如果把这个代码改成先向堆存储左节点再存储右节点,就变成了每一行从右向左打印 如果用队列替代堆,并且 ...

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

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

  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. 刷题94. Binary Tree Inorder Traversal

    一.题目说明 题目94. Binary Tree Inorder Traversal,给一个二叉树,返回中序遍历序列.题目难度是Medium! 二.我的解答 用递归遍历,学过数据结构的应该都可以实现. ...

  6. 【LeetCode】144. Binary Tree Preorder Traversal

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

  7. Java for LeetCode 144 Binary Tree Preorder Traversal

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

  8. 144. Binary Tree Preorder Traversal

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

  9. leetcode 144. Binary Tree Preorder Traversal ----- java

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

随机推荐

  1. 谷歌SRE运维模式解读

    谷歌SRE运维模式解读 前面我和你分享了一些关于运维组织架构和协作模式转型的内容,为了便于我们更加全面地了解先进的运维模式,今天我们再来谈一下谷歌的SRE(Site Reliability Engin ...

  2. [Azure DevOps] 如何安装并配置 Build Agent

    1. 编译服务器 在 Azure Pipelines 中至少需要一个编译服务器的 Agent 才能编译代码或发布软件.Azure DevOps 本身已经提供了一个 Agent,但出于各种理由(需要特殊 ...

  3. kubernets-java 动态修改deployment 的replicas

    /** * Scale up/down the number of pod in Deployment * * @param deploymentName * @param numberOfRepli ...

  4. NumPy之:数据类型

    目录 简介 数组中的数据类型 类型转换 查看类型 数据溢出 简介 我们知道Python中有4种数字类型,分别是int,float,bool和complex.作为科学计算的NumPy,其数据类型更加的丰 ...

  5. 浅谈在c#中使用Zlib压缩与解压的方法

    作者:Compasslg 介绍 近期用c#开发一个游戏的存档编辑工具需要用 Zlib 标准的 Deflate 算法对数据进行解压. 在 StackOverflow 上逛了一圈,发现 c# 比较常用到的 ...

  6. git 让忽略.gitignore文件马上生效

    在.gitignore文件里面输入 *.zip 表示所有zip文件忽略更改 /bin 表示忽略整个根目录的bin文件夹 /src/aa.jar 表示忽略/src/aa.jar文件 设置完.gitign ...

  7. OO第四单元总结与课程总结

    OO第四单元总结与课程总结 第四单元作业架构设计 总体分析:本单元作业的需求集中于对UML类图进行查询.对于查询操作来说自然的想法是提前预见到需要查询的内容,在一开始就采用适当的数据结构将必要的信息进 ...

  8. red and black(BFS)

    Red and Black Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 40685   Accepted: 22079 D ...

  9. linux 安装rabbitMQ详细教程

    经过第一次的安装失败, 第二次总算是成功了, 这里总结一下. 第一步:下载版本对应的rpm安装包 1. 下载Erlang安装包:RabbitMQ是Erlang语言编写,所以Erang环境必须要有,注: ...

  10. hdu1556 线段树段更新(简单题)

    题意: N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽"牌电动车从气球a开始到气球b依次给每个 ...