详解二叉树的实现

package com.datastructure;

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

/**
 * 二叉树(BinaryTree):
 *        二叉树的基本单元是节点;
 *        每个节点包含值、左子节点引用和右子节点引用;
 *
 *        在二叉树中,除叶节点外,其他所有节点都包含子节点和非空子树
 *
 *
 * 二叉树常见术语:
 *   1.根节点(root node):位于二叉树顶层的节点,没有父节点
 *   2.叶节点(leaf node):没有子节点的节点,其两个指针均指向None.
 *   3.边(edge):连接两个节点的线段,即节点引用(指针)
 *   4.节点所在的层(level):从顶至底递增,跟节点所在层为1
 *   5.节点的度(degree):节点的字节点的数量.在二叉树中,度的取值范围是0,1,2
 *   6.二叉树的高度(height):从根节点到最远叶节点所经过的边的数量
 *   7.节点的深度(depth):从根节点到该节点所经过的边的数量
 *   8.节点的高度(height):从距离该节点最远的叶节点到该节点所经过的边的数量
 *
 * 常见二叉树类型:
 * 1.完美二叉树/满二叉树(perferct binary tree):所有层的节点都被完美填满;在完美二叉树中,叶节点的度为0,其余所有节点的度为2;
 * 2.完全二叉树(complate binary tree):只有最底层的节点未被填满,且最底层节点尽量靠左填充
 * 3.完满二叉树(full binary tree):除了叶节点之外,其余所有节点都有两个子节点; 所有节点的度都为0或2
 * 4.平衡二叉树(balanced binary tree):任意节点的左子树和右子树的高度之差的绝对值不超过1
 *
 * 二叉树的遍历方式:层序遍历、前序遍历、中序遍历、后序遍历
 */
public class BinaryTree {
    public static void main(String[] args) {
        //1.初始化二叉树:首先初始化节点,然后构建引用(指针)
        //初始化节点
        TreeNode n1=new TreeNode(1);
        TreeNode n2=new TreeNode(2);
        TreeNode n3=new TreeNode(3);
        TreeNode n4=new TreeNode(4);
        TreeNode n5=new TreeNode(5);
        //构建节点之间的引用(指针)
        n1.left=n2;
        n1.right=n3;
        n2.left=n4;
        n2.right=n5;

        //2.插入与删除节点:在二叉树中插入与删除节点可以通过修改指针来实现
        TreeNode p=new TreeNode(0);
        //在n1->n2中间插入节点p
        n1.left=p;
        p.left=n2;
        //删除节点p
        n1.left=n2;


    }
}
class TreeNode{
     int val;//节点值
     TreeNode left;//左子节点引用
     TreeNode right;//右子节点引用

    public TreeNode(int x){
        this.val=x;
    }
}
/**
 * 1.层序遍历(level-order traversal):
 *               从顶部到底部逐层遍历二叉树,并在每一层按照从左到右的顺序访问节点;
 *               层序遍历本质上属于广度优先遍历(Breadth-first-traversal),也称广度优先搜索(breadth-first search BFS),
 *                体现的是一圈一圈向外扩展的逐层遍历的方式;
 *                广度优先遍历实现通常借助队列来实现。
 * 2.前序、中序、后序遍历都属于深度优先遍历(depth-frist-traversal),也称深度优先搜索(depth-frist-search DFS),体现了一种先走到尽头,再回溯继续的遍历方式;
 *              深度优先遍历就像绕着整颗二叉数的外围走一圈.每个节点都会遇到三个位置,分别对应前序遍历、中序遍历、后序遍历
 *              深度优先搜索通常基于递归实现
 */
class BinaryTreeBFS{
    /**
     *1. 层序遍历
     * 时间复杂度为O(n)
     */
    public List<Integer> levelOrder(TreeNode root){
        //初始化队列,加入根节点
        Queue<TreeNode> queue=new LinkedList<>();
        queue.add(root);

        //初始化一个列表,用于保存遍历序列
        List<Integer> list=new ArrayList<>();
        while (!queue.isEmpty()){
            TreeNode node=queue.poll();//队列出队
            list.add(node.val);//保存节点值
            if(node.left!=node){
                queue.offer(node.left);//左子节点入队
            }
            if(node.right!=node){
                queue.offer(node.right);//有子节点入队
            }
        }
        return  list;
    }
/**
 * 2.前序遍历
 * 访问方式:根->左->右
 */
public void preOrder(TreeNode root) {
    //初始化一个列表,用于保存遍历序列
    List<Integer> list = new ArrayList<>();
    if (root == null)
        return;
    list.add(root.val);
    preOrder(root.left);
    preOrder(root.right);
}
/**
 * 3.中序遍历
 * 访问方式:左->根->右
 */
public void inOrder(TreeNode root){
    List<Integer> list = new ArrayList<>();

    if(root==null)
        return;
    inOrder(root.left);
    list.add(root.val);
    inOrder(root.right);

}

/**
 * 4.后序遍历
 * 访问方式:左->右->根
 */
public void postOrder(TreeNode root){
    List<Integer> list = new ArrayList<>();

    if(root==null)
        return;
    postOrder(root.left);
    postOrder(root.right);
    list.add(root.val);
}
}
/**
 * 二叉树类:数组表示
 *
 * 左子节点的索引 2i+1;
 * 右子节点的索引 2i+2;
 *
 * 二叉树的数组表示优缺点
 *  优点:
 *      数组存储在连续的内存空间中,对缓存友好,访问与遍历速度较快。
 *      不需要存储指针,比较节省空间。
 *      允许随机访问节点。
 *
 *  缺点:
 *      数组存储需要连续内存空间,因此不适合存储数据量过大的树。
 *      增删节点需要通过数组插入与删除操作实现,效率较低。
 *      当二叉树中存在大量 None 时,数组中包含的节点数据比重较低,空间利用率较低
 */
class ArrayBinaryTree{
    private List<Integer> tree;

    /**
     * 构造方法
     */
    public ArrayBinaryTree(List<Integer> arr){
        tree=new ArrayList<>(arr);
    }
    /**
     * 列表容量
     */
    public int size(){
        return tree.size();
    }
    /**
     * 获取索引为i节点的值
     */
    public Integer val(int i){
        //若索引越界,则返回null,代表空位
        if(i<0|| i>=size())
            return null;
        return tree.get(i);
    }
    /**
     * 获取索引为i节点的左子节点的索引
     */
    public Integer left(Integer i){
    return 2*i+1;
    }

    /**
     * 获取索引为i节点的右子节点的索引
     */
    public Integer right(int i){
        return 2*i+2;
    }
    /**
     * 获取索引为i节点的父节点的索引
     */
    public Integer parent(int i){
        return (i-1)/2;
    }
    /**
     * 层序遍历
     */
    public List<Integer>  levelOrder(){
        List<Integer> res=new ArrayList<>();
        //直接遍历数组
        for(int i=0;i<size();i++){
            if(val(i)!=null)
                res.add(val(i));
        }
        return res;
    }
    /**
     * 深度优先遍历
     */
    public void dfs(Integer i,String order,List<Integer> res){
        //若未空未,返回
        if(val(i)==null)
            return;
        //前序遍历
        if("pre".equals(order)){
            res.add(val(i));
        }
        dfs(left(i),order,res);

        //中序遍历
        if("in".equals(order)){
            res.add(val(i));
        }
        dfs(right(i),order,res);

        //后序遍历
        if ("post".equals(order)){
            res.add(val(i));
        }
    }
    /**
     * 前序遍历
     */
    public List<Integer> preOrder(){
        List<Integer> res=new ArrayList<>();
        dfs(0,"pre",res);
        return res;
    }
    /**
     * 中序遍历
     *
     */
    public List<Integer> inOrder(){
        List<Integer> res=new ArrayList<>();
        dfs(0,"in",res);
        return res;
    }
    /**
     * 后序遍历
     */
    public List<Integer> postOrder(){
        List<Integer> res=new ArrayList<>();
        dfs(0,"post",res);
        return res;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值