以下面的二叉树为例:
二叉树结点的定义:
package model;
public class TreeNode {
private String value;
private TreeNode lchild;
private TreeNode rchild;
public TreeNode(){}
public TreeNode(String value, TreeNode lchild, TreeNode rchild) {
this.value = value;
this.lchild = lchild;
this.rchild = rchild;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public TreeNode getLchild() {
return lchild;
}
public void setLchild(TreeNode lchild) {
this.lchild = lchild;
}
public TreeNode getRchild() {
return rchild;
}
public void setRchild(TreeNode rchild) {
this.rchild = rchild;
}
}
二叉树的创建:
TreeNode x = new TreeNode("x",null,null);
TreeNode y = new TreeNode("y",null,null);
TreeNode d = new TreeNode("d",x,y);
TreeNode e = new TreeNode("e",null,null);
TreeNode f = new TreeNode("f",null,null);
TreeNode c = new TreeNode("c",e,f);
TreeNode b = new TreeNode("b",d,null);
TreeNode a = new TreeNode("a",b,c);
二叉树的遍历算法:
package service;
import model.TreeNode;
public interface TreeSerivce {
/** 先序遍历(递归)*/
void preOrder(TreeNode treeNode);
/** 中序遍历(递归)*/
void inOrder(TreeNode treeNode);
/** 后序遍历(递归)*/
void postOrder(TreeNode treeNode);
/** 先序遍历(非递归1)*/
void preOrderNo(TreeNode treeNode);
/** 先序遍历(非递归2)*/
void preOrderNo1(TreeNode treeNode);
/** 中序遍历(非递归)*/
void inOrderNo(TreeNode treeNode);
/** 后序遍历(非递归1)*/
void postOrderNo(TreeNode treeNode);
/** 后序遍历(非递归2)*/
void postOrderNo1(TreeNode treeNode);
/** 层次遍历 */
void levelOrder(TreeNode treeNode);
/** 层次遍历 (按行打印)*/
void levelOrder1(TreeNode treeNode);
/**
* 返回当前数的深度
* 说明:
* 1、如果一棵树只有一个结点,它的深度为1。
* 2、如果根结点只有左子树而没有右子树,那么树的深度是其左子树的深度加1;
* 3、如果根结点只有右子树而没有左子树,那么树的深度应该是其右子树的深度加1;
* 4、如果既有右子树又有左子树,那该树的深度就是其左、右子树深度的较大值再加1。
*/
int getTreeDepth(TreeNode treeNode);
/** 序列化树 (树-> 文件)(层次遍历)*/
void serializeTree(TreeNode treeNode);
/** 反序列化树 (文件-> 树)(层次遍历)*/
void reversreSerializeTree(String levelStr);
/** 序列化树 (树-> 文件)(先序遍历:非递归)*/
void serializeTreeByPre(TreeNode treeNode);
/** 序列化树 (树-> 文件)(先序遍历:递归)*/
String serializeTreeByPre1(TreeNode treeNode);
/** 反序列化树 (文件-> 树)(先序遍历)*/
void reverseSerializeTreeByPre(String preStr);
}
package serviceimpl;
import model.TreeNode;
import service.TreeSerivce;
import java.util.*;
public class TreeServiceImpl implements TreeSerivce {
public void preOrder(TreeNode treeNode) {
System.out.println(treeNode.getValue());
if (treeNode.getLchild() != null) {
preOrder(treeNode.getLchild());
}
if (treeNode.getRchild() != null) {
preOrder(treeNode.getRchild());
}
}
public void inOrder(TreeNode treeNode) {
if (treeNode.getLchild() != null) {
inOrder(treeNode.getLchild());
}
System.out.println(treeNode.getValue());
if (treeNode.getRchild() != null) {
inOrder(treeNode.getRchild());
}
}
public void postOrder(TreeNode treeNode) {
if (treeNode.getLchild() != null) {
postOrder(treeNode.getLchild());
}
if (treeNode.getRchild() != null) {
postOrder(treeNode.getRchild());
}
System.out.println(treeNode.getValue());
}
public void preOrderNo(TreeNode treeNode){
Stack<TreeNode> stack = new Stack<TreeNode>();
while(treeNode != null || !stack.isEmpty()) {
while(treeNode != null) {
System.out.println(treeNode.getValue());
stack.push(treeNode);
treeNode = treeNode.getLchild();
}
if(!stack.isEmpty()) {
treeNode = stack.pop();
treeNode = treeNode.getRchild();
}
}
}
public void preOrderNo1(TreeNode treeNode) {
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode currentTreeNode;
if (treeNode != null) {
stack.push(treeNode);
while (!stack.isEmpty()) {
currentTreeNode = stack.pop();
System.out.println(currentTreeNode.getValue());
if (currentTreeNode.getRchild() != null) {
stack.push(currentTreeNode.getRchild());
}
if (currentTreeNode.getLchild() != null) {
stack.push(currentTreeNode.getLchild());
}
}
}
}
public void inOrderNo(TreeNode treeNode) {
Stack<TreeNode> stack = new Stack<TreeNode>();
while(treeNode != null || !stack.isEmpty()) {
while(treeNode != null) {
stack.push(treeNode);
treeNode = treeNode.getLchild();
}
if (!stack.isEmpty()) {
treeNode = stack.pop();
System.out.println(treeNode.getValue());
treeNode = treeNode.getRchild();
}
}
}
public void postOrderNo(TreeNode treeNode) {
int left = 1; // 操作的是左子树
int right = 2; // 操作的是右子树
Stack<TreeNode> stack = new Stack<TreeNode>();
Stack<Integer> flagStack = new Stack<Integer>(); // 辅助栈,用于判断当前操作的是左结点还是右结点,判断根结点是否出栈
while(treeNode != null || !stack.isEmpty()) {
while(treeNode != null) {
stack.push(treeNode);
flagStack.push(left);
treeNode = treeNode.getLchild();
}
while(!stack.isEmpty() && flagStack.peek() == right) {
flagStack.pop();
System.out.println(stack.pop().getValue());
}
if (!stack.isEmpty() && flagStack.peek() == left) {
flagStack.pop();
flagStack.push(right);
treeNode = stack.peek().getRchild();
}
}
}
public void postOrderNo1(TreeNode treeNode) {
Stack<TreeNode> stack1 = new Stack<TreeNode>();
Stack<TreeNode> stack2 = new Stack<TreeNode>();
if (treeNode != null) {
stack1.push(treeNode);
while(!stack1.isEmpty()) {
treeNode = stack1.pop();
stack2.push(treeNode);
if (treeNode.getLchild() != null) stack1.push(treeNode.getLchild());
if (treeNode.getRchild() != null) stack1.push(treeNode.getRchild());
}
}
while(!stack2.isEmpty()) {
System.out.print(stack2.pop().getValue() + ",");
}
}
public void levelOrder(TreeNode treeNode) {
LinkedList<TreeNode> list = new LinkedList<TreeNode>();
list.add(treeNode);
TreeNode currentTreeNode;
while (!list.isEmpty()){
currentTreeNode = list.poll();
System.out.println(currentTreeNode.getValue());
if (currentTreeNode.getLchild() != null) {
list.add(currentTreeNode.getLchild());
}
if (currentTreeNode.getRchild() != null) {
list.add(currentTreeNode.getRchild());
}
}
}
public void levelOrder1(TreeNode treeNode) {
Queue<TreeNode> list = new LinkedList<TreeNode>();
TreeNode last;
TreeNode nlast;
TreeNode currentTreeNode;
if (treeNode != null) {
list.offer(treeNode);
last = treeNode;
nlast = treeNode;
while(!list.isEmpty()) {
currentTreeNode = list.poll();
if (currentTreeNode.getValue().equals(last.getValue())) {
System.out.print(currentTreeNode.getValue());
System.out.println();
} else {
System.out.print(currentTreeNode.getValue() + ",");
}
if (currentTreeNode.getLchild() != null) {
list.offer(currentTreeNode.getLchild());
nlast = currentTreeNode.getLchild();
}
if (currentTreeNode.getRchild() != null) {
list.offer(currentTreeNode.getRchild());
nlast = currentTreeNode.getRchild();
}
if (currentTreeNode.getValue().equals(last.getValue())) {
last = nlast;
}
}
}
}
public int getTreeDepth(TreeNode treeNode) {
if(treeNode.getLchild() == null && treeNode.getRchild() == null) return 1;
int left = 0,right = 0;
if(treeNode.getLchild() != null) left = getTreeDepth(treeNode.getLchild());
if(treeNode.getRchild() != null) right = getTreeDepth(treeNode.getRchild());
return left > right ? left+1 : right+1;
}
public void serializeTree(TreeNode treeNode) {
Queue<TreeNode> queue = new LinkedList<TreeNode>();
if (treeNode != null) {
queue.offer(treeNode);
TreeNode currentTreeNode;
StringBuffer sb = new StringBuffer();
sb.append(treeNode.getValue()).append("!");
while(!queue.isEmpty()) {
currentTreeNode = queue.poll();
if (currentTreeNode.getLchild() != null) {
queue.offer(currentTreeNode.getLchild());
sb.append(currentTreeNode.getLchild().getValue()).append("!");
} else {
sb.append("#!");
}
if (currentTreeNode.getRchild() != null) {
queue.offer(currentTreeNode.getRchild());
sb.append(currentTreeNode.getRchild().getValue()).append("!");
} else {
sb.append("#!");
}
}
System.out.println(sb.toString());
}
}
public void reversreSerializeTree(String levelStr) {
String[] strs = levelStr.split("!");
TreeNode treeNode = null;
TreeNode currentTreeNode;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
int index = 0;
if (!strs[0].equals("#")) {
treeNode = new TreeNode(strs[0]);
queue.offer(treeNode);
index++;
}
while (!queue.isEmpty()) {
currentTreeNode = queue.poll();
currentTreeNode.setLchild(strs[index].equals("#") ? null : new TreeNode(strs[index]));
index++;
currentTreeNode.setRchild(strs[index].equals("#") ? null : new TreeNode(strs[index]));
index++;
if (currentTreeNode.getLchild() != null) {
queue.offer(currentTreeNode.getLchild());
}
if (currentTreeNode.getRchild() != null) {
queue.offer(currentTreeNode.getRchild());
}
}
levelOrder(treeNode);
}
public void serializeTreeByPre(TreeNode treeNode) {
Stack<TreeNode> stack = new Stack<TreeNode>();
StringBuffer sb = new StringBuffer();
while (treeNode != null || !stack.isEmpty()) {
while (treeNode != null) {
sb.append(treeNode.getValue() + "!");
stack.push(treeNode);
treeNode = treeNode.getLchild();
if (treeNode == null) {
sb.append("#!");
}
}
if (!stack.isEmpty()) {
treeNode = stack.pop();
treeNode = treeNode.getRchild();
if (treeNode == null) {
sb.append("#!");
}
}
}
System.out.println(sb.toString());
}
public String serializeTreeByPre1(TreeNode treeNode) {
if (treeNode == null) {
return "#!";
}
String res = treeNode.getValue() + "!";
res += serializeTreeByPre1(treeNode.getLchild());
res += serializeTreeByPre1(treeNode.getRchild());
return res;
}
public void reverseSerializeTreeByPre(String preStr) {
String[] strs = preStr.split("!");
Queue<String> queue = new LinkedList<String>();
for (int i = 0; i < strs.length; i++) {
queue.offer(strs[i]);
}
preOrder(reconPreOrder(queue));
}
private TreeNode reconPreOrder(Queue<String> queue) {
String value = queue.poll();
if (value.equals("#")) return null;
TreeNode head = new TreeNode(value);
head.setLchild(reconPreOrder(queue));
head.setRchild(reconPreOrder(queue));
return head;
}
}
延伸:二叉树层次遍历的时候按行打印
思路:
1.定义两个节点last和nlast;
2.last代表当前行最右边的节点,nlast代表下一行最右边的节点(nlast一直跟踪记录队列中最新加入的结点,最新加入的结点一定是发现的下一行的最右结点。所以当前行打完时,nlast一定是下一行的最右结点。);
3.如果输出结点是last结点,说明该换行了,last=nlast。
public void levelOrder(TreeNode treeNode) {
Queue<TreeNode> list = new LinkedList<TreeNode>();
TreeNode last;
TreeNode nlast;
TreeNode currentTreeNode;
if (treeNode != null) {
list.offer(treeNode);
last = treeNode;
nlast = treeNode;
while(!list.isEmpty()) {
currentTreeNode = list.poll();
if (currentTreeNode.getValue().equals(last.getValue())) {
System.out.print(currentTreeNode.getValue());
System.out.println();
} else {
System.out.print(currentTreeNode.getValue() + ",");
}
if (currentTreeNode.getLchild() != null) {
list.offer(currentTreeNode.getLchild());
nlast = currentTreeNode.getLchild();
}
if (currentTreeNode.getRchild() != null) {
list.offer(currentTreeNode.getRchild());
nlast = currentTreeNode.getRchild();
}
if (currentTreeNode.getValue().equals(last.getValue())) {
last = nlast;
}
}
}
}
运行结果如下:
a
b,c
d,e,f
x,y
延伸:输入一棵二叉树,判断该二叉树是否是平衡二叉树。
Java源码实现:
public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
if (root == null) return true;
if (root.left == null && root.right == null) return true;
int left = 0;
int right = 0;
if (root.left != null) left = TreeDepth(root.left);
if (root.right != null) right = TreeDepth(root.right);
if (left - right == -1 || left - right == 0 || left - right == 1) return true;
return false;
}
private int TreeDepth(TreeNode root) {
if (root == null) return 0;
if (root.left == null && root.right == null) return 1;
int left = 0;
int right = 0;
if (root.left != null) left = TreeDepth(root.left);
if (root.right != null) right = TreeDepth(root.right);
return left >= right ? left + 1 :right+1;
}
}