树定义和基本术语
定义
树(Tree)是n(n≥0)个结点的有限集T,并且当n>0时满足下列条件:
     (1)有且仅有一个特定的称为根(Root)的结点;
     (2)当n>1时,其余结点可以划分为m(m>0)个互不相交的有限集T1、T2 、…、Tm,每个集Ti(1≤i≤m)均为树,且称为树T的子树(SubTree)。
    特别地,不含任何结点(即n=0)的树,称为空树。
如下就是一棵树的结构:

                        图1
基本术语
结点:存储数据元素和指向子树的链接,由数据元素和构造数据元素之间关系的引用组成。
孩子结点:树中一个结点的子树的根结点称为这个结点的孩子结点,如图1中的A的孩子结点有B、C、D
双亲结点:树中某个结点有孩子结点(即该结点的度不为0),该结点称为它孩子结点的双亲结点,也叫前驱结点。双亲结点和孩子结点是相互的,如图1中,A的孩子结点是B、C、D,B、C、D的双亲结点是A。
兄弟结点:具有相同双亲结点(即同一个前驱)的结点称为兄弟结点,如图1中B、B、D为兄弟结点。
结点的度:结点所有子树的个数称为该结点的度,如图1,A的度为3,B的度为2.
树的度:树中所有结点的度的最大值称为树的度,如图1的度为3.
叶子结点:度为0的结点称为叶子结点,也叫终端结点。如图1的K、L、F、G、M、I、J
分支结点:度不为0的结点称为分支结点,也叫非终端结点。如图1的A、B、C、D、E、H
结点的层次:从根结点到树中某结点所经路径的分支数称为该结点的层次。根结点的层次一般为1(也可以自己定义为0),这样,其它结点的层次是其双亲结点的层次加1.
树的深度:树中所有结点的层次的最大值称为该树的深度(也就是最下面那个结点的层次)。
有序树和无序树:树中任意一个结点的各子树按从左到右是有序的,称为有序树,否则称为无序树。
树的抽象数据类型描述
数据元素:具有相同特性的数据元素的集合。
结构关系:树中数据元素间的结构关系由树的定义确定。
基本操作:树的主要操作有
(1)创建树IntTree(&T)
         创建1个空树T。
(2)销毁树DestroyTree(&T)
(3)构造树CreatTree(&T,deinition)
(4)置空树ClearTree(&T)
          将树T置为空树。
(5)判空树TreeEmpty(T)
(6)求树的深度TreeDepth(T)
(7)获得树根Root(T)
(8)获取结点Value(T,cur_e,&e)
         将树中结点cur_e存入e单元中。
(9)数据赋值Assign(T,cur_e,value)
         将结点value,赋值于树T的结点cur_e中。
(10)获得双亲Parent(T,cur_e)
        返回树T中结点cur_e的双亲结点。
(11)获得最左孩子LeftChild(T,cur_e)
        返回树T中结点cur_e的最左孩子。
(12)获得右兄弟RightSibling(T,cur_e)
        返回树T中结点cur_e的右兄弟。
(13)插入子树InsertChild(&T,&p,i,c)
      将树c插入到树T中p指向结点的第i个子树之前。
(14)删除子树DeleteChild(&T,&p,i)
       删除树T中p指向结点的第i个子树。
(15)遍历树TraverseTree(T,visit())

树的实现
树是一种递归结构,表示方式一般有孩子表示法和孩子兄弟表示法两种。树实现方式有很多种、有可以由广义表的递归实现,也可以有二叉树实现,其中最常见的是将树用孩子兄弟表示法转化成二叉树来实现。

下面以孩子表示法为例讲一下树的实现:
树的定义和实现
    package datastructure.tree;  
      
    import java.util.ArrayList;  
    import java.util.Arrays;  
    import java.util.LinkedList;  
    import java.util.List;  
    /**
     * 树的定义和实现
     * @author Administrator
     *
     */  
    public class Tree {  
        private Object data;  
        private List<Tree> childs;  
          
        public Tree(){  
            data = null;  
            childs = new ArrayList();  
            childs.clear();  
        }  
          
        public Tree(Object data) {  
            this.data = data;  
            childs = new ArrayList();  
            childs.clear();  
        }  
      
        /**
         * 添加子树
         * @param tree 子树
         */  
        public void addNode(Tree tree) {  
            childs.add(tree);  
        }  
      
        /**
         * 置空树
         */  
        public void clearTree() {  
            data = null;  
            childs.clear();  
        }  
      
        /**
         * 求树的深度
         * 这方法还有点问题,有待完善
         * @return 树的深度
         */  
        public int dept() {  
            return dept(this);  
        }  
        /**
         * 求树的深度
         * 这方法还有点问题,有待完善
         * @param tree
         * @return
         */  
        private int dept(Tree tree) {  
            if(tree.isEmpty()) {  
                return 0;  
            }else if(tree.isLeaf()) {  
                return 1;  
            } else {  
                int n = childs.size();  
                int[] a = new int[n];  
                for(int i=0; i<n; i++) {  
                    if(childs.get(i).isEmpty()) {  
                        a[i] = 0+1;  
                    } else {  
                        a[i] = dept(childs.get(i)) + 1;  
                    }  
                }  
                Arrays.sort(a);  
                return a[n-1];  
            }  
        }  
        /**
         * 返回递i个子树
         * @param i
         * @return
         */  
        public Tree getChild(int i) {  
            return childs.get(i);  
        }  
      
        /**
         * 求第一个孩子 结点
         * @return
         */  
        public Tree getFirstChild() {  
            return childs.get(0);  
              
        }  
      
        /**
         * 求最后 一个孩子结点
         * @return
         */  
        public Tree getLastChild() {  
            return childs.get(childs.size()-1);  
        }  
      
        public List<Tree> getChilds() {  
            return childs;  
        }  
      
        /**
         * 获得根结点的数据
         * @return
         */  
        public Object getRootData() {  
            return data;  
        }  
      
        /**
         * 判断是否为空树
         * @return 如果为空,返回true,否则返回false
         */  
        public boolean isEmpty() {  
            if(childs.isEmpty() && data == null)  
                return true;  
            return false;  
        }  
          
        /**
         * 判断是否为叶子结点
         * @return
         */  
        public boolean isLeaf() {  
            if(childs.isEmpty())  
                return true;  
            return false;  
        }  
      
        /**
         * 获得树根
         * @return 树的根
         */  
        public Tree root() {  
            return this;  
        }  
      
        /**
         * 设置根结点的数据
         */  
        public void setRootData(Object data) {  
            this.data = data;  
        }  
      
        /**
         * 求结点数
         * 这方法还有点问题,有待完善
         * @return 结点的个数  
         */  
        public int size() {  
            return size(this);  
        }  
        /**
         * 求结点数
         * 这方法还有点问题,有待完善
         * @param tree
         * @return
         */  
        private int size(Tree tree) {  
            if(tree.isEmpty()) {  
                return 0;  
            }else if(tree.isLeaf()) {  
                return 1;  
            } else {  
                int count = 1;  
                int n = childs.size();  
                for(int i=0; i<n; i++) {  
                    if(!childs.get(i).isEmpty()) {  
                        count += size(childs.get(i));  
                    }  
                }  
                return count;  
            }  
        }  
    }

树的遍历
树的遍历有两种
前根遍历
(1).访问根结点;
(2).按照从左到右的次序行根遍历根结点的第一棵子树;

后根遍历
(1).按照从左到右的次序行根遍历根结点的第一棵子树;
(2).访问根结点;

Visit.Java
    package datastructure.tree;  
      
    import datastructure.tree.btree.BTree;  
      
    /**
     * 对结点进行操作的接口,规定树的遍历的类必须实现这个接口
     * @author Administrator
     *
     */  
    public interface Visit {  
        /**
         * 对结点进行某种操作
         * @param btree 树的结点
         */  
        public void visit(BTree btree);  
    }

order.java
    package datastructure.tree;  
      
      
    import java.util.List;  
    /**
     * 树的遍历
     * @author Administrator
     *
     */  
    public class Order {  
        /**
         * 先根遍历
         * @param root 要的根结点
         */  
        public void preOrder(Tree root) {  
            if(!root.isEmpty()) {  
                visit(root);  
                for(Tree child : root.getChilds()) {  
                    if(child != null) {  
                        preOrder(child);  
                    }  
                }  
            }  
        }  
        /**
         * 后根遍历
         * @param root 树的根结点
         */  
        public void postOrder(Tree root) {  
            if(!root.isEmpty()) {  
                for(Tree child : root.getChilds()) {  
                    if(child != null) {  
                        preOrder(child);  
                    }  
                }  
                visit(root);  
            }  
        }  
          
        public void visit(Tree tree) {  
            System.out.print("\t" + tree.getRootData());  
        }  
      
    }

测试:
要遍历的树如下:

package datastructure.tree;   
    import java.util.Iterator;  
    import java.util.Scanner;  
      
    public class TreeTest {  
      
        /**
         * @param args
         */  
        public static void main(String[] args) {  
            Tree root = new Tree("A");  
            root.addNode(new Tree("B"));  
            root.addNode(new Tree("C"));  
            root.addNode(new Tree("D"));  
            Tree t = null;  
            t = root.getChild(0);  
            t.addNode(new Tree("L"));  
            t.addNode(new Tree("E"));  
            t = root.getChild(1);  
            t.addNode(new Tree("F"));  
            t = root.getChild(2);  
            t.addNode(new Tree("I"));  
            t.addNode(new Tree("H"));  
            t = t.getFirstChild();  
            t.addNode(new Tree("L"));  
      
            System.out.println("first node:" + root.getRootData());  
            //System.out.println("size:" + root.size());  
            //System.out.println("dept:" + root.dept());  
            System.out.println("is left:" + root.isLeaf());  
            System.out.println("data:" + root.getRootData());  
              
            Order order = new Order();  
            System.out.println("前根遍历:");  
            order.preOrder(root);  
            System.out.println("\n后根遍历:");  
            order.postOrder(root);  
              
        }  
      
    }

结果:
first node:A
is left:false
data:A
前根遍历:
A BL E C F DI L H
后根遍历:
B LE C F D IL H A

转载至:http://blog.csdn.net/luoweifu/article/details/9071849

java数据结构之树的更多相关文章

  1. Java数据结构之树和二叉树(2)

    从这里始将要继续进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来 ...

  2. Java数据结构之树和二叉树

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  3. Java数据结构——AVL树

    AVL树(平衡二叉树)定义 AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树,并且拥有自平衡机制.在AV ...

  4. Java数据结构——字典树TRIE

    又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种. 典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 它的优点是:利用字符串的公共 ...

  5. JAVA数据结构--AVL树的实现

    AVL树的定义 在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下的时间复杂度都是.增 ...

  6. Java数据结构——2-3树

    定义2-3树是平衡的3路查找树,其中2(2-node)是指拥有两个分支的节点,3(3-node)是指拥有三个分支的节点.B-树是一种平衡的多路查找树,2-3树属于b-树,其也同样具有B-树的性质,如m ...

  7. java数据结构-12树相关概念

    一.树 1.概念: 包含n(n>=0)个结点的有穷集:树有多个节点(node),用以储存元素.某些节点之间存在一定的关系,用连线表示,连线称为边(edge).边的上端节点称为父节点,下端称为子节 ...

  8. Java数据结构和算法 - 什么是2-3-4树

    Q1: 什么是2-3-4树? A1: 在介绍2-3-4树之前,我们先说明二叉树和多叉树的概念. 二叉树:每个节点有一个数据项,最多有两个子节点. 多叉树:(multiway tree)允许每个节点有更 ...

  9. Java数据结构和算法(七)B+ 树

    Java数据结构和算法(七)B+ 树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 我们都知道二叉查找树的查找的时间复杂度是 ...

随机推荐

  1. Python OS模块中的fork方法实现多进程

    import os '''使用OS模块中的fork方式实现多进程''' '''fork方法返回两次,分别在父进程和子进程中返回,子进程中永远返回0,父进程返回的是子进程的is''' if __name ...

  2. java web 验证码-字符变形(推荐)

    该文章转载自:http://www.cnblogs.com/jianlun/articles/5553452.html 因为在我做的这个系统中发现验证码有点偏上,整体效果看起来不太好,就做了一些修改. ...

  3. dwr框架介绍

    转: [DWR框架]过时了吗? 置顶 2018年06月02日 11:59:02 许你笑颜 阅读数:4129   版权声明: https://blog.csdn.net/smileyan9/articl ...

  4. 个推基于Consul的配置管理

    作者:个推应用平台基础架构高级研发工程师 阿飞 在微服务架构体系中,由于微服务众多,服务之间又有互相调用关系,因此,一个通用的分布式配置管理是必不可少的.一般来说,配置管理需要解决配置集中管理.在系统 ...

  5. log4j2常见配置

    依赖jar: <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId> ...

  6. WINDOWS控制界面操作命令for WIN10

    Windows系统:开始--运行--命令大全: cmd--------CMD命令提示符 cleanmgr-------垃圾整理 compmgmt.msc---计算机管理 conf----------- ...

  7. Does Deep Learning Come from the Devil?

    Does Deep Learning Come from the Devil? Deep learning has revolutionized computer vision and natural ...

  8. Flex 编写 loading 组件

    Flex 界面初始化有时那个标准的进度条无法显示,界面长时间会处理空白的状态!我们来自定义一个进度条, 这个进度条加载在 Application 应用程序界面的 <s:Application 标 ...

  9. 在 Linux 中安装 VMware Tools

    由于较新的Linux版本中都包含了vm的部分组件,导致直接安装VMware Tools失败.所以这里写了篇新的. 软件版本:VMware 12 Linux版本:Ubuntu Desktop 16.04 ...

  10. MFC笔记(DN)

    01:MFC应用程序编程 02:MFC菜单.工具栏.状态栏 03:视图窗口