数据结构基础加强之二叉树

数据结构基础加强之二叉树

二叉树的按层遍历

对于二叉树遍历的方式有中序遍历、先序遍历、后序遍历等。但有时需要打印行信息时需要使用按层遍历。
对于
tree
按层按层遍历需要打印出结果:
1
2 3
4 5 6 7
建立二叉树节点类:

public class TreeNode {

    private int val;
    public TreeNode left = null;
    public TreeNode right = null;

    public int getVal() {
        return val;
    }

    public void setVal(int val) {
        this.val = val;
    }

    public TreeNode(int val){
        this.val = val;
    }
}

对于按层遍历二叉树只需要使用一个队列queue以及2个变量:last指向当前层的最右节点、nlast指向下一层的最右节点。
依次将节点加入队列,每次弹出一个节点打印,并将弹出节点的左右子节点加入队列,并让nlast依次指向当前加入队列的节点。当弹出队列的节点和last指向的节点相同时换行,并让last指向nlast。
代码如下:

import java.util.LinkedList;
import java.util.Queue;

public class PrintTreeByLine {

    public static void main(String[] args){
        //构造二叉树
        TreeNode root = new TreeNode(1);
        TreeNode left = root.left = new TreeNode(2);
        TreeNode right = root.right = new TreeNode(3);
        left.left = new TreeNode(4);
        left.right = new TreeNode(5);
        right.left = new TreeNode(6);
        right.right = new TreeNode(7);
        print(root);
    }

    //使用队列进项二叉树的按层遍历
    public static void print(TreeNode root){
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        TreeNode last = root;  //当前行的最右节点
        TreeNode nlast = null;  //下一行的最右节点
        while (!queue.isEmpty()) {
            TreeNode pollNode = queue.poll();
            System.out.print(pollNode.getVal() + " ");
//          root = pollNode;
            if (pollNode.left != null) {
                queue.add(pollNode.left);
                nlast = pollNode.left;
            }
            if (pollNode.right != null) {
                queue.add(pollNode.right);
                nlast = pollNode.right;
            }
            if (last == pollNode) {
                last = nlast;
                System.out.println();
            }
        }
    }
}

二叉树的序列化与反序列化

对于程序建立的二叉树都是保存在内存中,当机器关闭时将不再存在。因此需要将树永久保存的时候,需要存储于文件中,即树的序列化。使用树时,需要读取文件还原树,即树的反序列化。
序列化:将树以文件的方式存储。
反序列化:读取文件还原二叉树。

二叉树的序列化

对于二叉树的序列化采取先序遍历的方式。用!来分割节点,防止序列化的时候出现歧义。当节点存在是在文件中写入节点值val!,当节点不存在是写入#!。因为是先序遍历。所以可以使用递归的方式执行。
代码如下:

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;

public class TreeToFile {

    public static void main(String[] args) throws Exception {
        //构造二叉树
        TreeNode root = new TreeNode(1);
        TreeNode left = root.left = new TreeNode(2);
        TreeNode right = root.right = new TreeNode(3);
        left.left = new TreeNode(4);
        left.right = new TreeNode(5);
        right.left = new TreeNode(6);
        right.right = new TreeNode(7);
        File file = new File("src/tree.txt");
        BufferedWriter bw = new BufferedWriter(new FileWriter(file));
        saveToFile(root,bw);
        bw.close();
    }

    //二叉树按先序遍历存储到文件
    private static void saveToFile(TreeNode root, BufferedWriter bw) throws Exception {
        if (root == null) {
            bw.write("#!");
        }else{
            bw.write(root.getVal()+"!");
            saveToFile(root.left, bw);
            saveToFile(root.right, bw);
        }
    }
}

二叉树的反序列化

将先序遍历序列化的树还原。因为节点是用!分割,读取文件等到String s,用!来分割s得到String数组,遍历数组将数组一次加入队列。采用先序遍历的方式存储,可以采用递归的方式执行,每一次都弹出队列第一个元素,判断是否为数字,是数字则将元素转为int设置为当前节点的值,用递归的方式依次得出node.left与node.right。
代码如下:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.LinkedList;
import java.util.Queue;

public class FileToTree {

    public static void main(String[] args) throws Exception {

        File file = new File("src/tree.txt");
        BufferedReader br = new BufferedReader(new FileReader(file));
        String s = null;
        StringBuffer sb = new StringBuffer();
        while ((s = br.readLine()) != null) {
            sb.append(s);
        }
        br.close();
        String[] tree = sb.toString().split("!");
        Queue<String> queue = new LinkedList<String>();
        for (String s1 : tree) {
            queue.add(s1);
        }
        TreeNode root = buildTree(queue);
        PrintTreeByLine.print(root);

    }

    // 二叉树的反序列化
    private static TreeNode buildTree(Queue<String> queue) {

        String s = queue.poll();
        TreeNode root = null;
        // 判断读取的字符是不是数字 是返回true 否则返回false
        if (!s.equals("#")) {
            root = new TreeNode(Integer.parseInt(s));
            root.left = buildTree(queue);
            root.right = buildTree(queue);
        }
        return root;
    }

}

具体代码可以参考:https://github.com/Li-JY/algorithm-and-datastructure/tree/master/src/tree

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值