博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
二叉树
阅读量:4099 次
发布时间:2019-05-25

本文共 4993 字,大约阅读时间需要 16 分钟。

 首先定义二叉树结构,接着创建二叉树,实现二叉树的递归先、中、后序遍历

package treeLearn;

import java.util.LinkedList;

import java.util.List;

import javax.xml.soap.Node;

public class CreateTree {

    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        CreateTree t = new CreateTree();
        int[] arr = {0,1,2,3,4,5,6,7};
        List<Tree> tree = new LinkedList<Tree>();
        t.createTree(arr,tree);
        System.out.print("先序遍历:");
        t.preOrderTraversal(tree.get(0));
        System.out.println();
        System.out.print("中序遍历:");
        t.inOrderTraversal(tree.get(0));
        System.out.println();
        System.out.print("后序遍历:");
        t.postOrderTraversal(tree.get(0));
    }
    public void createTree(int[] arr,List<Tree> tree) {
        //将数组元素变为树节点元素
        for(int i=0;i<arr.length;i++) {
            Tree t = new Tree(arr[i]);
            tree.add(t);
        }
        //给所有父节点设定子节点
        for(int i=0;i<arr.length/2-1;i++) {
            //相当于为编号i的节点确定子节点
            //左子节点编号为2*n,右子节点为2*n+1,但是因为编号从0开始,故都在加一
            tree.get(i).setLchild(tree.get(i*2+1));
            tree.get(i).setRchild(tree.get(2*i+2));
            //这里父节点有1(2,3),2(4,5),3(6,7),4(8,9) 
            //但是最后一个父节点有可能没有右子节点 需要单独处理
        }
        //单独处理最后一个父节点,因为他可能没有右节点
        int index = tree.size()/2-1;
        tree.get(index).setLchild(tree.get(index*2+1));//先设置左子节点
        if(tree.size()%2==1) {//如果有奇数个节点,最后一个父节点才有右节点
            tree.get(index).setRchild(tree.get(index*2+2));
        }
    }
    /*
     * 遍历当前节点的值
     */
    public void checkCurrentNode(Tree tree) {
        System.out.print(tree.getData()+" ");
    }
    /**
     * 先序遍历二叉树
     * @param tree
     */
    public void preOrderTraversal(Tree tree) {
        if(tree==null) {//很重要,必须有这个条件,当遇到叶子节点用来停止向下遍历
            return;
        }
        checkCurrentNode(tree);
        preOrderTraversal(tree.getLchild());
        preOrderTraversal(tree.getRchild());
    }
    public void inOrderTraversal(Tree tree) {
        if(tree==null) {
            return;
        }
        inOrderTraversal(tree.getLchild());
        checkCurrentNode(tree);
        inOrderTraversal(tree.getRchild());
    }
    /**
     * 后序遍历二叉树
     * @param root 根节点
     */
    public void postOrderTraversal(Tree tree){
        if (tree == null)  //很重要,必须加上
            return;  
        postOrderTraversal(tree.getLchild());
        postOrderTraversal(tree.getRchild());
        checkCurrentNode(tree);
    }
}
class Tree{
    private Tree lchild;//左孩子
    private Tree rchild;//右孩子
    private int data;//数据域
    
    public Tree(int data) {
        this.data = data;
        this.lchild = null;
        this.rchild = null;
    }
    
    public Tree getLchild() {
        return lchild;
    }

    public void setLchild(Tree lchild) {

        this.lchild = lchild;
    }

    public Tree getRchild() {

        return rchild;
    }

    public void setRchild(Tree rchild) {

        this.rchild = rchild;
    }

    public int getData() {

        return data;
    }

    public void setData(int data) {

        this.data = data;
    }
}
 

 

接下来是二叉树的非递归先、中、后序遍历以及DFS和BFS的实现 

package treeLearn;

import java.util.ArrayDeque;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

public class TreeTraversal {

    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        TreeTraversal t = new TreeTraversal();
        CreateTree tt = new CreateTree();
        int[] arr = {0,1,2,3,4,5,6,7};
        List<Tree> tree = new LinkedList<Tree>();
        tt.createTree(arr,tree);
        System.out.print("DFS:");
        t.dfs(tree.get(0));
        System.out.println();
        System.out.print("BFS:");
        t.bfs(tree.get(0));
    }
    /*
     * 遍历当前节点的值
     */
    public void checkCurrentNode(Tree tree) {
        System.out.print(tree.getData()+" ");
    }
    /**
     * 非递归先序遍历二叉树
     * @param tree
     */
    public void preOrderTraversal(Tree tree) {
        Stack<Tree> stack = new Stack<Tree>();
        Tree t = tree;
        while(t!=null||!stack.isEmpty()) {
            while(t!=null) {
                checkCurrentNode(t);//读取根节点以及左子树节点
                stack.push(t);//并将读取到的左子树节点入栈
                t = t.getLchild();//指针下移,一直指向左子树节点,直至节点不存在
            }
            if(!stack.isEmpty()) {
                t = stack.pop();//将栈内元素弹出
                t = t.getRchild();//指针指向栈内节点的右子树节点,
                //当不为空时,会再次进入while循环输出并入栈,再次读取该子树的左子树节点
            }
        }
    }
    public void inOrderTraversal(Tree tree) {
        Stack<Tree> stack = new Stack<Tree>();
        Tree t = tree;
        while(t!=null&&!stack.isEmpty()) {
            while(t!=null) {
                stack.push(t);
                t = t.getLchild();
            }
            if(!stack.isEmpty()) {
                t = stack.pop();
                checkCurrentNode(t);
                t = t.getRchild();
            }
        }
    }
    public void postOrderTraversal(Tree tree) {
        Stack<Tree> stack = new Stack<Tree>();
        Tree t = tree,prev = tree;
        while(t!=null&&!stack.isEmpty()) {
            while(t!=null) {
                stack.push(t);
                t = t.getLchild();
            }
            if(!stack.isEmpty()) {
                Tree temp = stack.peek().getRchild();//指向当前栈顶一节点的右子树节点
                if(temp==null||temp==prev) {//若当前栈顶节点的右子树节点为null
                    //保证当前栈顶元素无兄弟节点
                    t = stack.pop();
                    checkCurrentNode(t);//弹出栈顶元素并输出
                    prev = t;//记录已经输出的元素
                    t = null;//t为空时才能进入栈操作
                }else {
                    //如果当前节点存在兄弟节点则需进入while循环再次入栈操作
                    t = temp;
                }
            }
        }
    }
    //通过队列实现
    public void bfs(Tree tree) {
        if(tree==null) {
            return;
        }
        LinkedList<Tree> queue = new LinkedList<Tree>();
        queue.offer(tree);//首先将根节点存入队列
        //当队列中有值时,每次取队首的节点打印,打印之后判断是否有子节点
        //若有,将子节点加入队列
        while(queue.size()>0) {
            Tree t = queue.peek();
            queue.poll();//取出队首元素并打印
            System.out.print(t.getData()+" ");
            if(t.getLchild()!=null) {//如果有左子节点,则将其加入队列
                queue.offer(t.getLchild());
            }
            if(t.getRchild()!=null) {//如果有右子节点,则将其存入队列
                queue.offer(t.getRchild());
            }
        }
    }
    //通过栈来实现
    public void dfs(Tree tree) {
        if(tree==null) {
            return;
        }
        ArrayDeque<Tree> stack = new ArrayDeque<Tree>();
        stack.push(tree);
        while(!stack.isEmpty()) {
            Tree t = stack.pop();
            if(t.getRchild()!=null) {
                stack.push(t.getRchild());
            }
            System.out.print(t.getData()+" ");
            if(t.getLchild()!=null) {
                stack.push(t.getLchild());
            }
        }
    }
}
 

转载地址:http://vreii.baihongyu.com/

你可能感兴趣的文章
mySQL--深入理解事务隔离级别
查看>>
分布式之redis复习精讲
查看>>
数据结构与算法7-栈
查看>>
Java并发编程 | 一不小心就死锁了,怎么办?
查看>>
(python版)《剑指Offer》JZ01:二维数组中的查找
查看>>
(python版)《剑指Offer》JZ06:旋转数组的最小数字
查看>>
(python版)《剑指Offer》JZ13:调整数组顺序使奇数位于偶数前面
查看>>
(python版)《剑指Offer》JZ28:数组中出现次数超过一半的数字
查看>>
(python版)《剑指Offer》JZ30:连续子数组的最大和
查看>>
(python版)《剑指Offer》JZ32:把数组排成最小的数
查看>>
(python版)《剑指Offer》JZ02:替换空格
查看>>
JSP/Servlet——MVC设计模式
查看>>
使用JSTL
查看>>
Java 8新特性:Stream API
查看>>
管理用户状态——Cookie与Session
查看>>
最受欢迎的前端框架Bootstrap 入门
查看>>
JavaScript编程简介:DOM、AJAX与Chrome调试器
查看>>
通过Maven管理项目依赖
查看>>
通过Spring Boot三分钟创建Spring Web项目
查看>>
Spring的IoC(依赖注入)原理
查看>>