二叉树的节点表示
首先,要完成二叉树的方式,要先定义二叉树的节点,节点定义如下:
class Node {
char value;
Node left;
Node right;
public Node(char value) {
this.value = value;
}
}
二叉树的前序遍历
二叉树的前序遍历:先遍历根节点,再遍历左子树,最后遍历右子树。
1.递归实现二叉树的前序遍历
每次遍历都是根-左子树-右子树的方式。
因此我们使用递归来完成,递归就是有终止条件,并且调用自己。
这里的终止条件就是当遍历的节点为空时,结束。
public void preOrderTraveral (Node root){
if(root == null){
return;
}
System.out.print(root.value + " ");
preOrderTraveral(root.left);
preOrderTraveral(root.right);
}
2.非递归实现二叉树的前序遍历
利用栈实现::从根节点开始,先遍历根节点,并输出,取栈顶,去遍历左孩子,并输出。当左孩子遍历完后,取栈顶,找右孩子。此时循环还没有结束,再遍历它的左孩子,右孩子直至孩子全部遍历结束。
void preOrderTraversal2(Node root) {
Stack<Node> stack = new Stack<>();
Node cur = root;
while(cur != null || !stack.empty()) {
while (cur != null) {
stack.push(cur);
System.out.print(cur.value + " ");
cur = cur.left;
}
cur = stack.pop();
cur = cur.right;
}
}
3.利用集合实现二叉树的先序遍历
public List<Character> preorderTraversal3(Node root) {
List<Character> list = new ArrayList<>();
if(root == null){
return list;
}
//System.out.print(root.value + " ");
list.add(root.value);
List<Character> left = preorderTraversal3(root.left);
list.addAll(left);
List<Character> right = preorderTraversal3(root.right);
list.addAll(right);
return list;
}
二叉树的中序遍历
二叉树的前序遍历:先遍历左子树,再遍历根节点,最后遍历右子树。
1.递归实现
void inOrderTraversal(Node root) {
if(root == null){
return;
}
inOrderTraversal(root.left);
System.out.print(root.value + " ");
inOrderTraversal(root.right);
}
2.非递归实现,利用栈
void inOrderTraversal2(Node root) {
Stack<Node> stack = new Stack<>();
Node cur = root;
while (cur != null || !stack.empty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
System.out.print(stack.peek().value + " ");
cur = stack.pop();
cur = cur.right;
}
}
3.利用集合实现:
public List<Character> inorderTraversal3(Node root) {
List<Character> list = new ArrayList<>();
if(root == null){
return list;
}
List<Character> left = inorderTraversal3(root.left);
list.addAll(left);
list.add(root.value);
List<Character> right = inorderTraversal3(root.right);
list.addAll(right);
return list;
}
二叉树的后序遍历
后序遍历递归定义:先左子树,后右子树,再根节点。
1.递归实现二叉树的后序遍历:
void postOrderTraversal(Node root) {
if(root == null){
return;
}
postOrderTraversal(root.left);
postOrderTraversal(root.right);
System.out.print(root.value + " ");
}
2.非递归实现,利用栈:
后序遍历的难点在于:需要判断上次访问的节点是位于左子树,还是右子树。若是位于左子树,则需跳过根节点,先进入右子树,再回头访问根节点;若是位于右子树,则直接访问根节点。
void postOrderTraversal2(Node root) {
Stack<Node> stack = new Stack<>();
Node cur = root;
Node tmp = null;
while (cur != null || !stack.empty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
cur = stack.peek();
if(cur.right == null || cur.right == tmp) {
System.out.print(stack.pop().value + " ");
tmp = cur;
cur = null;
}else {
cur = cur.right;
}
}
}
3.利用集合实现后序遍历
public List<Character> postorderTraversal3(Node root) {
List<Character> list = new ArrayList<>();
if(root == null){
return list;
}
List<Character> left = postorderTraversal3(root.left);
list.addAll(left);
List<Character> right = postorderTraversal3(root.right);
list.addAll(right);
//System.out.println(root.value + " ");
list.add(root.value);
return list;
}
二叉树的层序遍历
1.利用队列实现
void levelOrderTraversal(Node root){
Queue<Node> queue = new LinkedList<>();
if(root != null){
queue.offer(root);
}
while(!queue.isEmpty()){
Node cur = queue.peek();
if(cur == null){
return;
}
System.out.print(cur.value + " ");
queue.poll();
if(cur.left != null){
queue.offer(cur.left);
}
if(cur.right != null){
queue.offer(cur.right);
}
}
}
2.利用List集合实现
public List<List<Character>> levelOrder(Node root) {
List<List<Character>> ret = new ArrayList<>();
Queue<Node> queue = new LinkedList<>();
if(root != null){
queue.offer(root);
}
//队列的元素,也就是一层数据
while(!queue.isEmpty()){
int count = queue.size();
//存放的是一层数据
List<Character> list = new ArrayList<>();
while(count > 0){
Node cur = queue.poll();
//System.out.print(cur.value + " ");
list.add(cur.value);
if(cur.left != null){
queue.offer(cur.left);
}
if(cur.right != null){
queue.offer(cur.right);
}
count--;
}
ret.add(list);
}
return ret;
}