树系列之二叉树非递归实现遍历、序列号反序列化

     大学里面学习过的树,现在都快忘没了。打算整理一个系列关于树的知识结构,并用java代码加以实现,这个系列会包含二叉树、平衡二叉树、B-树、B+树、红黑树。

1.二叉树的定义

    参考https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%8F%89%E6%A0%91(注意区别二叉树、满二叉树、完全二叉树)

2.二叉树的数据结构

@Data
public class Node {
    private int val;
    private Node left;
    private Node right;
}

3.二叉树的基本操作

3.1 遍历:递归算法很好写,这里就不赘述,非递归实现树的先序遍历,中序遍历,后序遍历(todo),层次遍历

小感悟:树的层次遍历很重要,判断二叉树是否是completeBinaryTree、fullBinaryTree,查看树的度数,节点总数都有用到此方法。

代码实现如下:

 //二叉树遍历 先序遍历
    private List proRootTraverse(Node treeNode) {

        List proRootTraverseArray = new ArrayList<>(0);

        Stack stack = new Stack<>();

        while (!stack.isEmpty() || treeNode != null) {

            if (treeNode != null) {
                proRootTraverseArray.add(treeNode.getVal());

                stack.add(treeNode);

                treeNode = treeNode.getLeft();
            } else {

                Node node = stack.pop();

                treeNode = node.getRight();
            }
        }

        return proRootTraverseArray;
    }
//二叉树遍历 中序遍历
    private List midleRootTraverse(Node treeNode) {

        List midleRootTraverseArray = new ArrayList<>(0);

        Stack stack = new Stack<>();

        while (!stack.isEmpty() || treeNode != null) {

            if (treeNode != null) {

                stack.push(treeNode);
                treeNode = treeNode.getLeft();
            } else {

                Node node = stack.pop();

                midleRootTraverseArray.add(node.getVal());

                treeNode = node.getRight();
            }
        }

        return midleRootTraverseArray;
    }

//层次遍历不打印空节点,每一层换行分离
    private void levelRootTraverse(Node treeNode) {

        Node last = treeNode;
        Node nLast = treeNode;

        LinkedList queue = new LinkedList<>();

        queue.offer(treeNode);
        while (!queue.isEmpty()) {

            Node node = queue.poll();
            System.out.print(node.getVal()+" ");

            if (node.getLeft() != null) {
                queue.offer(node.getLeft());
                nLast = node.getLeft();
            }

            if (node.getRight() != null) {
                queue.offer(node.getRight());
                nLast = node.getRight();
            }

            if (node.equals(last)) {
                System.out.print("\n");
                last = nLast;
            }
        }
    }
 //层次遍历打印出空节点,每一层换行分离
    private void levelRootTraverseWithNull(Node treeNode) {

        int parentSize = 1;
        int childSize = 0;

        LinkedList queue = new LinkedList<>();

        queue.offer(treeNode);
        while (!queue.isEmpty()) {

            Node node = queue.poll();

            System.out.print(node == null ? "null ": node.getVal()+" ");

            if (node != null) {
                queue.offer(node.getLeft());
                queue.offer(node.getRight());
            }

            childSize = childSize +2;
            parentSize --;

            if (parentSize == 0) {
                System.out.print("\n");
                parentSize = childSize;
                childSize = 0;
            }
        }
    }

3.2 判断一棵树是否是完全二叉树,满二叉树

//判断是否是完全二叉树,完全二叉树除最后一层外,其他层都是满的
    private boolean isCompleteBinaryTree(Node treeNode) {

        LinkedList queue = new LinkedList<>();

        queue.push(treeNode);

        while (queue.peek() != null) {

            Node node = queue.pop();
            queue.offer(node.getLeft());
            queue.offer(node.getRight());
        }

        while (!queue.isEmpty() && queue.size() > 0) {

            Node node = queue.pop();

            if (node != null) {
                return false;
            }
        }

        return true;
    }

//判断是否是满二叉树 每一层都是满的 节点数=2^(n-1)
    private boolean isFullBinaryTree(Node treeNode) {

        LinkedList queue = new LinkedList<>();
        queue.offer(treeNode);

        int deep = 0;

        int parentPosition = 1;

        int childPosition = 0;

        int levelNodeNum = 0;


        while (!queue.isEmpty()) {
            Node node = queue.pop();
            parentPosition --;
            levelNodeNum ++;

            if (node.getLeft() != null) {
                queue.offer(node.getLeft());
                childPosition ++;
            }
            if (node.getRight() != null) {
                queue.offer(node.getRight());
                childPosition ++;
            }

            if (parentPosition == 0) {

                if (levelNodeNum != (int)Math.pow(2,deep)) {
                    return false;
                }

                levelNodeNum = 0;
                deep ++;
                parentPosition = childPosition;
                childPosition =0;
            }
        }

        return true;
    }

3.3 序列号反序列化,序列号与树的遍历方式一致,反序列化实现todo

4.高频bat算法面试题

树系列之二叉树非递归实现遍历、序列号反序列化_第1张图片

树系列之二叉树非递归实现遍历、序列号反序列化_第2张图片



你可能感兴趣的:(数据结构)