二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。
如下便是一棵二叉树:
二叉树的前序遍历:
1. 遍历根节点
2. 如果存在左子树,先序遍历左子树
3. 如果存在右子树,先序遍历右子树
二叉树结构定义:
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
实现方法1:递归
public void preOrder(TreeNode root) {
// 递归结束的条件
if(root==null) return;
// 将当前节点的值加入列表
nodesVal.add(root.val);
// 如果存在左孩子,遍历左孩子
if(root.left!=null) {
preOrder(root.left);
}
// 如果存在右孩子,遍历右孩子
if(root.right!=null) {
preOrder(root.right);
}
}
实现方式2:非递归
public void preOrder1(TreeNode root) {
if(root==null) return;
// 栈,保存访问过的节点
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode node = root;
while(!stack.isEmpty() || node!=null) {
// 一直往左下遍历
while(node!=null) {
stack.push(node);
nodesVal.add(node.val);
node = node.left;
}
// 无左子树的时候,去判断右子树
node = stack.pop();
node = node.right;
}
}
为什么采用“栈”:
我们来看二叉树的前序遍历的特点,先遍历根节点,如果根节点存在左子树,则先遍历左子树,再遍历右子树。而对于左子树,也是同样的遍历方式,先遍历该左子树的根节点,再遍历该左子树的左子树,再遍历该左子树的右子树。也即,一直遍历到最左下。遍历到最左下的时候,如果最左下节点无右子树,则需要回溯到它的父节点,以相同的方式遍历右子树。
在这个回溯的过程中,我们需要能够知道上一个最近访问的节点是哪个,根据这个特点,我们很容易想到“Stack”,也就是栈的特点。栈就是一个后进先出的数据结构,因此,在非递归中采用栈来保存遍历过的节点。
推荐阅读:
二叉树的后序遍历(递归与迭代)
https://blog.csdn.net/Elliot_Elliot/article/details/115744270