二叉树的遍历
1、前序遍历
root -> left -> right
规则是若二叉树为空,则空操作返回;否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。
2、中序遍历
left -> root- > right
规则是若二叉树为空,则空操作返回;否则从根结点开始(注意并不是先访问根节点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。
3、后序遍历
left -> right -> root
规则是若二叉树为空,则空操作返回;否则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。、
前序遍历代码
①递归
class Solution {
List<Integer> list = new ArrayList<Integer>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null){
return list;
}
list.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return list;
}
}
②迭代
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode node = root;
while (!stack.isEmpty() || node != null) {
while (node != null) {
res.add(node.val);
stack.push(node);
node = node.left;
}
node = stack.pop();
node = node.right;
}
return res;
}
}
中序遍历代码
①递归
class Solution {
List<Integer> list = new ArrayList<Integer>();
public List<Integer> inorderTraversal(TreeNode root) {
if(root == null){
return list;
}
inorderTraversal(root.left);
list.add(root.val);
inorderTraversal(root.right);
return list;
}
}
②迭代
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
Deque<TreeNode> stk = new LinkedList<TreeNode>();
while (root != null || !stk.isEmpty()) {
while (root != null) {
stk.push(root);
root = root.left;
}
root = stk.pop();
res.add(root.val);
root = root.right;
}
return res;
}
}
后序遍历代码
①递归
class Solution {
List<Integer> list = new ArrayList<Integer>();
public List<Integer> postorderTraversal(TreeNode root) {
if(root == null){
return list;
}
postorderTraversal(root.left);
postorderTraversal(root.right);
list.add(root.val);
return list;
}
}
②迭代
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode prev = null;
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
if (root.right == null || root.right == prev) {
res.add(root.val);
prev = root;
root = null;
} else {
stack.push(root);
root = root.right;
}
}
return res;
}
}
最后,分析比较可知,三种遍历方法(递归)的不同之处仅仅是代码顺序不一样。
首次编辑于 2021年11月7日
---------------------------------------分割线----------------------------------------------
【注意】如果一棵树是二叉排序树(又称 二叉搜索树),那么中序遍历得到的是递增序列。
因为二叉排序树具有以下性质:
定义一:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的结点。
定义二:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
定义三:
(1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
【注】:以上的三种定义在不同的数据结构教材中均有不同的定义方式,但是都是正确的,在开发时需要根据不同的需求进行选择
第一次修改于 2021年12月1日