data structure and algorithms

二叉树

2020-01-12  本文已影响0人  spraysss

二叉树每个节点最多有两个子树,并且子树有左右之分,其次序不能任意颠倒

java 实现二叉树

public class BinaryTree {

    private BiNode root;

    public BinaryTree(BiNode root) {
        this.root = root;
    }
    static class BiNode {

        char data;
        BiNode left;
        BiNode right;

        public BiNode(char data) {
            this.data = data;
        }
    }

遍历二叉树

二叉树的遍历可以使用递归的算法实习,也可以使用非递归的算法实现

递归遍历

递归遍历算法比较简单直接按照定义递归即可,代码如下:

/**
     * Recursive implementation of preOrder traversal
     */

    public void perOrderTraverseRecursive() {
        System.out.println("perOrderTraverseRecursive:");
        perOrderTraverseRecursive(root);
        System.out.println();
    }

    private void perOrderTraverseRecursive(BiNode node) {
        if (node != null) {
            visit(node);
            perOrderTraverseRecursive(node.left);
            perOrderTraverseRecursive(node.right);
        }
    }

    /**
     * Recursive implementation of inOrder traversal
     */

    public void inOrderTraverseRecursive() {
        System.out.println("inOrderTraverseRecursive:");
        inOrderTraverseRecursive(root);
        System.out.println();
    }

    private void inOrderTraverseRecursive(BiNode node) {

        if (node != null) {
            inOrderTraverseRecursive(node.left);
            visit(node);
            inOrderTraverseRecursive(node.right);
        }
    }


    /**
     * Recursive implementation of postOrder traversal
     */
    public void postOrderTraverseRecursive() {
        System.out.println("postOrderTraverseRecursive:");
        postOrderTraverseRecursive(root);
        System.out.println();
    }

    private void postOrderTraverseRecursive(BiNode node) {
        if (node != null) {
            postOrderTraverseRecursive(node.left);
            postOrderTraverseRecursive(node.right);
            visit(node);
        }

    }
非递归的遍历算法

非递归的遍历算法使用Stack实现,其中前序遍历和中序遍历相对来说比较简单,结构也类似
代码如下:

/**
     * Stack implementation of preOrder traversal
     */

    public void preOrderTraverse() {
        System.out.println("preOrder Traverse use Stack:");
        Stack<BiNode> nodeStack = new Stack<>();
        BiNode node = root;
        while (!nodeStack.isEmpty() || node != null) {
            while (node != null) {
                visit(node);
                nodeStack.push(node);
                node = node.left;

            }
            if (!nodeStack.isEmpty()) {
                node = nodeStack.pop();
                node = node.right;
            }
        }
        System.out.println();
    }

    /**
     * Stack implementation of inOrder traversal
     */

    public void inOrderTraverse() {

        System.out.println("inOrder Traverse use Stack:");
        Stack<BiNode> nodeStack = new Stack<>();
        BiNode node = root;
        while (!nodeStack.isEmpty() || node != null) {
            while (node != null) {
                nodeStack.push(node);
                node = node.left;

            }
            if (!nodeStack.isEmpty()) {
                node = nodeStack.pop();
                visit(node); //访问根结点
                node = node.right;
            }
        }
        System.out.println();
    }

后序遍历的非递归算法麻烦一点,如下给出了后序遍历的两个实现,其中第一个使用一个栈完成,但是逻辑看起来复杂一些,后一个使用两个栈完成,逻辑看起来比较简洁

/**
     * Stack implementation of postOrder traversal
     */
    public void postOrderTraverse() {
        System.out.println("postOrder Traverse use Stack:");
        BiNode node = root;
        if (node != null) {
            Stack<BiNode> stack = new Stack<>();
            stack.push(node);
            BiNode c;
            while (!stack.isEmpty()) {
                c = stack.peek();
                if (c.left != null && node != c.left && node != c.right) {
                    stack.push(c.left);
                } else if (c.right != null && node != c.right) {
                    stack.push(c.right);
                } else {
                    visit(stack.pop());
                    node = c;
                }
            }
        }
        System.out.println();
    }

    /**
     * Double Stack implementation of postOrder traversal
     */
    public void postOrderTraverseWithDoubleStack() {
        System.out.println("postOrderTraverse use Double Stack:");
        BiNode node = root;
        if (node != null) {
            Stack<BiNode> s1 = new Stack<>();
            Stack<BiNode> s2 = new Stack<>();
            s1.push(root);
            while (!s1.isEmpty()) {
                node = s1.pop();
                s2.push(node);
                if (node.left != null) {
                    s1.push(node.left);
                }
                if (node.right != null) {
                    s1.push(node.right);
                }
            }
            while (!s2.isEmpty()) {
                visit(s2.pop());
            }
        }

        System.out.println();
    }

创建二叉树

我们根据先序遍历的字符串创建二叉树,使用#表示空指针

比如AB##DE##C#F## 会创建如下一个二叉树:

二叉树创建的代码如下:

 /**
     * @param s preOrder string represent of Binary Tree, # mean nil
     * @return Binary Tree construct by the preOrder string
     */
    public static BinaryTree createBiTree(String s) {
        System.out.println("createBiTree with preOrder String : " + s);
        i = 0;
        return new BinaryTree(BinaryTree.createBiTreeNode(s));
    }


    private static BiNode createBiTreeNode(String s) {
        BiNode node = null;
        if (s.charAt(i) != '#') {// char is not #, do recursion
            node = new BiNode(s.charAt(i));
            i++; // when successful create a BiNode ,increase string index
            node.left = createBiTreeNode(s);
            node.right = createBiTreeNode(s);


        } else {// Character # encountered, increase  string index
            i++;
        }
        return node;

    }

创建二叉树并测试

 public static void main(String[] args) {
        BinaryTree binaryTree = createBiTree("AB##DE##C#F##");
        binaryTree.perOrderTraverseRecursive();
        binaryTree.inOrderTraverseRecursive();
        binaryTree.postOrderTraverseRecursive();
        binaryTree.preOrderTraverse();
        binaryTree.inOrderTraverse();
        binaryTree.postOrderTraverse();
        binaryTree.postOrderTraverseWithDoubleStack();
    }

测试结果

createBiTree with preOrder String : AB##DE##C#F##
perOrderTraverseRecursive:
A B D E C F 
inOrderTraverseRecursive:
B A E D C F 
postOrderTraverseRecursive:
B E F C D A 
preOrder Traverse use Stack:
A B D E C F 
inOrder Traverse use Stack:
B A E D C F 
postOrder Traverse use Stack:
B E F C D A 
postOrderTraverse use Double Stack:
B E F C D A 

完整代码地址

https://github.com/spraysss/data-structure/blob/master/src/main/java/com/ds/tree/BinaryTree.java

上一篇下一篇

猜你喜欢

热点阅读