Java二叉树的实现

  树形结构就是一种非常重要的非线性结构。在树形结构中数据元素之间具有一对多的逻辑关系,它反映了数据元素之间的层次关系,和一个数据元素可以有多个后继但最多只有一个前驱的特点。树形结构在现实中有很多实际应用。


一、 树

  树是由n(n≥0)个结点所构成的有限集合,当n=0时,称为空树。

 例:

 

 常用术语:

 1.树的结点

   树的节点是由一个数据元素和关联其子树的边所组成。如图,有6个结点。

 2. 结点的路径

  结点的路径是指从根结点到该结点所经历的结点和分支的排列顺序。如图,结点E的路径是A——>C——>E。

 3. 路径的长度

  路径的长度是指结点路径中所包含的分支数。如图,结点E的路径长度是2。

 4.结点的度

  结点的度是指该结点所拥有子树的数目。如图,结点C的度为2,结点E的度为0。

 5. 树的度

  树的度是指树中所有结点的度的最大值。如图,树的度为2。

 6. 叶结点

  树的度是指树中度为0的结点。如图,结点D、E、F都是叶结点。

 7. 子结点 (孩子结点)

  结点的子结点是指这个结点的子树的根结点。

 8. 父结点 (双亲结点)

  若树中的某个结点有孩子结点,则这个结点就称为孩子结点的父结点。

 9. 兄弟结点

  兄弟结点是指具有同一双亲的结点。如图,结点B、C是兄弟结点。

 10. 结点的层次

  规定树中根结点的层次为0,则其它结点的层次是其双亲结点的层次数加1。

 11.  树的深度

  树地深度是指树中所有结点的层次数的最大值加1。

 12. 森林

  森林是指由m(m≥0)棵互不相交的树所构成的集合。


二、 二叉树

 1. 二叉树是一种特殊的树,它的每个结点最多只有两棵子树,并且这两棵子树也是二叉树。

  当n=0时,二叉树为空树;当n≥0时,二叉树由根节点和左右子树构成。

 2. 满二叉树

  一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。

  即如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树

 

 3.完全二叉树

  叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树

 


三、 二叉树的性质

 1. 二叉树中第i(i≥0)层上的结点数最多为2^i

 2. 深度为h(h≥1)的二叉树中最多有2^h-1个结点

 3. 对于任何一棵二叉树,若其叶结点的个数为n0,度为2的结点个数为n2,则有n0=n2+1

 4. 具有n个结点的完全二叉树,其深度为[ log2n ]+1


四、 二叉树的存储结构

 1. 二叉树的存储实现方法有多种,主要有顺序存储和链式存储两大类。

 2. 在二叉链表结构中,二叉树的每一个结点有3个域:数据域、左孩子域和右孩子域。

  其中,数据域用来存放结点的值,左、右孩子域分别用来存放结点的左、右孩子结点党的存储地址。


五、 二叉树的实现

 二叉链式存储结构是二叉树最常用的存储结构。

代码如下:

public class BinTree {

    private Node root;  //根节点

    private static int index=0;   //记录字符串的索引值(先序创建二叉树)

    public BinTree()
    {
        this.root=null;
    }
    public BinTree(Node root)
    {
        this.root=root;
    }

    //根据字符串先序创建二叉树
    public BinTree(String preStr)
    {
        char c=preStr.charAt(index++);
        if(c!='#')
        {
            root=new Node(c);
            root.lchild=new BinTree(preStr).root;
            root.rchild=new BinTree(preStr).root;
        }
        else
            root=null;
    }

    //获取树根
    public Node getRoot()
    {
        return root;
    }
    //获取结点的父节点
    public Node getParent(Node current, Node r)
    {
        if(r==null)
            return null;
        if(r.lchild==current || r.rchild==current)
            return r;
        Node lNode=getParent(current, r.lchild);
        Node rNode=getParent(current, r.rchild);
        if(lNode==null)
            return rNode;
        if(rNode==null)
            return lNode;
        return r;
    }
    //获取左结点
    public Node getLchild(Node r)
    {
        return (r!=null)?r.lchild:null;
    }
    //获取右结点
    public Node getRchild(Node r)
    {
        return (r!=null)?r.rchild:null;
    }


    //查找所在结点
    public Node searchNode(Node r, Object x)
    {
        if(r!=null)
        {
            if(r.data.equals(x))
                return r;
            else
            {
                Node q=searchNode(r.lchild, x);
                return q!=null? q:searchNode(r.rchild, x);
            }
        }
        return null;
    }

    //计算结点总个数
    public int countNode(Node r)
    {
        if(r==null)
            return 0;
        else
            return countNode(r.lchild)+countNode(r.rchild)+1;
    }
    //求树的深度
    public int getDepth(Node r)
    {
        if(r==null)
            return 0;
        else
        {
            int left=getDepth(r.lchild);
            int right=getDepth(r.rchild);
            return left>right?(left+1):(right+1);
        }
    }

    //先序递归
    public void preRootTraverse(Node r)
    {
        if(r!=null)
        {
            System.out.print(r.data+" ");
            preRootTraverse(r.lchild);
            preRootTraverse(r.rchild);
        }
    }
    //先序非递归
    public void preRootTraverse()
    {
        Node r=root;
        if(r!=null)
        {
            Stack<Node> stack=new Stack<Node>();
            stack.push(r);
            while(!stack.isEmpty())
            {
                r=(Node)stack.pop();
                System.out.print(r.data+" ");

                while(r!=null)
                {
                    if(r.lchild!=null)
                        System.out.print(r.lchild.data+" ");
                    if(r.rchild!=null)
                        stack.push(r.rchild);
                    r=r.lchild;
                }
            }
        }
    }

    //中序递归
    public void inRootTraverse(Node r)
    {
        if(r!=null)
        {
            inRootTraverse(r.lchild);
            System.out.print(r.data+" ");
            inRootTraverse(r.rchild);
        }
    }
    //中序非递归
    public void inRootTraverse()
    {
        Node r=root;
        if(r!=null)
        {
            Stack<Node> stack=new Stack<Node>();
            stack.push(r);
            while (!stack.isEmpty())
            {
                while(stack.peek()!=null)
                {
                    Node q=(Node)stack.peek();
                    stack.push(q.lchild);
                }
                stack.pop();
                if(!stack.isEmpty())
                {
                    r=(Node)stack.pop();
                    System.out.print(r.data+" ");
                    stack.push(r.rchild);
                }
            }
        }
    }

    //后序递归
    public void postRootTraverse(Node r)
    {
        if(r!=null)
        {
            postRootTraverse(r.lchild);
            postRootTraverse(r.rchild);
            System.out.print(r.data+" ");
        }
    }
    //后序非递归
    public void postRootTraverse()
    {
        Node r=root;
        if(r!=null)
        {
            Stack<Node> stack=new Stack<Node>();
            stack.push(r);
            Boolean flag;
            Node q=null;

            while(!stack.isEmpty())
            {
                while (stack.peek()!=null)
                {
                    Node t=(Node)stack.peek();
                    stack.push(t.lchild);
                }
                stack.pop();
                while(!stack.isEmpty())
                {
                    r=(Node)stack.peek();
                    if(r.rchild==null || r.rchild==q)
                    {
                        System.out.print(r.data+" ");
                        stack.pop();
                        q=r;
                        flag=true;
                    }
                    else
                    {
                        stack.push(r.rchild);
                        flag=false;
                    }
                    if(!flag)
                        break;
                }
            }
        }
    }

    //层次遍历
    public void levelTraverse()
    {
        Node r=root;
        if(r!=null)
        {
            ArrayDeque deque=new ArrayDeque();
            deque.offer(r);
            while (!deque.isEmpty())
            {
                r=(Node)deque.poll();
                System.out.print(r.data+" ");
                if(r.lchild!=null)
                    deque.offer(r.lchild);
                if(r.rchild!=null)
                    deque.offer(r.rchild);
            }
        }
    }

    //判断两棵树是否相等
    public boolean isEqual(Node t1, Node t2)
    {
        if(t1==null && t2==null)
            return true;
        if(t1!=null && t2!=null)
        {
            if(t1.data.equals(t2.data))
            {
                if(isEqual(t1.lchild, t2.rchild))
                {
                    if(isEqual(t1.rchild, t2.rchild))
                    {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    //打印树
    public void printTree(Node r)
    {
        if(r==null)
            return;
        else  if(r.lchild==null && r.rchild==null)
            System.out.print(r.data);
        else
        {
            System.out.print(r.data +"(");
            printTree(r.lchild);
            System.out.print(",");
            printTree(r.rchild);
            System.out.print(")");
        }
    }

    //例子建立二叉树
    public static BinTree createBinTree()
    {
        Node d=new Node('D');
        Node g=new Node('G');
        Node h=new Node('H');
        Node e=new Node('E', g,null);
        Node f=new Node('F',null, h);
        Node b=new Node('B', d, e);
        Node c=new Node('C', f, null);
        Node a=new Node('A', b, c);
        return new BinTree(a);
    }
    //顺序建立二叉树
    public static Node createBinTree(String seqStr,int i)
    {
        Node r=null;
        if(i<seqStr.length())
        {
            char c=seqStr.charAt(i);
            if(c!='#')
            {
                r = new Node(c);
                r.lchild = createBinTree(seqStr, 2 * i + 1);
                r.rchild = createBinTree(seqStr, 2 * i + 2);
            }
        }
        return r;
    }

    public static void main(String[] args)
    {
        /*建立二叉树(例子)
        BinTree tree=BinTree.createBinTree();
        */
        /*顺序建立二叉树
        String preStr="ABCDEF###G##H";
        Node r=BinTree.createBinTree(preStr,0);
        BinTree tree=new BinTree(r);
        */
        String preStr="ABD##EG###CF#H###";  //根据字符串先序建立二叉树
        BinTree tree=new BinTree(preStr);
        Node r=tree.getRoot();   //获取根节点

        System.out.println("例子: A(B(D,E(G,)),C(F(,H),))");
        System.out.println("根节点:"+tree.getRoot().data);
        char c='B';
        Node currNode=tree.searchNode(r,c);
        Node currParentNode=tree.getParent(currNode,r);
        Node currLchildNode=tree.getLchild(currNode);
        Node currRchildNode=tree.getRchild(currNode);
        System.out.print("B所在结点:"+currNode.data+",  ");
        System.out.print("B的父节点结点:"+currParentNode.data+",  ");
        System.out.print("B的左结点:"+currLchildNode.data+",    ");
        System.out.print("B的右结点:"+currRchildNode.data);
        System.out.println();

        System.out.println("树高: "+tree.getDepth(r));
        System.out.println("树结点总个数: "+tree.countNode(r));

        System.out.print("先序遍历(递归):  ");
        tree.preRootTraverse(r);
        System.out.println();
        System.out.print("先序遍历(非递归):");
        tree.preRootTraverse();
        System.out.println();

        System.out.print("中序遍历(递归):  ");
        tree.inRootTraverse(r);
        System.out.println();
        System.out.print("中序遍历(非递归):");
        tree.inRootTraverse();
        System.out.println();

        System.out.print("后序遍历(递归):  ");
        tree.postRootTraverse(r);
        System.out.println();
        System.out.print("后序遍历(非递归):");
        tree.postRootTraverse();
        System.out.println();

        System.out.print("层序遍历(递归):  ");
        tree.levelTraverse();
        System.out.println();

        System.out.print("打印树:  ");
        tree.printTree(r);
        System.out.println();
    }
}
 运行结果:

 

好不容易整完了,有点费时间,不过整理完后关于二叉树的东西都有条有序清晰起来,也方便过后回忆。

加油!(凡星逝水2018!)





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值