二叉树的创立和简单操作

节点类

//静态内部节点类
private static class Node{
        Object data;//存放数据
        
        Node left;//左孩子
        Node right;//右孩子

        public Node(Object data){
            this.data = data;
        }
    }

建立二叉树

public Node createTree(Object[] objects){
        System.out.println(objects);
        for(Object object : objects)
            list.add(new Node(object));
        for(int parentIndex = 0; parentIndex < objects.length /2 - 1; parentIndex++){
            list.get(parentIndex).left = list.get(2 * parentIndex + 1);
            list.get(parentIndex).right = list.get(2 * parentIndex + 2);
        }
        //对最后节点的父节点进行单独设置,若元素个数为奇数,则可以构建右孩子,否则不能构建
        int lastParentIndex = objects.length / 2 - 1;//objects.length>>1 - 1
        list.get(lastParentIndex).left = list.get(2 * lastParentIndex + 1);
        if(objects.length % 2 == 1){
            list.get(lastParentIndex).right = list.get(2 * lastParentIndex + 2);
        }
        root = list.get(0);
        return root;
    }

递归实现三种遍历

    //前序递归遍历
    public void preOrder(Node root){
        if(root != null){
            System.out.print(root.data + " ");
            preOrder(root.left);
            preOrder(root.right);
        }
    }
    
    //中序递归遍历
    public void inOrder(Node root){
        if(root != null){
            inOrder(root.left);
            System.out.print(root.data + " ");
            inOrder(root.right);
        }
    }
    
    //后序递归遍历
    public void postOrder(Node root){
        if(root != null){
            postOrder(root.left);
            postOrder(root.right);
            System.out.print(root.data + " ");
        }
    }

非递归实现三种遍历

//前序非递归遍历
    public void preOrderByStack(Node root){
        if(root == null)
            return;
        Stack<Node> stack = new Stack<>();//建立辅助栈
        Node temp = root;
        while (temp != null || !stack.isEmpty()){
            while (temp != null){
                System.out.print(temp.data + " ");//先序遍历时先打印当前节点值
                stack.push(temp);
                temp = temp.left;
            }
            //依次出栈,若当前节点的右子树不为空,则将当前引用指向右节点,重新进行上一步循环
            if (!stack.isEmpty()){
                temp = stack.pop();
                temp = temp.right;
            }
        }
    }
    
    //中序非递归遍历
    public void inOrderByStack(Node root){
    	if(root == null)
    		return;
        Node temp = root;
        Stack<Node> stack = new Stack<>();
        while (temp != null || !stack.isEmpty()){
            while (temp != null){
                stack.push(temp);
                temp = temp.left;
            }
            if(!stack.isEmpty()){
                temp = stack.pop();
                System.out.print(temp.data + " ");
                temp = temp.right;
            }
        }
    }
    
   //后序非递归遍历
    public void postOrderByStack(Node root){
        if(root == null)
            return;
        Stack<Node> stack = new Stack<>();
        stack.push(root);
        Node cur = null, pre = null;
        while (!stack.isEmpty()){
            cur = stack.peek();
            /**
             * 1.当前节点是根节点
             * 2.当前节点是上一个处理节点的左孩子或右孩子
             * 上述两种情况代表正在从二叉树的根节点寻找到左子树的最深的那个节点(左子树优先寻找)
             */
            if(pre == null || pre.left == cur || pre.right == cur){
                //当前节点左子树存在,则将它的左孩子加入
                if(cur.left != null)
                    stack.push(cur.left);
                //否则左子树不存在,应该从它的右子树找最深的那个节点
                else if(cur.right != null)
                    stack.push(cur.right);
            }
            /**
             * 前一个处理节点是当前节点的左节点,如果当前节点的右节点还不为空,则需要进行右子树的处理
             * 需要对右孩子进行上一步判定
             */
            else if(cur.left == pre){
                if(cur.right != null)
                    stack.push(cur.right);
            }
            /**
             * 剩下的情况包括:
             * 1.当前节点是叶子节点,在叶子节点的父亲将它加入堆栈中后,第一遍循环时进入第一个条件,但是什么也没做,
             * 只是将前一个处理节点变成了叶子节点,于是第二遍循环直接打印叶子节点的值
             * 2.前一个处理节点是当前节点的右孩子,说明当前节点的右子树已经处理完了,可以直接打印当前节点的值,若前一个处理节点
             * 是当前节点的左孩子,则需要进入上一个条件进行处理,若右子树不存在,则会进行对这个节点的第二遍循环,就会
             * 直接打印这个节点的值
             */
            else{
                System.out.print(cur.val + " ");
                stack.pop();
            }
            //将当前节点设置为前一个处理节点
            pre = cur;
        }
    }

获取树的深度

//递归获取树的深度
    public int getDepth(Node root){
        if(root == null)
            return 0;
        int lDeep = getDepth(root.left);
        int rDeep = getDepth(root.right);
        return lDeep > rDeep ? lDeep + 1 : rDeep + 1;

    }
    
    //非递归获取树的深度
    public int getDepthByQueue(Node root){
       if(root == null)
           return 0;
        Queue<Node> queue = new LinkedList<>();
        Node current = null;
        queue.offer(root);
        int cur, last;
        int level = 0;
        while (!queue.isEmpty()){
            cur = 0;
            last = queue.size(); //记录当前层需要遍历的节点个数
            while (cur < last){
                current = queue.poll();
                cur++;
                //当前节点的左右节点不为空的加入队列,等待下一层遍历
                if(current.left != null)
                    queue.offer(current.left);
                if(current.right != null)
                    queue.offer(current.right);
            }
            level++;//每遍历一遍层数加一
        }
        return level;
    }

层序遍历

//层序遍历
    //利用队列先进先出的特点依次将每一层的每一个节点的左右子节点加入队列,可以保持每一层输出的顺序
    public void floorTravel(Node root){
        Queue<Node> queue = new LinkedList<>();
        queue.offer(root);
        Node temp = null;
        while (!queue.isEmpty()){
            temp = queue.peek();
            //将当前节点的左右孩子依次加入队列
            if(temp.left != null)
                queue.offer(temp.left);
            if(temp.right != null)
                queue.offer(temp.right);
            System.out.print(queue.poll().data + " ");
        }
    }

交换每个节点的左右孩子

//递归实现交换子节点
    public void exchangeChild(Node root){
        if(root != null){
            Node temp = root.left;
            root.left = root.right;
            root.right = temp;

            exchangeChild(root.left);
            exchangeChild(root.right);
        }
    }

    //非递归实现交换左右子树
    public void exchangeChildByQueue(Node root){
        Queue<Node> queue = new LinkedList<>();
        queue.offer(root);
        Node temp;
        while (!queue.isEmpty()){
            Node left = null;
            Node right = null;
            temp = queue.poll();
            //将存在的孩子节点加入队列进行下一层的交换
            if(temp.left != null){
                left = temp.left;
                queue.offer(left);
            }
            if(temp.right != null){
                right = temp.right;
                queue.offer(right);
            }
            temp.left = right;
            temp.right = left;
        }
    }
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值