leetcode:Preorder Traversal(树的先序
最终代码请拉到结尾:
先序遍历:
若二叉树为空,则不进行任何操作:否则
1、访问根结点。
2、先序方式遍历左子树。
3、先序遍历右子树。
简称:根左右
以下图为例进行先序遍历:
image.png遍历过程如下:
[A,A left,A right]
-->[A,B,B left, B right,C,C left,C right]
--->[A,B,D,E,C,F,F left,G]
-->[A,B,D,E,C,F,H,G]
理解节点
在对节点TreeNode的抽象中,TreeNode具有三个属性,分别是val、left和right,val表示节点的值,而left和right分别指向左右两个子节点(默认为None)。
思路
需要一个长度可变的变量来存储结果。这里可以使用列表preorderlist。
从上面的分析,第一步是得到[A,A left,A right]
具体怎么做呢,需要从根节点A出发,然后将preorderList.append(A),然后应该做判断,如果存在左节点,那么就preorderList.append(A.left),如果存在右节点,就preorderList.append(A.right),那么第一步就可以实现[A,A left,A right].
image.png然后我们怎么进行到下一步,可以令A = A.left或者A = A.right吗?
答案是不行,因为这样我们一步只能完成左边或者右边的添加。而且左右节点可能存在也可能不存在,所以要执行的次数也是不确定的。
解决方法:
额外添加一个数组stack,这个数组存在的作用相当于确定要执行的次数。这么说可能有点悬。还是以上面的数组为例,先让数组stack = []。
先把A添加进stack中。然后再把A从stack中pop出来,这时候只需要pop一个元素(就是A)。再把A添加到preorderList中。然后继续判断node.right和node.left存在与否,如果存在就添加到stack中。
接下来怎么办,继续pop
image.png也就是说,可以将node = stack.pop()之后的内容变成一个循环。
上面说了左右节点可能存在可能不存在,所以stack.pop()的具体执行次数是不确定,但是反正必须要pop到stack为空。
所以这里可以用while循环。只要stack != [],就继续进行操作。因此上面的代码可以修改成:
stack的左右问题:
还有一点注意的是,将stack的元素pop出来放到preorderList去的时候,由于最后的结果要求是按照“根左右”的顺序,那么stack中就应该按照“右左”的顺序进行添加,所以先判断node.right,如有右节点先添加右节点。
image.png