树-普通树

一、树的概述:

  线性表、栈、队列都是线型的数据结构,该种数据结构之间的元素只存在一对一的关系,而树的结构内元素是非线性的关系,存在着一对多的关系,例如一个父节点可以包含多个子节点。

  树指的是N个有父子关系的节点的有限集合,满足以下关系:

  1、当N=0时,该节点集合为空,这棵树被称为空树。

  2、在任意的非空树中,有且仅有一个根节点。

  3、当N>1时,除根节点以外的其余节点可分为M个互为相交的有限集合T1,T2...Tm,其中的每个集合本身又是一棵树并成为根的子树

二、树的递归特性:

  一棵树由根和若干棵子树组成,而每个子树又由若干棵更小的子树组成。

  

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

三、节点的分类:  

    (按照节点是否包含子节点来划分)

    1、普通节点:包含子节点的节点

    2、叶子节点:没有子节点的节点,因此叶子节点不可以作为父节点。

    (按照节点是否具有唯一的父节点来划分)

    1、根节点:没有父节点的节点,根节点不可作为子节点。

    2、普通节点:具有唯一的父节点。

    一棵树只能有一个根节点,多棵树被称为森林。

四、树的术语:

  节点:树的最基本组成单元,常包括一个数据元素以及若干指针用于指向其他节点。

  节点的度(degree):节点拥有的子树的个数。

  树的度:树中所有节点的度的最大值

  叶子节点:度为0的节点被称为叶子节点或终端节点。

  分支节点:度不为0的节点被称为分支节点或非终端节点。  

  节点的层次(level):节点的层次从根开始算起,根的层次值为1,其余节点的层次值为父节点层次值加一

  树的深度(depth):树中节点的最大层次值称为树的深度或高度。

  有序树与无序树:如果将树中节点 的各个子树看成从左到右是有序的(即不能互换),则称该树为有序树,否则是无序树。

  祖先节点(ancestor):从根到该节点所经分支上的所有节点。

  后代节点(descendant):以某节点为根的子树中任一节点都称为该节点的后代节点。

  森林:森林是两棵树或两棵以上互不相交的树的集合。

  

五、树的操作

  为了实现树的这种数据结构,程序必须能记录节点与节点之间的父子关系,为此有两种选择: 

  1、父节点表示法:每个子节点都记录它的父节点。(为诶一个节点都增加一个parent域来记录该节点的父节点)

  2、孩子节点表示法:每个非叶子节点通过一个链表来记录它所有的子节点。

父节点表示:

package com.zxc.TreeLearning;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2018/2/18 0018
 * 父节点表示法表示树
 */
public class CommonTree {
    public static class Node {
        String data;
        int parent;

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

        public String toString() {
            return "父节点表示法|data" + data + ",parent=" + parent;
        }
    }

    private int treeSize = 100;//树节点的数量
    private Node[] nodes=new Node[this.treeSize];//使用一个数组来记录树中所有节点
    private int nodeNums;//记录节点数

    public CommonTree(){
    }

    /**
     *
     * @param node:要查找的节点
     * @return
     */
    public int pos(Node node){
        for(int i=0;i<this.treeSize;i++){
            if(nodes[i]==node){
                return i;
            }
        }
        return -1;
    }


    /**
     *
     * @param data:当前节点数据
     * @param parent:指定它的父节点
     */
    public Node add(String data,Node parent) {
        for (int i = 0; i < this.treeSize; i++) {
            if (nodes[i] == null) {
                nodes[i] = new Node(data, pos(parent));
                this.nodeNums++;
                return nodes[i];
            }
        }
        return null;
    }


    /**
     *
     * @return 该树的高度
     */
    public int deep(){
        int max=0;
        for(int i=0;i<this.treeSize&&nodes[i]!=null;i++){
            int count=1;
            int m=nodes[i].parent;
            //找到当前m所指的节点的父亲,直到没有节点位置,或者到root节点为止
            while(m!=-1&&nodes[m]!=null){
                m=nodes[m].parent;
                count++;
            }
            if(count>max){
                max=count;
            }
        }
        return max;
    }


    /**
     *
     * @param parent:指定父节点
     * @return 当前父节点下的子节点
     */
    public List<Node> getchild(Node parent){
        List<Node> list=new ArrayList();
        for(int i=0;i<this.treeSize;i++){
            if(nodes[i]!=null&&nodes[i].parent==this.pos(parent)){
                list.add(nodes[i]);
            }
        }
        return list;
    }

    public Node root(String data){
        nodes[0]=new Node(data,-1);
        this.nodeNums++;
        return nodes[0];
    }
    @Test
    public void test(){
        Node root=this.root("root");
        Node a=this.add("A",root);
        Node b=this.add("B",a);
        Node c=this.add("C",root);
        Node d=this.add("D",c);

        System.out.println(this.deep());
        List<Node> list=this.getchild(c);
        for(Node node:list){
            System.out.println(node.data);
        }
    }
}

 子节点表示法:

package com.zxc.TreeLearning;

import org.junit.Test;

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

/**
 * Created by Administrator on 2018/2/19 0019.
 * 子节点链表示法
 */
public class CommonTreeB {

     private static class SonNode{//子节点链每个节点的信息
         private int pos;//记录当前节点的位置
         private SonNode next;//子节点记录下一个节点的对象
         public SonNode(int pos,SonNode next){
             this.pos=pos;//当前节点位置
             this.next=next;//下一个节点位置
         }
     }

     //子节点链
     private static class Node{//单个节点的信息
         String data;
         //记录第一个子节点:用于保存对该子节点链的引用,通过这种关系,可以记录树中节点之间的关系
         SonNode first;
         public Node(String 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 int treeSize=100;
     private Node[] nodes=new Node[treeSize];
     private int nodeNums;
     public Node root(String data) {
        nodes[0]=new Node(data);
        nodeNums++;
        return nodes[0];
     }

     public Node addNode(String 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);//parent的儿子节点链的第一个节点
                 }else{//父节点中有子节点,应该传到最后,再连接
                     SonNode next=parent.first;
                     while(next.next!=null){
                         next=next.next;
                     }
                    next.next=new SonNode(i,null);
                 }
                 nodeNums++;
                 return nodes[i];
             }
         }
         return null;
     }

    private int deep(Node node){//从下到上的深度
         if(node.first==null){
             return 1;
         }else{
             int max=0;
             SonNode son=node.first;
             while(son!=null){
                 int temp=deep(nodes[son.pos]);
                 if(temp>max){
                     max=temp;
                 }
                 son=son.next;
             }
             return  max+1;
         }
    }

    public List getChildren(Node parent){
        List list=new ArrayList();
        SonNode node=parent.first;
        while(node!=null){
            list.add(nodes[node.pos]);
            node=node.next;
        }
        return list;
    }

    @Test
    public void ok(){
        Node root=this.root("A");
        Node B=this.addNode("B",root);
        Node C=this.addNode("C",root);
        Node D=this.addNode("D",root);
        Node E=this.addNode("E",B);
        Node F=this.addNode("F",D);
        Node G=this.addNode("G",D);
        Node H=this.addNode("H",E);
        Node I=this.addNode("I",E);
        Node J=this.addNode("J",E);
        Node K=this.addNode("K",G);
        System.out.println(this.deep(G));

        List<Node> list=this.getChildren(B);
        for(Node b:list){
            System.out.println(b.data);
        }

    }
}
原文地址:https://www.cnblogs.com/television/p/8453155.html