JAVA二叉树的遍历和序列化

二叉树实体类
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);
        } 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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值