树结构以及简单实现

树简介

树结构,一种非线性结构,指的是N个有父子关系节点的有限集合。

树中任一节点可以有0或多个子节点,但只能有一个父节点。根节点是一个特例,根节点没有父节点,叶子节点没有子节点。树中每个节点既可以是其上一级节点的子节点,也可以是下一级节点的父节点,因此同一个节点可以既是父节点,也是子节点。

如果按节点是否包含子节点来分,节点分成以下两种:

  • 普通节点:包含子节点的节点。
  • 叶子节点:没有子节点的节点,因此叶子节点不可作为父节点。

如果按节点是否具有唯一的父节点来分,节点又可分为如下两种:

  • 根节点:没有父节点的节点,根节点不可作为子节点。
  • 普通节点:具有唯一父节点的节点。

相关术语:

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

父节点表示法

树中除根节点之外的每个节点都有一个父节点。为了记录树中节点与节点之间的父子关系,可以为每个节点增加一个parent域,用以记录该节点的父节点。

public class TreeParent<E> {
    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;
        }

        @Override
        public String toString() {
            return "TreeParent$Node[data=" + data + ",parent=" + parent + "]";
        }
    }
    private final int DEFAULT_SIZE = 100;
    private int treeSize = 0;
    private Node<E>[] nodes;
    private int nodeNums;
    //  以指定根节点创建树
    public TreeParent(E data) {
        treeSize = DEFAULT_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);
        nodeNums++;
    }
    //  为指定节点添加子节点
    public void addNode(E data, Node parent) {
        for (int i = 0; i < treeSize; i++) {
            if (nodes[i] != null) {
                nodes[i] = new Node(data, pos(parent));
                nodeNums++;
                return;
            }
        }
        throw new RuntimeException();
    }
    public boolean empty() {
        return nodeNums == 0;
    }
    //  返回根节点
    public Node<E> root() {
        return nodes[0];
    }
    // 返回指定节点的父节点
    public Node<E> parent(Node node) {
        return nodes[node.parent];
    }
    //  返回指定节点(非叶子节点)的所有子节点
    public List<Node<E>> children(Node 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;
    }
    //  返回该树的深度
    public int deep() {
        int max = 0;
        for (int i = 0; i < treeSize && nodes[i] != null; i++) {
            int def = 1;
            int m = nodes[i].parent;
            while (m != -1 && nodes[m] != null) {
                m = nodes[m].parent;
                def++;
            }
            if (max < def) {
                max = def;
            }
        }
        return max;
    }
    //  返回包含指定值的节点
    private int pos(Node parent) {
        for (int i = 0; i < treeSize; i++) {
            if (nodes[i] == parent) {
                return i;
            }
        }
        return -1;
    }
}

子节点链表示法

由每个节点记住它的所有子节点。

 

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;
        }
    }

    public static class Node<T> {
        T data;
        //记录第一个节点
        SonNode first;
        public Node(T data) {
            this.data = data;
            this.first = null;
        }
    }

    private final int DEFAULT_SIZE = 100;
    private int treeSize = 0;
    //使用一个Node[]数组来记录该树里所有节点
    private Node<E>[] nodes;
    //记录节点数
    private int nodeNums;
    //以指定根节点创建树
    public TreeChild(E data) {
        this.treeSize = DEFAULT_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++) {
            if (nodes[i] == null) {
                nodes[i] = new Node(data);
                if (parent.first == null) {
                    parent.first = new SonNode(i, null);
                } else {
                    SonNode next = parent.first;
                    while (next.next != null) {
                        next = next.next;
                    }
                    next.next = new SonNode(i, null);
                }
                nodeNums++;
                return;
            }
        }
        throw new RuntimeException();
    }
    //判断是否为空
    public boolean empty() {
        return nodeNums == 0;
    }
    //返回根节点
    public Node<E> root() {
        return nodes[0];
    }
    //返回指定节点(非叶子结点)的所有子节点
    public List<Node<E>> children(Node parent) {
        List<Node<E>> list = new ArrayList<>();
        SonNode next = parent.first;
        while (next != null) {
            list.add(nodes[next.pos]);
            next = next.next;
        }
        return list;
    }
    //返回指定节点(非叶子节点)的第index个子节点
    public Node<E> child(Node parent, int index) {
        SonNode next = parent.first;
        for (int i = 0; next != null; i++) {
            if (i == index) {
                return nodes[next.pos];
            }
            next = next.next;
        }
        return null;
    }
    //返回该树的深度
    public int deep() {
        return deep(root());
    }
    private int deep(Node node) {
        if (node.first == null) {
            return 1;
        } else {
            int max = 0;
            SonNode next = node.first;
            while (next != null) {
                int tmp = deep(nodes[next.pos]);
                if (tmp > max) {
                    max = tmp;
                }
                next = next.next;
            }
            return max + 1;
        }
    }
    //返回包含指定值的节点
    public int pos(Node node) {
        for (int i = 0; i < treeSize; i++) {
            if (nodes[i] == node) {
                return i;
            }
        }
        return -1;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值