介绍树的三种非递归遍历代码的Java实现及应用。
算法
创建内部接口 Visitor ,通过传入方法来实现对遍历元素的定制操作。
1 2 3 4 5 6 7 8 9
| public interface Visitor<E>{ boolean stop = false; boolean visit(TreeNode<E> node); }
protected Visitor visitor = (node) -> { System.out.print(node.element + " "); return false; };
|
使用:
1 2 3 4 5 6
| BinaryTree<Integer> tree = new BinaryTree<>(); tree.preorder((node) -> { if(node.element == 2) return true; node.element ++; return false; })
|
先序遍历
递归:
1 2 3 4 5 6 7
| private void preorder1(Visitor visitor){ if(root==null || visitor.stop) return;
visitor.visit(root); preorder1(root.left,visitor); preorder1(root.right,visitor); }
|
非递归:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| private void preorder2(Visitor visitor) { TreeNode<E> node = root; Stack<TreeNode<E>> stack = new LinkedStack<TreeNode<E>>(); List<TreeNode<E>> visited = new LinkedList<TreeNode<E>>(); if(visitor.stop) return; visitor.visit(node); visited.add(node); stack.push(node); while(visited.size() < size) { if(visitor.stop) return; if(node.left != null && !visited.contains(node.left)) { visitor.visit(node.left); visited.add(node.left); stack.push(node.left); node = node.left; } else if (node.right != null && !visited.contains(node.right)) { visitor.visit(node.right); visited.add(node.right); stack.push(node.right); node = node.right; } else { node = stack.pop(); } } }
|
中序遍历
递归:
1 2 3 4 5 6 7 8
| private void inorder1(Visitor visitor){ if(root==null || visitor.stop) return;
inorder1(root.left,visitor); if(visitor.stop) return; visitor.visit(root); inorder1(root.right,visitor); }
|
非递归:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| private void inorder2(Visitor visitor){ TreeNode<E> node = root; List<TreeNode<E>> visited = new LinkedList<TreeNode<E>>(); Stack<TreeNode<E>> stack = new LinkedStack<TreeNode<E>>(); stack.push(node); while(node.left != null) { stack.push(node.left); node = node.left; } node = stack.pop(); while(visited.size() < size) { if(node.left != null && !visited.contains(node.left)) { stack.push(node); node = node.left; } else { if(visitor.stop) return; visitor.visit(node); visited.add(node); if(node.right != null && !visited.contains(node.right)) { node = node.right; } else { node = stack.pop(); } } } }
|
后序遍历
递归:
1 2 3 4 5 6 7 8
| private void postorder1(Visitor visitor){ if(root==null || visitor.stop) return;
postorder1(root.left,visitor); postorder1(root.right,visitor); if(visitor.stop) return; visitor.visit(root); }
|
非递归:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| private void postorder2(TreeNode<E> root,Visitor visitor){ TreeNode<E> node = root; List<TreeNode<E>> visited = new LinkedList<TreeNode<E>>(); Stack<TreeNode<E>> stack = new LinkedStack<TreeNode<E>>(); stack.push(node); while(node.left != null) { stack.push(node.left); node = node.left; } node = stack.pop(); while(visited.size() < size) { if((node.left != null && !visited.contains(node.left)) || (node.right != null && !visited.contains(node.right))) { stack.push(node); if(node.left != null && !visited.contains(node.left)) { node = node.left; } else { node = node.right; } } else { if(visitor.stop) return; visitor.visit(node); visited.add(node); node = stack.pop(); } } }
|
层序遍历
1 2 3 4 5 6 7 8 9 10 11
| private void levelorder(Visitor visitor){ Queue<TreeNode<E>> queue = new LinkedQueue<TreeNode<E>>(); queue.offer(root); while(!queue.isEmpty()){ TreeNode<E> node = queue.poll(); if(visitor.stop) break; visitor.visit(node); if(node.left!=null) queue.offer(node.left); if(node.right!=null) queue.offer(node.right); } }
|
应用
计算树的高度
计算树的节点数量
复制树
非递归:(先序遍历)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public BinaryTree<E> copy() { TreeNode<E> newRoot = new TreeNode<>(root.element); TreeNode<E> p = newRoot; TreeNode<E> node = root; List<TreeNode<E>> visited = new LinkedList<TreeNode<E>>(); Stack<TreeNode<E>> stack = new LinkedStack<TreeNode<E>>(); visited.add(newRoot); while (visited.size() != size) { if(node.left != null && !visited.contains(node.left)) { stack.push(node); TreeNode<E> newNode = new TreeNode<E>(node.left.element); visited.add(node.left); p.left = newNode; newNode.parent = p; node = node.left; p = p.left; } else if(node.right != null && !visited.contains(node.right)) { stack.push(node); TreeNode<E> newNode = new TreeNode<E>(node.right.element); visited.add(node.right); p.right = newNode; newNode.parent = p; node = node.right; p = p.right; } else { node = stack.pop(); p = p.parent; } } BinaryTree<E> newTree = new BinaryTree<>(); newTree.size = size; newTree.root = newRoot; return newTree; }
|