二叉树的深度优先遍历和广度优先遍历的实现

二叉树:

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分。
二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个结点。(百度百科)

二叉树的深度优先遍历:

二叉树的深度优先遍历有三种方式:前序遍历、中序遍历、后序遍历。

二叉树

上图所示为一颗二叉树,它还是一颗AVL树,不知道AVL的可以查看(AVL):

以上图为例,该树的前序遍历为:4、2、1、3、6、5、7;
中序遍历为:1、2、3、4、5、6、7;
后序遍历为:1、3、2、5、7、6、4;

代码实现:

  • 首先创建一个二叉树对象,root为树的根节点:
class Tree<T> {
    T root;
    Tree<T> left;
    Tree<T> right;

    public Tree(T root) {
        this.root = root;
    }
}
  • 遍历的递归实现,通过递归算法可以实现二叉树的遍历:
	//前序遍历
    public static void frontTree(Tree tree) {
        if (null == tree) {
            return;
        }
        System.out.print(tree.root+" ");
        frontTree(tree.left);
        frontTree(tree.right);
    }

    //中序遍历
    public static void middleTree(Tree tree) {
        if (null == tree) {
            return;
        }
        middleTree(tree.left);
        System.out.print(tree.root+" ");
        middleTree(tree.right);
    }

    //后序遍历
    public static void behindTree(Tree tree) {
        if (null == tree) {
            return;
        }
        behindTree(tree.left);
        behindTree(tree.right);
        System.out.print(tree.root+" ");
    }
  • 遍历的非递归实现,以下主要采用栈这种数据结构来实现:
	//前序遍历
    public static void frontNoTree(Tree tree) {
        if (tree == null) {
            return;
        }
        Stack<Tree> stack = new Stack<Tree>();
        stack.push(tree);
        while (!stack.empty()) {
            tree = stack.pop();
            System.out.print(tree.root + " ");
            if (tree.right != null) {
                stack.push(tree.right);
            }
            if (tree.left != null) {
                stack.push(tree.left);
            }
        }
    }

    //中序遍历
    public static void middleNoTree(Tree tree) {
        if (tree == null) {
            return;
        }
        Stack<Tree> stack = new Stack<>();
        while (!stack.empty() || tree != null) {
            while (tree != null) {
                stack.push(tree);
                tree = tree.left;
            }
            tree = stack.pop();
            System.out.print(tree.root + " ");
            tree = tree.right;
        }
    }

    //后序遍历
    public static void behindNoTree(Tree tree) {
        if (null == tree) {
            return;
        }
        Stack<Tree> stack = new Stack<Tree>();
        Tree p = tree;
        while (!stack.empty() || tree != null){
            while (tree != null){
                stack.push(tree);
                tree = tree.left;
            }
            tree = stack.peek().right;
            if (tree == null || tree == p){
                tree = stack.pop();
                System.out.print(tree.root + " ");
                p = tree;
                tree = null;
            }
        }
    }

二叉树的广度优先遍历:

在这里插入图片描述
根据上图中的二叉树进行广度优先遍历:4、2、6、1、3、5、7;
可以看出广度优先遍历实际上就是层级遍历,从第一层遍历到第三层。

代码实现:

  • 递归实现,在递归实现中需要都得到树的高度,然后根据高度一层层访问:
	//首先要知道树的高度
    public static Integer lengthTree(Tree tree){
        if (tree == null){
            return 0;
        }
        return Math.max(lengthTree(tree.left),lengthTree(tree.right))+1;
    }

    //设置访问一层的方法
    public static void yiceng(Tree tree, Integer length) {
        if (tree == null || length < 1){
            return;
        }
        if (length == 1){
            System.out.print(tree.root + " ");
            return;
        }
        yiceng(tree.left, length - 1);
        yiceng(tree.right, length - 1);
    }

    //递归层次遍历
    public static void guangduTree(Tree tree){
        if (tree == null){
            return;
        }
        Integer treeLength = lengthTree(tree);
        //i=1表示从第一行开始,直到第三层
        for (int i = 1; i < treeLength + 1; i++) {
            yiceng(tree, i);
        }
    }
  • 非递归实现,主要是采用队列的形式去实现:
	//非递归层次遍历:采用队列实现
    public static void guangduNoTree(Tree tree){
        if (tree == null){
            return;
        }
        Queue<Tree> queue = new LinkedList<Tree>();
        queue.offer(tree);//等同于add方法,不同在于add超出队列界限会抛出异常,offer会返回false
        while (!queue.isEmpty()){
            Integer size = queue.size();
            for (int i = 0; i < size; i++) {
                tree = queue.poll();//检索队列的head元素,然后删除
                if (tree.left != null){
                    queue.offer(tree.left);
                }
                if (tree.right != null){
                    queue.offer(tree.right);
                }
                System.out.print(tree.root + " ");
            }
        }
    }

测试一下上面的方法:

 public static void main(String[] args) {
        //初始化一颗树
        Tree a = new Tree(1);
        Tree b = new Tree(2);
        Tree c = new Tree(3);
        Tree d = new Tree(4);
        Tree e = new Tree(5);
        Tree f = new Tree(6);
        Tree g = new Tree(7);

        d.left = b;
        d.right = f;
        b.left = a;
        b.right = c;
        f.left = e;
        f.right = g;

        System.out.print("递归前序:");
        frontTree(d);
        System.out.println();
        System.out.print("递归中序:");
        middleTree(d);
        System.out.println();
        System.out.print("递归后序:");
        behindTree(d);
        System.out.println();
        System.out.print("非递归前序:");
        frontNoTree(d);
        System.out.println();
        System.out.print("非递归中序:");
        middleNoTree(d);
        System.out.println();
        System.out.print("非递归后序:");
        behindNoTree(d);
        System.out.println();
        System.out.print("递归层次遍历(广度优先遍历):");
        guangduTree(d);
        System.out.println();
        System.out.print("非递归层次遍历(广度优先遍历):");
        guangduNoTree(d);
    }

运行结果:

递归前序:4 2 1 3 6 5 7 
递归中序:1 2 3 4 5 6 7 
递归后序:1 3 2 5 7 6 4 
非递归前序:4 2 1 3 6 5 7 
非递归中序:1 2 3 4 5 6 7 
非递归后序:1 3 2 5 7 6 4 
递归层次遍历(广度优先遍历):4 2 6 1 3 5 7 
非递归层次遍历(广度优先遍历):4 2 6 1 3 5 7 

写博客是为了记录自己容易忘记的东西,也是对自己学习的总结,大家一起加油!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值