二叉树的非递归遍历和递归遍历
前言
二叉树的遍历有前序遍历、中序遍历、后续遍历、层序遍历。然后我们分别实现一下各种遍历的递归与非递归的方式,树节点定义如下:
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
前序遍历
前序遍历是指我们的二叉树先遍历root节点,然后遍历左节点,最后是右节点
递归
public void preOrder(TreeNode root){
if (root == null){
return;
}
//输出当前节点的值
System.out.println(root.val);
//遍历做子树
preOrder(root.left);
//遍历右子树
preOrder(root.right);
}
非递归
public void preOrder(TreeNode root){
if (root == null){
return;
}
//借助栈先进后出的特性,先将root.right存入,在存入root.left
Stack stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
System.out.println(node.val);
if (node.right != null){
stack.push(node.right);
}
if (node.left != null){
stack.push(node.left);
}
}
}
中序遍历
递归
public void midOrder(TreeNode root){
if (root == null){
return;
}
//遍历做子树
preOrder(root.left);
//输出当前节点的值
System.out.println(root.val);
//遍历右子树
preOrder(root.right);
}
非递归
public void midOrder(TreeNode root){
if (root == null){
return;
}
Stack stack = new Stack<>();
do {
//如果左节点一直有,一直压栈
while (root != null){
stack.push(root);
root = root.left;
}
//出栈,判断是否有右孩子,如果有,就要继续压栈
TreeNode node = stack.pop();
System.out.println(node.val);
if (node.right != null){
root = node.right;
}
}while (root!= null || !stack.isEmpty());
}
后序遍历
递归
public void afterOrder(TreeNode root){
if (root == null){
return;
}
//遍历做子树
preOrder(root.left);
//遍历右子树
preOrder(root.right);
//输出当前节点的值
System.out.println(root.val);
}
非递归
public void afterOrder(TreeNode root){
if (root == null){
return;
}郑州妇科哪家好 http://www.zzkdfk.com/
//借助两个栈来实现,因为要先遍历右孩子才能root节点,所以root节点要在s2的最底部
Stack s1 = new Stack<>();
Stack s2 = new Stack<>();
s1.push(root);
while (!s1.isEmpty()){
TreeNode node = s1.pop();
if (node.left != null){
s1.push(node.left);
}
if (node.right != null){
s1.push(node.right);
}
s2.push(node);
}
while (!s2.isEmpty()){
System.out.println(s2.pop().val);
}
}
层序遍历
层序遍历是指将二叉树的节点一层一层的遍历出来,这里我假设将节点存入list,采用BFS的方式遍历节点。
public List> levelOrder(TreeNode root) {
//存访每一层的结果
List> lists = new ArrayList<>();
if (root == null){
return lists;
}
//借助队列存放每一层的节点
Queue queue = new LinkedBlockingQueue<>();
queue.add(root);
while (!queue.isEmpty()){
List list = new ArrayList<>();
int size = queue.size();
//获取当前队列中的所有节点,然后将每个节点的左右孩子放入队列,以提供下层循环输出
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
list.add(node.val);
if (node.left != null){
queue.add(node.left);
}
if (node.right != null){
queue.add(node.right);
}
}
//每一层的list存入lists
lists.add(list);
}
return lists;
}