树遍历算法概述
树的遍历
遍历定义——指按某条搜索路线遍访每个结点且不重复(又称周游)
遍历用途——它是树结构插入、删除、修改、查找和排序运算的前提,是二叉树一切运算的基础和核心
遍历方法——牢记一种约定,对每个结点的查看都是“先左后右”
实例:
- 先序遍历:ABCDEFGH
- 中序遍历:BDCEAFHG
- 后序遍历:DECBHGFA
树遍历的口诀
- DLR—先序遍历,即先根再左再右
- LDR—中序遍历,即先左再根再右
- LRD—后序遍历,即先左再右再根
简单讲就是根节点先、中、后的顺序。
树的递归遍历代码
public class BiTree { String val; BiTree left; BiTree right; BiTree(String x) { val = x; } }
树的先序遍历
public void preOrder(BiTree root) { if (root == null) { return; } System.out.print(root.val + " "); preOrder(root.left); preOrder(root.right); }
树的中序遍历
public void inOrder(BiTree root) { if (root == null) { return; } inOrder(root.left); System.out.print(root.val + " "); inOrder(root.right); }
树的后序遍历
public void postOrder(BiTree root) { if (root == null) { return; } postOrder(root.left); postOrder(root.right); System.out.print(root.val + " "); }
测试:
/** * A * / \ * B F * / \ * C G * / \ / * D E H */ @Test public void testOrder() { BiTree tn = new BiTree("A"); tn.left = new BiTree("B"); tn.left.right = new BiTree("C"); tn.left.right.left = new BiTree("D"); tn.left.right.right = new BiTree("E"); tn.right = new BiTree("F"); tn.right.right = new BiTree("G"); tn.right.right.left = new BiTree("H"); System.out.print("递归前序遍历:"); preOrder(tn); System.out.println(); System.out.print("递归中序遍历:"); inOrder(tn); System.out.println(); System.out.print("递归后序遍历:"); postOrder(tn); System.out.println(); System.out.print("非递归前序遍历:"); preOrderTraversal(tn); System.out.println(); System.out.print("非递归中序遍历:"); midOrderTraversal(tn); System.out.println(); System.out.print("非递归后序遍历:"); postOrderTraversal(tn); System.out.println(); System.out.print("非递归广度遍历:"); levelOrderTraversal(tn); System.out.println(); }
递归遍历思想
从前面的三种遍历算法可以知道:如果将print语句抹去,从递归的角度看,这三种算法是完全相同的,或者说这三种遍历算法的访问路径是相同的,只是访问结点的时机不同
从虚线的出发点到终点的路径上,每个结点经过3次
第1次经过时访问=先序遍历
第2次经过时访问=中序遍历
第3次经过时访问=后序遍历
二叉树遍历的时间效率和空间效率
时间效率:O(n) //每个结点只访问一次
空间效率:O(n) //栈占用的最大辅助空间(精确值:树深为k的递归遍历需要k+1个辅助单元!)
树的非递归遍历
1、广度优先遍历-层次遍历
/** * 广度优先遍历,非递归实现,需要辅助数据结构:队列 * @param root */ public void levelOrderTraversal(BiTree root) { if (root == null) { System.out.println("empty tree"); return; } ArrayDeque<BiTree> queue = new ArrayDeque<BiTree>(); queue.add(root); while (queue.isEmpty() == false) { BiTree node = queue.remove(); System.out.print(node.val + " "); if (node.left != null) { queue.add(node.left); } if (node.right != null) { queue.add(node.right); } } System.out.print("\n"); }
结果:A B F C G D E H
2、树非递归的先序遍历
算法思想:
/** * 非递归-前序遍历 * * @param root */ public void preOrderTraversal(BiTree root) { if (root == null) return; Stack<BiTree> stack = new Stack<>(); stack.push(root); while (!stack.isEmpty()) { BiTree node = stack.pop(); System.out.print(node.val + " "); if (node.right != null) { stack.push(node.right); } if (node.left != null) { stack.push(node.left); } } }
中序遍历:
/** * 非递归-中序 * * @param root */ public void midOrderTraversal(BiTree root) { if (root == null) return; Stack<BiTree> stack = new Stack<>(); while (root != null || !stack.isEmpty()) { if (root != null) { stack.push(root); root = root.left; } else { BiTree node = stack.pop(); System.out.print(node.val + " "); root = node.right; } } }
后序遍历:
/** * 非递归-后序 * @param root */ public void postOrderTraversal(BiTree root) { if (root == null) return; Stack<BiTree> stack1 = new Stack<>(); Stack<BiTree> stack2 = new Stack<>(); stack1.push(root); while (!stack1.isEmpty()) { root = stack1.pop(); stack2.push(root); if (root.left != null) { stack1.push(root.left); } if (root.right != null) { stack1.push(root.right); } } while (!stack2.isEmpty()) { System.out.print(stack2.pop().val + " "); } }
结果:
递归前序遍历:A B C D E F G H
递归中序遍历:B D C E A F H G
递归后序遍历:D E C B H G F A
非递归前序遍历:A B C D E F G H
非递归中序遍历:B D C E A F H G
非递归后序遍历:D E C B H G F A
非递归广度遍历:A B F C G D E H
全部代码:

import org.junit.Test; import java.util.ArrayDeque; import java.util.Stack; public class Tree { public class BiTree { String val; BiTree left; BiTree right; BiTree(String x) { val = x; } } public void preOrder(BiTree root) { if (root == null) { return; } System.out.print(root.val + " "); preOrder(root.left); preOrder(root.right); } public void inOrder(BiTree root) { if (root == null) { return; } inOrder(root.left); System.out.print(root.val + " "); inOrder(root.right); } public void postOrder(BiTree root) { if (root == null) { return; } postOrder(root.left); postOrder(root.right); System.out.print(root.val + " "); } /** * A * / \ * B F * / \ * C G * / \ / * D E H */ @Test public void testOrder() { BiTree tn = new BiTree("A"); tn.left = new BiTree("B"); tn.left.right = new BiTree("C"); tn.left.right.left = new BiTree("D"); tn.left.right.right = new BiTree("E"); tn.right = new BiTree("F"); tn.right.right = new BiTree("G"); tn.right.right.left = new BiTree("H"); System.out.print("递归前序遍历:"); preOrder(tn); System.out.println(); System.out.print("递归中序遍历:"); inOrder(tn); System.out.println(); System.out.print("递归后序遍历:"); postOrder(tn); System.out.println(); System.out.print("非递归前序遍历:"); preOrderTraversal(tn); System.out.println(); System.out.print("非递归中序遍历:"); midOrderTraversal(tn); System.out.println(); System.out.print("非递归后序遍历:"); postOrderTraversal(tn); System.out.println(); System.out.print("非递归广度遍历:"); levelOrderTraversal(tn); System.out.println(); } /** * 非递归-前序遍历 * * @param root */ public void preOrderTraversal(BiTree root) { if (root == null) return; Stack<BiTree> stack = new Stack<>(); stack.push(root); while (!stack.isEmpty()) { BiTree node = stack.pop(); System.out.print(node.val + " "); if (node.right != null) { stack.push(node.right); } if (node.left != null) { stack.push(node.left); } } } /** * 非递归-中序 * * @param root */ public void midOrderTraversal(BiTree root) { if (root == null) return; Stack<BiTree> stack = new Stack<>(); while (root != null || !stack.isEmpty()) { if (root != null) { stack.push(root); root = root.left; } else { BiTree node = stack.pop(); System.out.print(node.val + " "); root = node.right; } } } /** * 非递归-后序 * @param root */ public void postOrderTraversal(BiTree root) { if (root == null) return; Stack<BiTree> stack1 = new Stack<>(); Stack<BiTree> stack2 = new Stack<>(); stack1.push(root); while (!stack1.isEmpty()) { root = stack1.pop(); stack2.push(root); if (root.left != null) { stack1.push(root.left); } if (root.right != null) { stack1.push(root.right); } } while (!stack2.isEmpty()) { System.out.print(stack2.pop().val + " "); } } /** * 广度优先遍历,非递归实现,需要辅助数据结构:队列 * * @param root */ public void levelOrderTraversal(BiTree root) { if (root == null) { System.out.println("empty tree"); return; } ArrayDeque<BiTree> queue = new ArrayDeque<BiTree>(); queue.add(root); while (queue.isEmpty() == false) { BiTree node = queue.remove(); System.out.print(node.val + " "); if (node.left != null) { queue.add(node.left); } if (node.right != null) { queue.add(node.right); } } System.out.print("\n"); } }
参考:https://blog.csdn.net/Erice_s/article/details/78375302?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_utm_term~default-0.pc_relevant_paycolumn_v3&spm=1001.2101.3001.4242.1&utm_relevant_index=3
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理