文章目录
- 二叉树的基本操作-遍历
- (一)前序遍历(preOrderTraversal)
- 递归实现
- 非递归实现
- (二)中序遍历
- 递归实现
- 非递归实现
- (三)后序遍历
- 递归实现
- 非递归实现
- (四)层序遍历
二叉树的基本操作-遍历
所谓的遍历(Traversal)是指沿着某条搜索路线,依次对树中每个节点均做一次且仅作一次的访问。访问节点后需要进行的操作看具体的问题(比如打印节点内容,数据计算等)。遍历二叉树是其他很多方法的基础,很重要。
二叉树的遍历就前中后和层序遍历四种。前三种有着固定的遍历顺序。
(一)前序遍历(preOrderTraversal)
前序遍历又叫先序遍历。
遍历顺序:根节点、左子树、右子树。
递归实现
//定义树的节点
class TreeNode{
public char val;
public TreeNode left;
public TreeNode right;
//构造方法
public TreeNode(char val){
this.val=val;
}
public TreeNode(){
}
}
public class BinaryTree {
//比较low的创建方法-穷举法
public TreeNode createTree(){
TreeNode A=new TreeNode('A');
TreeNode B=new TreeNode('B');
TreeNode C=new TreeNode('C');
TreeNode D=new TreeNode('D');
TreeNode E=new TreeNode('E');
TreeNode F=new TreeNode('F');
TreeNode H=new TreeNode('H');
TreeNode I=new TreeNode('I');
TreeNode G=new TreeNode('G');
A.left=B;
A.right=C;
B.left=D;
B.right=E;
C.left=F;
C.right=G;
E.right=H;
return A;
}
//前序遍历
public void preOrderTraversal(TreeNode root){
if(root==null) return;
System.out.print(root.val+" ");
preOrderTraversal(root.left);
preOrderTraversal(root.right);
}
}
在TestDemo类中调用打印
public class TestDemo {
public static void main(String[] args) {
BinaryTree binaryTree=new BinaryTree();
TreeNode root=binaryTree.createTree();
//前序遍历
System.out.println("前序:");
binaryTree.preOrderTraversal(root);
System.out.print("");
}
}
运行结果如下:
非递归实现
递归实现需要多次调用函数(自己本身),而函数的调用是在栈上进行的。递归隐式的维护了这个栈,非递归就是显式的把这个栈给模拟出来。我们需要用到一种数据结构-队列。
代码如下:
以下代码是将返回值放在了一个list中。
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res=new ArrayList<>();
if(root==null) return res;
Deque<TreeNode> stack=new LinkedList<TreeNode>();
TreeNode node=root;
while(node!=null || !stack.isEmpty()){
while(node!=null){
res.add(node.val);
stack.push(node);
node=node.left;
}
node=stack.pop();
node=node.right;
}
return res;
}
}
(二)中序遍历
遍历顺序:左子树、根节点、右子树
递归实现
//中序遍历
public void inOrderTraversal(TreeNode root){
if(root==null){
return;
}
preOrderTraversal(root.left);
System.out.print(root.val+" ");
preOrderTraversal(root.right);
}
同上,代码中省略的部分同上,在类TestDemo中运行结果如下:
非递归实现
同上,将代码返回值放在了一个list中。
class Solution {
public List<Integer> inorderTraversal(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){
stack.push(node);
node=node.left;
}
node=stack.pop();//左边为空,就得到栈顶子树的根节点
res.add(node.val);
node=node.right;
}
return res;
}
}
(三)后序遍历
遍历顺序:左子树、右子树、根节点
递归实现
//后序遍历
public void postOrderTraversal(TreeNode root){
if(root==null){
return;
}
preOrderTraversal(root.left);
preOrderTraversal(root.right);
System.out.print(root.val+" ");
}
同上,代码中省略的部分同上,在类TestDemo中运行结果如下:
非递归实现
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 node=null;
while(root!=null || !stack.isEmpty()){
while(root!=null){
stack.push(root);
root=root.left;
}
root=stack.pop();
if(root.right==null || root.right==node){
res.add(root.val);
node=root;
root=null;
}else{
stack.push(root);
root=root.right;
}
}
return res;
}
}
(四)层序遍历
层序遍历就是先遍历深度为1的根节点,再遍历深度为2的子节点,再遍历深度为3的所有子节点…一直到最后的叶子节点。就是按顺序遍历每一层。
//层序遍历(借助队列)
void levelOrderTraversal(TreeNode root){
if(root ==null){
return;
}
Queue<TreeNode> queue=new LinkedList<TreeNode>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode top=queue.poll();
System.out.print(top.val+" ");
if(top.left!=null){
queue.offer(top.left);
}
if(top.right!=null){
queue.offer(top.right);
}
}
}
力扣上有道题是要求将每一层遍历节点都放在一起,也就需要你判断出当前节点在哪一层。我们在上面的代码中不难发现,队列的size就是每层的节点数。
所以代码如下:
//层序遍历(借助队列+将每一层的树节点都放到一个list中 leetcode题目)
public List<List<Integer>> levelOrder(TreeNode root){
//只是为了满足结果的要求
List<List<Integer>> res=new ArrayList<>();
if(root==null){
return null;
}
//队列的作用是用来实现层序遍历的。
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
//size的大小就是一层
int size=queue.size();
List<TreeNode> list=new ArrayList<>();
while(size!=0){
TreeNode top=queue.poll();
list.add(top.val);
if(top.left!=null){
queue.offer(top.left);
}
if(top.right!=null){
queue.offer(top.right);
}
size--;
}
res.add(list);
}
return null;
}