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

来源:互联网 发布:喋血街头java 编辑:程序博客网 时间:2024/05/23 01:13

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

二叉树的按层遍历

对于二叉树遍历的方式有中序遍历、先序遍历、后序遍历等。但有时需要打印行信息时需要使用按层遍历。
对于
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

原创粉丝点击