二叉树的定义和用Java进行实现

来源:互联网 发布:杨幂为李易峰打胎知乎 编辑:程序博客网 时间:2024/05/29 14:03

先放上数据结构中有关树的一些定义:

  1. 节点:节点包括一个数据元素及若干指向其子树的分支

  2. 节点的度:节点所拥有的子树的个数成为该节点的度

  3. 叶节点:度为0的节点称为叶结点

  4. 分支节点:度不为0的节点称为分支节点

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

  6. 二叉树:是n(n>=0)个有限节点构成的集合。n=0的树称为空二叉树;n=1的树只有一个根结点;
    n>1的二叉树由一个根节点和至多两个互不相交的,分别称为左子树和右子树的子二叉树构成
    二叉树不是有序树,这是因为,二叉树中某个节点即使只有一个子树也要区分是左子树还是右子树;
    而对于有序树来说,如果某个节点只有一个子树就必定是第一个子树

  7. 二叉树所有结点的形态有5种:空节点,无左右子树节点,只有左子树节点,只有右子树节点和左右子树均存在的节点

  8. 满二叉树:在一棵二叉树中,如果所有分支节点都存在左子树和右子树,并且所有叶子节点都在同一层,则这样的二叉树称作满二叉树
  9. 完全二叉树:如果一颗具有n个节点的二叉树的结构与满二叉树的前n个节点的结构相同,这样的二叉树称为完全二叉树
  10. 二叉树的性质

1)若规定根节点的层数为0,则一棵非空二叉树的第i层上最多有2^i(i>=0)个节点
2)若规定只有根节点的二叉树的深度为0,则深度为k的二叉树的最大节点数是2^(k+1)-1(k>=-1)
3)对于一棵非空的二叉树,如果叶节点个数为n0,度为2的节点个数为n2,则有n0=n2+1
4)具有n个节点的完全二叉树的深度k为大于或等于ln(n+1)-1的最小整数
5)对于具有n个节点的完全二叉树,如果按照从上至下和从左至右的顺序对所有节点序号从0开始顺序编号,则对于序号为i(0<=i< n)的节点有:
如果i>0,则序号为i节点的双亲节点的序号为(i-1)/2(/为整除);如果i=0,则序号为i节点为根节点,无双亲节点 如果2i+1<
n,则序号为i节点的左孩子节点的序号为2i+1;如果2i+1>=n,则序号为i节点无左孩子 如果2i+2<
n,则序号为i节点的右孩子节点的序号为2i+2;如果2i+2>=n,则序号为i节点无右孩子

11.二叉树的存储结构

1.二叉树的顺序存储结构 利用性质5,对于完全二叉树可以利用一维数组存储,如果不是完全二叉树,则可以补空节点,使成为完全二叉树在进行存储,
但是对于非完全二叉树,可能要浪费很多的空间。
2.二叉树的链式存储结构 二叉树的链式存储结构就是用指针建立二叉树中节点之间的关系,二叉树最常用的链式存储结构是二叉链。二叉树的二叉链存储结构是一种常用的
二叉树存储结构。二叉链存存储结构的优点时,结构简单,可以方便的构造任何形状的二叉树,并可以方便的实现二叉树的大多数操作。
二叉链存储结构的缺点是,查找当前节点的双亲节点操作实现比较麻烦
3.二叉树的仿真指针存储结构 利用一维数组和结构体实现,利用数组的下标进行仿真指针进行二叉树的操作

下面为具体代码实现:

package tree;import java.util.LinkedList;import java.util.List;/**  *   * @author xmhzwy@163.com @date: 2017-3-7  *   */  public class BinTreeTraverse {    private int arr[]={1,2,3,4,5,6,7};    private static List<Node> nodeList=null;    private static class Node{        Node leftchild;        Node rightchild;        int data;        Node(int newdata){            leftchild=null;            rightchild=null;            data=newdata;        }    }    public void createBintree(){//新建一个二叉树        nodeList=new LinkedList<Node>();        for (int nodIndex = 0; nodIndex < arr.length; nodIndex++) {            nodeList.add(new Node(arr[nodIndex]));        }        //以下定义主要依据上面讲解的第五条的特性实现        for (int parentIndex = 0; parentIndex < arr.length/2-1; parentIndex++) {            //左孩子            nodeList.get(parentIndex).leftchild=nodeList.get(parentIndex*2+1);            //右孩子            nodeList.get(parentIndex).rightchild=nodeList.get(parentIndex*2+2);        }        //最后一个父节点,因为最后一个父节点可能没有右孩子,所以单独拿出来处理        int lastParentIndex=arr.length/2-1;        //左孩子        nodeList.get(lastParentIndex).leftchild=nodeList.get(lastParentIndex*2+1);        if (arr.length%2==1) {            nodeList.get(lastParentIndex).rightchild=nodeList.get(lastParentIndex*2+2);        }    }     /**      * 先序遍历      *       * 这三种不同的遍历结构都是一样的,只是先后顺序不一样而已      *       * @param node      * 遍历的节点      */      public static void preOrderTraverse(Node node) {          if (node == null)              return;          System.out.print(node.data + " ");          preOrderTraverse(node.leftchild);          preOrderTraverse(node.rightchild);      }      /**      * 中序遍历      *       * 这三种不同的遍历结构都是一样的,只是先后顺序不一样而已      *       * @param node      *            遍历的节点      */      public static void inOrderTraverse(Node node) {          if (node == null)              return;          inOrderTraverse(node.leftchild);          System.out.print(node.data + " ");          inOrderTraverse(node.rightchild);      }      /**      * 后序遍历      *       * 这三种不同的遍历结构都是一样的,只是先后顺序不一样而已      *       * @param node      *            遍历的节点      */      public static void postOrderTraverse(Node node) {          if (node == null)              return;          postOrderTraverse(node.leftchild);          postOrderTraverse(node.rightchild);          System.out.print(node.data + " ");      }      public static void main(String[] args) {          BinTreeTraverse binTree = new BinTreeTraverse();          binTree.createBintree();          // nodeList中第0个索引处的值即为根节点          Node root = nodeList.get(0);          System.out.println("先序遍历:");          preOrderTraverse(root);          System.out.println();          System.out.println("中序遍历:");          inOrderTraverse(root);          System.out.println();          System.out.println("后序遍历:");          postOrderTraverse(root);      }  }

输出的结果为:

先序遍历:1 2 4 5 3 6 7 中序遍历:4 2 5 1 6 3 7 后序遍历:4 5 2 6 7 3 1 
0 0