4、树的概述

4.1 与树相关的概念

  • 节点:树的最基本组成元素,常常包含一个数据元素以及若干个指针用于指向其他节点;
  • 节点的度(degree):节点拥有的子树的个数
  • 树的度:树中所有节点的最大度即该树的度
  • 叶子节点:度为0的节点被称为叶子节点或者终端节点
  • 分支节点:度不为0的节点称为分支节点或者非终端节点
  • 子节点、父节点、兄弟节点:节点的子树的根被称为该节点的子节点,该节点被称为子节点的父节点,具有相同父节点的子节点被称为兄弟节点
  • 节点的层次(level):节点的层次从根开始算起,根节点的层次为1,其他节点的层次为父节点的层次加1
  • 树的深度:树中节点的最大层次值称为树的深度或高度
  • 有序树与无序树:如果将树中节点的各个子树看成从左到右是有序的,则该树被称为有序树,否则是无序树
  • 祖先节点(ancestor):从根到该节点所经路径的所有节点
  • 后代节点:以某节点为跟的子树中任意节点都被称为该节点的子节点
  • 森林:2棵或者2棵以上互不相交的树的集合,删去一棵树的根,就得到一片森林

4.2 树的实现

为实现树这种数据结构,必须记录节点与节点之间的父子关系,所以又以下两种表示方法:

  • 父节点表示法:每个节点都记录他的父节点
  • 孩子链表示法:每个非叶子节点通过一个链表来记录它的所有的子节点

下面分别用两种方法实现树的表示:

4.2.1 树的父节点表示

这里写图片描述

这里写图片描述

import java.util.ArrayList;
import java.util.List;

/**
 * 树的父节点表示法
 * @author retreatweb
 *
 * @param <E> 树中保存的元素类型
 */
public class TreeParent<E> {

    /**
     * 树中保存的元素
     * @author retreatweb
     * @param <T> 节点的数据类型
     */
    public static class Node<T>{
        T data;
        //记录父节点的位置
        int parent;

        public Node(){

        }

        public Node(T data){
            this.data = data;
        }

        public Node(T data, int parent) {
            this.data = data;
            this.parent = parent;
        }

        public String toString(){
            return "TreeParent$Node[data="+data+",parent="+parent+"]";
        }

    }

    private final int DEFAULT_TREE_SIZE = 10;
    private int treeSize = 0;
    //使用一个NOde[]数组来记录树中所有的节点
    private Node<E>[] nodes;
    //记录节点数
    private int nodeNums;
    //以指定根节点创建树
    public TreeParent(E data){
        treeSize = DEFAULT_TREE_SIZE;
        nodes = new Node[treeSize];
        nodes[0] = new Node<E>(data, -1);
        nodeNums++;
    }
    //以指定根节点指treesize创建树
    public TreeParent(E data,int treeSize){
        this.treeSize = treeSize;
        nodes = new Node[treeSize];
        nodes[0] = new Node<E>(data, -1);
        nodeNums++;
    }
    /**
     * 为指定节点添加子节点
     * @param data 子节点的数据
     * @param parent 需要添加子节点的节点
     */
    public void addNode(E data,Node parent){
        for (int i = 0; i < treeSize; i++) {
            //找到数组中第一个为null的元素,用该元素保存该子节点
            if(nodes[i] == null){
                //创建新节点,并用数组元素保存
                nodes[i] = new Node<E>(data, pos(parent));
                nodeNums++;
                return;
            }
        }
        throw new RuntimeException("该树已满,无法添加元素");
    }
    /**
     * 获得包含指定值的位置
     * @param parent 指定值
     * @return 指定值的位置
     */
    public int pos(Node<E> parent) {
        for (int i = 0; i < treeSize; i++) {
            if(nodes[i] == parent){
                return i;
            }
        }
        return -1;
    }
    /**
     * 判断树是否为空
     * @return 返回根元素是否为null
     */
    public boolean isEmpty(){
        return nodes[0] == null;
    }
    /**
     * 求根节点
     * @return 返回根节点
     */
    public Node<E> root(){
        return nodes[0];
    }
    /**
     * 获得指定父节点的所有的子节点
     * @param parent 指定的父节点
     * @return 返回子节点的集合
     */
    public List<Node<E>> children(Node<E> parent){
        List<Node<E>> list = new ArrayList();
        for (int i = 0; i < treeSize; i++) {
            //如果当前节点的父节点的位置等于父节点的位置
            if(nodes[i] != null && nodes[i].parent == pos(parent)){
                list.add(nodes[i]);
            }
        }
        return list;
    }
    /**
     * 获取该树的深度
     * @return 返回该树的节点的最大深度
     */
    public int deep(){
        //用于记录节点的最大深度
        int max = 0;
        for (int i = 0; i < treeSize && nodes[i] != null; i++) {
            //初始化本节点的深度
            int def = 1;
            //用m记录当前节点的父节点的位置
            int m = nodes[i].parent;
            //如果当前节点的父节点存在
            if(m != -1 && nodes[m] != null){
                //向上继续搜索父节点
                m = nodes[m].parent;
                def++;
            }
            if(max < def){
                max = def;
            }
        }
        return max;
    }

}
4.2.2 树的孩子链表示

这里写图片描述

import java.util.ArrayList;
import java.util.List;

/**
 * 树的子节点链表示法
 * 
 * @author Administrator
 *
 */
public class TreeChild<E> {

    /**
     * 子节点
     */
    private static class SonNode {
        // 记录当前节点位置
        private int pos;
        private SonNode next;

        public SonNode(int pos, SonNode next) {
            this.pos = pos;
            this.next = next;
        }
    }

    /**
     * 节点
     * 
     * @author Administrator
     *
     * @param <T>
     */
    public static class Node<T> {
        T data;
        // 记录第一个子节点
        SonNode first;

        public Node(T data) {
            this.data = data;
            this.first = null;
        }

        public String toString() {
            if (first != null) {
                return "TreeChild$Node[data=" + data + ",first" + first.pos + "]";
            } else {
                return "TreeChild$Node[data=" + data + ",first=-1]";
            }
        }
    }

    private final int DEFAULT_TREE_SIZE = 10;
    private int treeSize = 0;
    // 使用一个NOde[]数组来记录树中所有的节点
    private Node<E>[] nodes;
    // 记录节点数
    private int nodeNums;

    // 以指定根节点创建树
    public TreeChild(E data) {
        treeSize = DEFAULT_TREE_SIZE;
        nodes = new Node[treeSize];
        nodes[0] = new Node<E>(data);
        nodeNums++;
    }

    // 以指定根节点指treesize创建树
    public TreeChild(E data, int treeSize) {
        this.treeSize = treeSize;
        nodes = new Node[treeSize];
        nodes[0] = new Node<E>(data);
        nodeNums++;
    }

    // 为指定节点添加子节点
    public void addNode(E data, Node parent) {
        for (int i = 0; i < treeSize; i++) {
            // 找到数组中第一个为null的元素,用该元素保存该子节点
            if (nodes[i] == null) {
                // 创建新节点,并用指定数组元素保存
                nodes[i] = new Node(data);
                if (parent.first == null) {
                    parent.first = new SonNode(i, null);
                } else {
                    SonNode snext = parent.first;
                    while (snext.next != null) {
                        snext = snext.next;
                    }
                    snext.next = new SonNode(i, null);
                }
                nodeNums++;
                return;
            }
        }
        throw new RuntimeException("该树已满,无法添加元素");
    }

    /**
     * 判断树是否为空
     * @return 返回根元素是否为null
     */
    public boolean isEmpty(){
        return nodes[0] == null;
    }
    /**
     * 求根节点
     * @return 返回根节点
     */
    public Node<E> root(){
        return nodes[0];
    }

    /**
     * 获得指定父节点的所有的子节点
     * @param parent 指定的父节点
     * @return 返回子节点的集合
     */
    public List<Node<E>> children(Node<E> parent){
        List<Node<E>> list = new ArrayList();
        //获取parent节点的第一个子节点
        SonNode first = parent.first;
        //沿着孩子链不断搜素下一个孩子节点
        while(first != null){
            list.add(nodes[first.pos]);
            first = first.next;
        }
        return list;
    }
    /**
     * 获取指定父节点的第index个子节点
     * @param parent 指定父节点
     * @param index 第index个子节点
     * @return 返回子节点
     */
    public Node<E> child(Node parent,int index){
        //获取指定父节点的第一个子节点
        SonNode first = parent.first;
        for (int i = 0;first != null; i++) {
            if(i == index){
                return nodes[first.pos];
            }
            first = first.next;
        }
        return null;
    }
    /**
     * 获取树的最大深度
     * @return 返回树的深度
     */
    public int deep(){
        return deep(root());
    }

    /**
     * 获得某节点的最大深度
     * 该方法为递归方法,每一棵子树的最大深度为其子树的深度+1
     * @param node 要求深度的节点
     * @return
     */
    private int deep(Node<E> node) {
        //叶子节点
        if(node.first == null){
            return 1;
        }else{
            //记录所有子树的最大深度
            int max = 0;
            SonNode next = node.first;
            while(next != null){
                //获取以其子节点为跟的树的深度
                int tem = deep(nodes[next.pos]);
                if(tem > max){
                    max = tem;
                }
                next = next.next;
            }
            return max + 1;
        }
    }

    public int index(Node node){
        for (int i = 0; i < treeSize; i++) {
            if(nodes[i] == node){
                return i;
            }
        }
        return -1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值