JAVA二叉树的遍历和序列化
2017-04-09 13:03
148 查看
二叉树实体类
public class TreeNode { private int val = 0; private TreeNode left = null; private TreeNode right = null; public TreeNode(int val) { this.val = val; } public int getVal() { return val; } public void setVal(int val) { this.val = val; } public TreeNode getLeft() { return left; } public void setLeft(TreeNode left) { this.left = left; } public TreeNode getRight() { return right; } public void setRight(TreeNode right) { this.right = right; } }
递归遍历
/** * 前序遍历(根左右) */ public void DLR(TreeNode head) { if (head == null) return; System.out.print(head.getVal()); if (head.getLeft() != null) DLR(head.getLeft()); if (head.getRight() != null) DLR(head.getRight()); } /** * 中序遍历(左根右) */ public void LDR(TreeNode head) { if (head == null) return; if (head.getLeft() != null) LDR(head.getLeft()); System.out.print(head.getVal()); if (head.getRight() != null) LDR(head.getRight()); } /** * 后序遍历(左右根) */ public void LRD(TreeNode head) { if (head == null) return; if (head.getLeft() != null) LRD(head.getLeft()); if (head.getRight() != null) LRD(head.getRight()); System.out.print(head.getVal()); }
递归遍历没什么好说的,比较简单,下面介绍非递归遍历
非递归遍历
/** * 前序遍历(非递归) */ public void dlr_by_stack(TreeNode head) { Stack<TreeNode> stack = new Stack<TreeNode>(); stack.push(head); while (!stack.isEmpty()) { TreeNode node = stack.pop(); System.out.print(node.getVal()); if (node.getRight() != null) { stack.push(node.getRight()); } if (node.getLeft() != null) { stack.push(node.getLeft()); } } }
1:准备一个栈,头节点先入栈。
2:弹出栈顶节点,打印节点的值,然后当前结点的右孩子和左孩子依次入栈
3:重复步骤2直到栈为空
由于栈的结构是先进后出,所以每次先弹出的都是左孩子。弹出左孩子后又将该节点的右孩子和左孩子依次入栈。这样就实现了根左右的遍历顺序。
/** * 中序遍历(非递归) */ public void ldr_by_stack(TreeNode head) { Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode cur = head; while (!stack.isEmpty() || cur != null) { if (cur != null) { stack.push(cur);//左孩子依次入栈 cur = cur.getLeft(); } else {//左孩子为空时,打印节点值 cur = stack.pop(); System.out.print(cur.getVal()); cur = cur.getRight(); } } }
1:同样先准备一个栈,令头节点先入栈
2:将整颗树的左孩子依次入栈,当没有左孩子时,右孩子入栈
3:重复步骤2直到栈为空或者当前结点为空
/** * 后序遍历(非递归) */ public void lrd_by_stack(TreeNode head) { Stack<TreeNode> s1 = new Stack<>(); Stack<TreeNode> s2 = new Stack<>(); s1.push(head); while (!s1.isEmpty()) { TreeNode node = s1.pop(); s2.push(node); if (node.getLeft() != null) s1.push(node.getLeft()); if (node.getRight() != null) s1.push(node.getRight()); } while (!s2.isEmpty()) { System.out.print(s2.pop().getVal()); } }
1:准备两个栈s1和s2,头节点进入s1
2:弹出s1的栈顶节点,计为node,node入栈s2,node的左右节点依次入s1
3:重复步骤2直到s2为空,这是s2的出栈顺序就是后序遍历的结果
层序遍历
/** * 层序遍历 */ public void printTree(TreeNode head) { LinkedList<TreeNode> queue = new LinkedList<TreeNode>(); TreeNode node; TreeNode last = head; TreeNode nlast = last; queue.offer(head); while (!queue.isEmpty()) { node = queue.poll(); System.out.print(node.getVal()); if (node.getLeft() != null) { queue.offer(node.getLeft()); nlast = node.getLeft(); } if (node.getRight() != null) { queue.offer(node.getRight()); nlast = node.getRight(); } if (node == last) { last = nlast; System.out.println(); } } }
序列化
将一颗二叉树序列化成字符串,空节点用#!表示/** * 前序序列化 */ private void serialize_dlr(TreeNode head, StringBuilder builder) { builder.append(head.getVal()); builder.append("!"); if (head.getLeft() != null) { serialize_dlr(head.getLeft(), builder); } else { builder.append("#!"); } if (head.getRight() != null) { serialize_dlr(head.getRight(), builder); } else { builder.append("#!"); } }
/** * 中序序列化 */ private void serialize_ldr(TreeNode head, StringBuilder builder) { if (head.getLeft() != null) { serialize_ldr(head.getLeft(), builder); e620 } else { builder.append("#!"); } builder.append(head.getVal()); builder.append("!"); if (head.getRight() != null) { serialize_ldr(head.getRight(), builder); } else { builder.append("#!"); } }
/** * 后序序列化 */ private void serialize_lrd(TreeNode head, StringBuilder builder) { if (head.getLeft() != null) { serialize_lrd(head.getLeft(), builder); } else { builder.append("#!"); } if (head.getRight() != null) { serialize_lrd(head.getRight(), builder); } else { builder.append("#!"); } builder.append(head.getVal()); builder.append("!"); }
完整代码
/** * Created by Clanner on 2017/10/25. * 二叉树工具类 */ public class TreeUtil { public static final int DLR = 1; public static final int LDR = 2; public static final int LRD = 3; private TreeUtil() { } public static final TreeUtil getInstance() { return Holder.instance; } private static final class Holder { private static final TreeUtil instance = new TreeUtil(); } /** * 层序遍历 */ public void printTree(TreeNode head) { LinkedList<TreeNode> queue = new LinkedList<TreeNode>(); TreeNode node; TreeNode last = head; TreeNode nlast = last; queue.offer(head); while (!queue.isEmpty()) { node = queue.poll(); System.out.print(node.getVal()); if (node.getLeft() != null) { queue.offer(node.getLeft()); nlast = node.getLeft(); } if (node.getRight() != null) { queue.offer(node.getRight()); nlast = node.getRight(); } if (node == last) { last = nlast; System.out.println(); } } } /** * 前序反序列化 * * @param head * @param values * @param index */ private void deserialize_dlr(TreeNode head, String[] values, int index) { } /** * 前序序列化 */ private void serialize_dlr(TreeNode head, StringBuilder builder) { builder.append(head.getVal()); builder.append("!"); if (head.getLeft() != null) { serialize_dlr(head.getLeft(), builder); } else { builder.append("#!"); } if (head.getRight() != null) { serialize_dlr(head.getRight(), builder); } else { builder.append("#!"); } } /** * 中序序列化 */ private void serialize_ldr(TreeNode head, StringBuilder builder) { if (head.getLeft() != null) { serialize_ldr(head.getLeft(), builder); } else { builder.append("#!"); } builder.append(head.getVal()); builder.append("!"); if (head.getRight() != null) { serialize_ldr(head.getRight(), builder); } else { builder.append("#!"); } } /** * 后序序列化 */ private void serialize_lrd(TreeNode head, StringBuilder builder) { if (head.getLeft() != null) { serialize_lrd(head.getLeft(), builder); } else { builder.append("#!"); } if (head.getRight() != null) { serialize_lrd(head.getRight(), builder); } else { builder.append("#!"); } builder.append(head.getVal()); builder.append("!"); } /** * 前序遍历(根左右) */ public void DLR(TreeNode head) { if (head == null) return; System.out.print(head.getVal()); if (head.getLeft() != null) DLR(head.getLeft()); if (head.getRight() != null) DLR(head.getRight()); } /** * 前序遍历(非递归) */ public void dlr_by_stack(TreeNode head) { Stack<TreeNode> stack = new Stack<TreeNode>(); stack.push(head); while (!stack.isEmpty()) { TreeNode node = stack.pop(); System.out.print(node.getVal()); if (node.getRight() != null) { stack.push(node.getRight()); } if (node.getLeft() != null) { stack.push(node.getLeft()); } } } /** * 中序遍历(左根右) */ public void LDR(TreeNode head) { if (head == null) return; if (head.getLeft() != null) LDR(head.getLeft()); System.out.print(head.getVal()); if (head.getRight() != null) LDR(head.getRight()); } /** * 中序遍历(非递归) */ public void ldr_by_stack(TreeNode head) { Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode cur = head; while (!stack.isEmpty() || cur != null) { if (cur != null) { stack.push(cur);//左孩子依次入栈 cur = cur.getLeft(); } else {//左孩子为空时,打印节点值 cur = stack.pop(); System.out.print(cur.getVal()); cur = cur.getRight(); } } } /** * 后序遍历(左右根) */ public void LRD(TreeNode head) { if (head == null) return; if (head.getLeft() != null) LRD(head.getLeft()); if (head.getRight() != null) LRD(head.getRight()); System.out.print(head.getVal()); } /** * 后序遍历(非递归) */ public void lrd_by_stack(TreeNode head) { Stack<TreeNode> s1 = new Stack<>(); Stack<TreeNode> s2 = new Stack<>(); s1.push(head); while (!s1.isEmpty()) { TreeNode node = s1.pop(); s2.push(node); if (node.getLeft() != null) s1.push(node.getLeft()); if (node.getRight() != null) s1.push(node.getRight()); } while (!s2.isEmpty()) { System.out.print(s2.pop().getVal()); } } /** * 判断两个树是否相同 */ public boolean isSameTree(TreeNode p, TreeNode q) { if (p == null && q == null) return true; if (p == null || q == null) return false; if (p.getVal() != q.getVal()) return false; return isSameTree(p.getLeft(), q.getLeft()) && isSameTree(p.getRight(), q.getRight()); } /** * 序列化 * * @param head 树的根节点 * @param type 序列化方式 */ public String serialize(TreeNode head, int type) { StringBuilder builder = new StringBuilder(); builder.append("type_id:"); builder.append(type); builder.append(":"); switch (type) { case DLR: serialize_dlr(head, builder); return builder.toString(); case LDR: serialize_ldr(head, builder); return builder.toString(); case LRD: serialize_lrd(head, builder); return builder.toString(); default: return "序列化类型错误"; } } /** * 层序构造,构建完全二叉树 * * @param values */ public TreeNode createTree(int[] values) { TreeNode head = new TreeNode(values[0]); LinkedList<TreeNode> queue = new LinkedList<TreeNode>(); TreeNode node; TreeNode last = head; TreeNode nlast = last; queue.offer(head); int i = 1; while (i + 1 < values.length) { node = queue.poll(); if (node.getLeft() == null) { node.setLeft(new TreeNode(values[i++])); queue.offer(node.getLeft()); nlast = node.getLeft(); } if (node.getRight() == null) { node.setRight(new TreeNode(values[i++])); queue.offer(node.getRight()); nlast = node.getRight(); } if (node == last) { last = nlast; } } return head; } }
相关文章推荐
- JAVA语言实现二叉树的层次遍历的非递归算法及递归算法。
- 根据前序遍历和中序遍历重建二叉树的Java实现
- Java遍历二叉树各种方式(code)
- JAVA实现二叉树及递归遍历二叉树
- 实现二叉树的层序遍历,说说Java中的队列结构(实现一个Java的队列)
- 我用Java实现的二叉树的遍历(递归和非递归)
- java建立二叉树,递归/非递归先序遍历,递归/非递归中序遍历,层次遍历
- Java实现二叉树的多种遍历
- JAVA语言实现二叉树的层次遍历的非递归算法及递归算法
- java实现二叉树的先序、中序、后序遍历
- 二叉树及其遍历方式(java)
- java二叉树的增、删、查、前序遍历、中序遍历和后序遍历 算法 源代码
- Java写的一个二叉树三种遍历递归算法(仅用作理解三种遍历)
- 二叉树后序遍历的循环实现(JAVA)
- Java 创建二叉树并遍历
- java语言实现的二叉树的各种操作(包括递归与非递归遍历二叉树,求二叉树的高度,节点总数,叶子节点等)
- java语言实现二叉树的前序、中序与后序遍历(递归与非递归)
- java实现二叉树的建立及遍历方法
- 并发遍历二叉树 Java 实现
- 二叉树的遍历(Java,前序、中序、后序、递归and非递归)