二叉树的遍历(递归与非递归实现)

二叉树的遍历(递归与非递归实现)

二叉树的实现(三叉链表的形式)

public class XieChaoThreeLinkBinTree<E> {
    public static class TreeNode<T>
    {
        T data;
        TreeNode<T> left;
        TreeNode<T> right;
        TreeNode<T> parent;

        public TreeNode(){ }
        public TreeNode(T data)
        {
            this.data=data;
        }

        public TreeNode(T data, TreeNode<T> left, TreeNode<T> right, TreeNode<T> parent) {
            this.data = data;
            this.left = left;
            this.right = right;
            this.parent = parent;
        }

        public TreeNode(T data, TreeNode<T> left, TreeNode<T> right)
        {
            this.data=data;
            this.left=left;
            this.right=right;

        }

    }

    TreeNode<E> root;

    public XieChaoThreeLinkBinTree(){
        root= new TreeNode<E>();
    }
    public XieChaoThreeLinkBinTree(E data)
    {
        this.root=new TreeNode<>(data);
    }
    public XieChaoThreeLinkBinTree(TreeNode<E> root){
        this.root=root;
    }

    public TreeNode<E> addTreeNode(TreeNode<E> parent,E data, boolean isLeft) {
        if (null == parent)
            throw new RuntimeException("节点为空,无法插入子节点");
        if (isLeft && parent.left != null)
            throw new RuntimeException(parent + "节点已经有了左节点,无法继续插入");
        if (!isLeft && parent.right != null)
            throw new RuntimeException(parent + "节点已有了右节点,无法继续插入");
        TreeNode<E> node=new TreeNode<>(data,null,null,parent);

        if (isLeft)
        {
            parent.left=node;
        }
        else{
            parent.right=node;
        }
        return node;
    }

    public boolean empty()
    {
        return root==null;
    }
    public TreeNode<E> root()
    {

        return this.root;
    }
    public E parent(TreeNode<E>  root)
    {
        if(null == root)
            throw new RuntimeException("节点为null,无法访问其父节点");
        return root.parent.data;
    }
    public E leftChild(TreeNode<E> root)
    {
        if( null == root)
            throw new RuntimeException("节点为空,无法访问其子节点");
        return root.left == null?null:root.left.data;
    }
    public E rightChild(TreeNode<E> root)
    {
        if( null == root)
            throw new RuntimeException("节点为空,无法访问其子节点");
        return root.right == null?null:root.right.data;
    }

    public int deep()
    {
        return deep(root);
    }

    private int deep(TreeNode<E> root) {
        if(null == root )
            return 0;
        if(null == root.left && null==root.right)
            return 1;
        return Math.max(deep(root.left),deep(root.right))+1;
    }
   }

一.递归
前序遍历:

 public void PreOrderTraverse(TreeNode<E> root){
        if(null == root)
            return;
        System.out.print(root.data+"  ");
        PreOrderTraverse(root.left);
        PreOrderTraverse(root.right);
    }

中序遍历:

  public void InOrderTraverse(TreeNode<E> root)
    {
        if(null == root)
            return;
        InOrderTraverse(root.left);
        System.out.print(root.data+"   ");
        InOrderTraverse(root.right);
    }

后续遍历:

if(null == root)
            return;
        PostOrderTraverse(root.left);
        PostOrderTraverse(root.right);
        System.out.print(root.data+"  ");

非递归方式:
1.前序遍历(深度优先遍历):借助栈,右孩子先于左孩子入栈,后语左孩子出栈。

public void PreOrderTraverseByStack(TreeNode<E> root)
{
    if( null == root)
        return;
    Stack<TreeNode<E>> stack=new Stack<>();
    stack.push(root);
    while(!stack.empty())
    {
        TreeNode<E> node=stack.pop();
        if(null != node.right)
             stack.push(node.right);
        if(null != node.left)
            stack.push(node.left);
    }
}

2.中序遍历:栈

public void InOrderTraverseByStack(TreeNode<E> root)
    {
        Stack<TreeNode<E>> stack=new Stack<>();
        TreeNode<E> node=root;
        while(!stack.empty()|| null!=node)
        {
           while(null !=node )
           {
               stack.push(node);
               node=node.left;
           }
           if(stack != null)
           {
               node=stack.pop();
               System.out.print(node.data+"   ");
               node=node.right;
           }
        }
    }

3.后序遍历:后序遍历是最难的,也是借助栈。
思路:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一个结点P,先将其入栈,如果P不存在左孩子和右孩子,可以直接访问它。或者P存在左孩子或者右孩子,但其左孩子和右孩子都已经被访问过了(已经出栈了),则同样可以访问此P结点。

总结一下思路:
1)对于任意个结点P,首先需要将其入栈
2)如果P没有左孩子也没有右孩子,或者有左孩子或者右孩子,但是左右孩子已经被输出了,那么就可以把该结点直接进行输出,并将其出栈。将出栈的结点定义为上一个结点(pre=cur),并把当前栈顶的元素重新置为当前结点(cur=s.peek())。
3)如果不满足2)的条件,则将其右孩子左孩子入栈。当前结点重新置为栈顶结点,然后重复2)
4)直至栈顶为空,然后遍历结束。

设计思路:设置两个指针,cur指向当前栈顶节点,为当前节点。
pre为上一个访问的节点,上一个出栈的节点。

  public void PostOrderTraverseByStack(TreeNode<E> root)
    {
        Stack<TreeNode<E>> stack=new Stack<>();
        TreeNode<E> cur;
        TreeNode<E> pre=null;
        stack.push(root);
        while(!stack.empty()){
            cur=stack.peek();
            if((cur.left == null && cur.right ==null)||(pre !=null &&(pre.parent == cur)))
            {
                System.out.print(cur.data+"  ");
                stack.pop();
                pre=cur;
            }else{
                if(null != cur.right)
                    stack.push(cur.right);
                if(null != cur.left)
                    stack.push(cur.left);
            }
        }
    }

4.层序遍历(广度优先遍历):借助队列

public void LayerOrderTraverse(TreeNode<E> root)
    {
       Queue<TreeNode<E>> queue=new LinkedList<TreeNode<E>>();
       if(null !=root){
           queue.offer(root);
       }
        while(!queue.isEmpty())
        {
            TreeNode<String> node= (TreeNode<String>) queue.poll();
            System.out.print(node.data+"  ");
            if(null !=node.left)
               queue.offer((TreeNode<E>) node.left);
            if(null !=node.right)
                queue.offer((TreeNode<E>) node.right);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值