该篇总结关于二叉树前序遍历,中序遍历,后序遍历的各种实用算法(包括递归和遍历)。
先序遍历
先序遍历又称前序遍历,先序遍历(DLR),是二叉树遍历的一种,也叫做前序周游,可记做根左右。先序遍历首先访问根结点然后遍历左子树,最后遍历右子树。
递归表达
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList();
helper(root,list);
return list;
}
public void helper(TreeNode root,List<Integer> list){
if(root==null)return;
list.add(root.val);
helper(root.left,list);
helper(root.right,list);
}
迭代表达
public List<Integer> preorderTraversal(TreeNode root) {
//s1
List<Integer> list = new ArrayList();
Deque<TreeNode> deque = new LinkedList<TreeNode>();
deque.add(root);
while(!deque.isEmpty()){
TreeNode node = deque.removeLast();
if(node!=null){
if(node.right==null&&node.left==null){
list.add(node.val);
}else{
TreeNode right = node.right;
TreeNode left = node.left;
node.right = null;
node.left = null;
deque.add(right);
deque.add(left);
deque.add(node);
}
}
}
return list;
//s2
/*List<Integer> list = new ArrayList();
Deque<TreeNode> deque = new LinkedList<TreeNode>();
deque.add(root);
while(!deque.isEmpty()){
TreeNode node = deque.removeLast();
while(node!=null){
list.add(node.val);
if(node.right!=null)
deque.add(node.right);
node = node.left;
}
}
return list;*/
}
s1和s2是迭代算法的两种表达方式,s1这种方式适用于前序、中序、后序三种遍历,唯一不同点是双端队列添加根节点、右节点和左节点的顺序。下面我们会看到这些变化。
中序遍历
中序遍历(LDR)是二叉树遍历的一种,也叫做中根遍历、中序周游。在二叉树中,中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。
递归表达
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList();
helper(root,list);
return list;
}
public void helper(TreeNode root,List<Integer> list){
if(root==null)return;
helper(root.left,list);
list.add(root.val);
helper(root.right,list);
}
迭代表达
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList();
Deque<TreeNode> deque = new LinkedList<TreeNode>();
deque.add(root);
while(!deque.isEmpty()){
TreeNode node = deque.removeLast();
if(node!=null){
if(node.right==null&&node.left==null){
list.add(node.val);
}else{
TreeNode right = node.right;
TreeNode left = node.left;
node.right = null;
node.left = null;
deque.add(right);
deque.add(node);
deque.add(left);
}
}
}
return list;
}
后序遍历
后序遍历(LRD)是二叉树遍历的一种,也叫做后根遍历、后序周游,可记做左右根。后序遍历有递归算法和非递归算法两种。在二叉树中,先左后右再根,即首先遍历左子树,然后遍历右子树,最后访问根结点。
递归表达
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList();
helper(root,list);
return list;
}
public void helper(TreeNode root,List<Integer> list){
if(root==null)return;
helper(root.left,list);
helper(root.right,list);
list.add(root.val);
// helper(root.left,list);
//helper(root.right,list);
}
迭代表达
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList();
Deque<TreeNode> deque = new LinkedList<TreeNode>();
deque.add(root);
while(!deque.isEmpty()){
TreeNode node = deque.removeLast();
if(node!=null){
if(node.right==null&&node.left==null){
list.add(node.val);
}else{
TreeNode right = node.right;
TreeNode left = node.left;
node.right = null;
node.left = null;
deque.add(node);
deque.add(right);
deque.add(left);
}
}
}
return list;
}
总结
可以看到三种遍历方式在代码表达上都差不多,无论递归还是迭代,只要掌握其中一种,其它两种都掌握了!!!!还是非常实用的。