二叉树练习——二叉树的中序遍历、前序遍历和后序遍历
二叉树
二叉树结构是一个节点上最多有两个子树的树结构。定义二叉树是用指针来定义树中的每个节点,包括一个节点值、一个指向左子树的左指针和一个指向右子树的右指针。如图所示
代码如下所示
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
假如有一棵二叉树如下图所示
中序遍历就是按照“左节点——根节点——右节点”这样的顺序进行遍历,以上图为例,中序遍历的结果为
[
左
子
树
,
1
,
右
子
树
]
=
[
[
左
子
树
,
2
,
右
子
树
]
,
1
,
[
左
子
树
,
3
,
右
子
树
]
]
=
[
[
[
左
子
树
,
4
,
右
子
树
]
,
2
,
[
左
子
树
,
5
,
右
子
树
]
]
,
1
,
[
[
左
子
树
,
6
,
右
子
树
]
,
3
,
[
左
子
树
,
7
,
右
子
树
]
]
]
=
[
8
,
4
,
2
,
5
,
9
,
1
,
3
,
6
,
10
,
7
]
\begin{aligned} &\left[ 左子树,1,右子树 \right]\\ =&\left[ \left[ 左子树,2,右子树\right],1,\left[ 左子树,3,右子树 \right] \right]\\ =&\left[ \left[ \left[左子树,4,右子树\right],2,\left[左子树,5,右子树\right]\right],1,\left[ \left[左子树,6,右子树\right],3,\left[左子树,7,右子树\right] \right] \right]\\ =&\left[8,4,2,5,9,1,3,6,10,7\right] \end{aligned}
===[左子树,1,右子树][[左子树,2,右子树],1,[左子树,3,右子树]][[[左子树,4,右子树],2,[左子树,5,右子树]],1,[[左子树,6,右子树],3,[左子树,7,右子树]]][8,4,2,5,9,1,3,6,10,7]
前序遍历就是按照“根节点——左节点——右节点”这样的顺序进行遍历,以上图为例,前序遍历的结果为
[
1
,
左
子
树
,
右
子
树
]
=
[
1
,
[
2
,
左
子
树
,
右
子
树
]
,
[
3
,
左
子
树
,
右
子
树
]
]
=
[
1
,
[
2
,
[
4
,
左
子
树
,
右
子
树
]
,
[
5
,
左
子
树
,
右
子
树
]
]
,
[
3
,
[
6
,
左
子
树
,
右
子
树
]
,
[
7
,
左
子
树
,
右
子
树
]
]
]
=
[
1
,
2
,
4
,
8
,
5
,
9
,
3
,
6
,
10
,
7
]
\begin{aligned} &\left[ 1,左子树,右子树 \right]\\ =&\left[1, \left[ 2,左子树,右子树\right],\left[ 3,左子树,右子树 \right] \right]\\ =&\left[ 1,\left[2, \left[4,左子树,右子树\right],\left[5,左子树,右子树\right]\right],\left[ 3,\left[6,左子树,右子树\right],\left[7,左子树,右子树\right] \right] \right]\\ =&\left[1,2,4,8,5,9,3,6,10,7\right] \end{aligned}
===[1,左子树,右子树][1,[2,左子树,右子树],[3,左子树,右子树]][1,[2,[4,左子树,右子树],[5,左子树,右子树]],[3,[6,左子树,右子树],[7,左子树,右子树]]][1,2,4,8,5,9,3,6,10,7]
后序遍历就是按照“左节点——右节点——根节点”这样的顺序进行遍历,以上图为例,后序遍历的结果为
[
左
子
树
,
右
子
树
,
1
]
=
[
[
左
子
树
,
右
子
树
,
2
]
,
[
左
子
树
,
右
子
树
,
3
]
,
1
]
=
[
[
[
左
子
树
,
右
子
树
,
4
]
,
[
左
子
树
,
右
子
树
,
5
]
,
2
]
,
[
[
左
子
树
,
右
子
树
,
6
]
,
[
左
子
树
,
右
子
树
,
7
]
,
3
]
,
1
]
=
[
8
,
4
,
9
,
5
,
2
,
10
,
6
,
7
,
3
,
1
]
\begin{aligned} &\left[ 左子树,右子树,1 \right]\\ =&\left[ \left[ 左子树,右子树,2\right],\left[ 左子树,右子树,3 \right],1 \right]\\ =&\left[ \left[ \left[左子树,右子树,4\right],\left[左子树,右子树,5\right],2\right],\left[ \left[左子树,右子树,6\right],\left[左子树,右子树,7\right],3 \right] ,1\right]\\ =&\left[8,4,9,5,2,10,6,7,3,1\right] \end{aligned}
===[左子树,右子树,1][[左子树,右子树,2],[左子树,右子树,3],1][[[左子树,右子树,4],[左子树,右子树,5],2],[[左子树,右子树,6],[左子树,右子树,7],3],1][8,4,9,5,2,10,6,7,3,1]
Leetcode二叉树的中序遍历
问题描述:
给定一个二叉树,返回它的中序遍历。
示例:
输入:[1,null,2,3]
输出:[1,3,2]
思考:
定义一个栈,从树的根节点开始,沿着左子树开始遍历,并将遍历到的左子节点存到栈中。当这一条路线上的左子节点全部存入栈中后,开始出栈,并将当前树节点指针指向右子节点,并继续从该右子节点继续将左子节点压栈出栈
具体代码如下
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
order_result = [] #储存排序结果
read_tree = [] #用来将读到的树节点进行存储的栈
current_node = root
while current_node != None or len(read_tree) != 0:
while current_node != None:
#找到每一树枝上最左边的节点,并把路径上的树节点存入栈中
read_tree.append(current_node)
current_node = current_node.left
#当读取到每条路径上的最左边的节点后,
#将栈中最后进入的节点进行出栈,也就是该路径上最左边的节点,
#然后从当前节点下遍历它的右子树
data = read_tree.pop()
order_result.append(data.val)
current_node = data.right
return order_result
Leetcode二叉树的前序遍历
问题描述:
给定一个二叉树,返回它的前序遍历。
示例:
输入:[1,null,2,3]
输出:[1,2,3]
思考:
定义一个栈,从树的根节点开始,沿着左子树开始遍历,并将遍历到的左子节点存到栈中,同时将当前节点的值进行存储。这样做是因为在从根遍历的过程中,每经过的节点都是该节点子树的根节点。前序遍历就是先将根节点进行存储。当这一条路线上的左子节点全部存入栈中后,开始出栈,并将当前树节点指针指向右子节点,并继续从该右子节点进行上述操作
具体代码如下
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
order_result = []
read_tree = []
current_node = root
while current_node != None or len(read_tree) != 0:
while current_node != None:
#将遍历到的当前节点值存入列表,同时将该节点压入栈中,并指向该节点的左子节点
order_result.append(current_node.val)
read_tree.append(current_node)
current_node = current_node.left
#当遍历完一条路径后,将最后入栈的节点出栈,并从该节点的右子节点开始遍历
current_node = read_tree.pop()
current_node = current_node.right
return order_result
Leetcode二叉树的后序遍历
问题描述:
给定一个二叉树,返回它的后序遍历。
示例:
输入:[1,null,2,3]
输出:[3,2,1]
思考:
定义一个栈,从树的根节点开始,沿着左子树开始遍历,并将遍历到的左子节点存到栈中。如果当前节点没有左子节点,就要将他的右子节点进行入栈处理,直到遍历到既没有左子节点也没有右子节点时停止。这是因为后序遍历的顺序是“左——右——根”,如果不将整条路径上的所有的节点遍历到,后续出栈存值时,就会将没有左子节点而有右子节点的节点出栈存值。
将整条路径上的节点入栈后,开始出栈存值,并将当前节点指向其根节点的右子节点,从右子树开始遍历。这样做也是为了将右子节点的值保存在根节点值之前。
具体代码如下
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
order_result = []
read_tree = []
current_node = root
while current_node != None or len(read_tree) != 0:
while current_node != None:
read_tree.append(current_node)
if current_node.left != None:
current_node = current_node.left
else:
current_node = current_node.right
current_node = read_tree.pop()
order_result.append(current_node.val)
if len(read_tree) != 0 and current_node == read_tree[-1].left:
current_node = read_tree[-1].right
else:
current_node = None
return order_result