【数据结构】——创建二叉树,以及二叉树的遍历

 如何创建一颗二叉树?

  • 先创建一个根结点
  • 通过这个根结点,创建它的左节点和右节点
  • 再为它的左节点和右节点分别创建左节点和右节点
  • 依次递归

创建一颗静态的二叉树

就是我们直接创建结点,为结点赋值,然后将结点连接起来,就形成了一颗二叉树

首先,创建一个结点类

  • 一个结点的信息包括:结点的值、它的左结点、它的右结点

在结点类中实现两个方法

  • 设置左节点:传入一个结点参数,将传入的结点设置为当前结点的左节点
  • 设置右节点:传入一个结点参数,将传入的结点设置为当前结点的右节点
package tree;

/**
 * 创建一个结点
 */
class Node {

    // 结点的权
    int value;
    // 左结点
    Node leftNode;
    // 右节点
    Node rightNode;

    Node(int value) {
        this.value = value;
    }

    // 设置左结点
    void setLeftNode(Node leftNode) {
        this.leftNode = leftNode;
    }
    // 设置右节点
    void setRightNode(Node rightNode) {
        this.rightNode = rightNode;
    }
}

然后再创建一颗二叉树,创建过程就是

  • 创建一个根结点、一个左节点、一个右节点
  • (此时这三个结点除了值不同外,都是一样的)
  • 然后将左右结点设置为根结点的左右结点
  • (此时已将这三个结点连接起来,形成了一颗二叉树)
package tree;

/**
 * 静态创建二叉树
 */
public class StaticBinaryTree {
    private void createBinaryTree() {
        // 创建一个结点
        Node root = new Node(0);
        // 创建其它结点
        Node left = new Node(1);
        Node right = new Node(2);
        // 将其设置为根结点的左节点和右节点
        root.setLeftNode(left);
        root.setRightNode(right);
    }
    public static void main(String[] args) {
        StaticBinaryTree tree = new StaticBinaryTree();
        tree.createBinaryTree();
    }
}

 这样,一颗简单的二叉树就创建好了

它的根结点的值为0,左节点值为1,右节点值为2,每个结点都是我们一个一个创建的,所以才称为静态创建

而我们使用递归的方式,则可实现动态创建二叉树

创建一颗满二叉树

  • 根据指定层数,创建一个满二叉树,按层来依次来分配结点的值
  • 并实现四种方式遍历二叉树(下面讲解)

同样,还是先创建一个结点类,和上面的一样,创建一次即可

package tree;

/**
 * 创建一个结点
 */
class Node {

    // 结点的权
    int value;
    // 左结点
    Node leftNode;
    // 右节点
    Node rightNode;

    Node(int value) {
        this.value = value;
    }

    // 设置左结点
    void setLeftNode(Node leftNode) {
        this.leftNode = leftNode;
    }
    // 设置右节点
    void setRightNode(Node rightNode) {
        this.rightNode = rightNode;
    }
}

 创建一颗满二叉树

  • 根据构造方法中传入:根结点和二叉树的深度
  • 一个结点的序号为 i ,则它的左节点为(2 * i + 1),右节点为(2 * i + 2)
  • 递归创建,即当我们为根结点创建左右结点后,再为分别左右节点再创建左右结点,依次递归,直到指定深度
package tree;

import java.util.LinkedList;
import java.util.Queue;

public class CreateBinaryTree {
    private Node root;
    private int depth;

    // 构造方法,初始化根结点和二叉树的深度
    private CreateBinaryTree(Node root, int depth) {
        this.root = root;
        this.depth = depth;
    }

    // 递归创建满二叉树
    private void fullBinaryTree(int currentDepth, Node root, int index) {
        if (currentDepth > depth) {
            return;
        }
        // 创建左节点
        Node leftNode = new Node(2 * index + 1);
        root.setLeftNode(leftNode);

        // 创建右节点
        Node rightNode = new Node(2 * index + 2);
        root.setRightNode(rightNode);

        // 递归,分别以左右结点,再创建
        fullBinaryTree(currentDepth + 1, leftNode, 2 * index + 1);
        fullBinaryTree(currentDepth + 1, rightNode, 2 * index + 2);
    }

    // 先序遍历
    private void preorderTraversal(Node node) {
        if (node == null) {
            return;
        }
        System.out.print(node.value + " ");
        preorderTraversal(node.leftNode);
        preorderTraversal(node.rightNode);
    }
    // 中序遍历
    private void inorderTraversal(Node node) {
        if (node == null) {
            return;
        }
        inorderTraversal(node.leftNode);
        System.out.print(node.value + " ");
        inorderTraversal(node.rightNode);
    }
    // 后序遍历
    private void postorderTraversal(Node node) {
        if (node == null) {
            return;
        }
        postorderTraversal(node.leftNode);
        postorderTraversal(node.rightNode);
        System.out.print(node.value + " ");
    }
    // 层次遍历
    private void levelTraversal(Node node) {
        if (node == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            Node treeNode = queue.poll();
            System.out.print(treeNode.value + " ");
            if (treeNode.leftNode != null) {
                queue.offer(treeNode.leftNode);
            }
            if (treeNode.rightNode != null) {
                queue.offer(treeNode.rightNode);
            }
        }
    }

    public static void main(String[] args) {
        // 创建根结点
        Node root = new Node(0);
        // 初始化
        CreateBinaryTree tree = new CreateBinaryTree(root, 3);
        // 创建二叉树
        tree.fullBinaryTree(0, root, 0);
        // 遍历
        System.out.print("先序遍历:");
        tree.preorderTraversal(root);
        System.out.println();
        System.out.print("中序遍历:");
        tree.inorderTraversal(root);
        System.out.println();
        System.out.print("后序遍历:");
        tree.postorderTraversal(root);
        System.out.println();
        System.out.print("层次遍历:");
        tree.levelTraversal(root);
    }
}

上述代码在创建完二叉树之后,以四种遍历方式遍历二叉树,输出结果如下 

 

遍历二叉树

  • 就是打印结点的顺序不同

先序遍历:根结点 ---> 左子树 ---> 右子树

中序遍历:左子树 ---> 根结点 ---> 右子树

后序遍历:左子树 ---> 右子树 ---> 根结点

层次遍历:按层数依次遍历每个结点

先序遍历

    private void preorderTraversal(Node node) {
        if (node == null) {
            return;
        }
        System.out.print(node.value + " ");
        preorderTraversal(node.leftNode);
        preorderTraversal(node.rightNode);
    }

中序遍历

    private void inorderTraversal(Node node) {
        if (node == null) {
            return;
        }
        inorderTraversal(node.leftNode);
        System.out.print(node.value + " ");
        inorderTraversal(node.rightNode);
    }

后序遍历

    private void postorderTraversal(Node node) {
        if (node == null) {
            return;
        }
        postorderTraversal(node.leftNode);
        postorderTraversal(node.rightNode);
        System.out.print(node.value + " ");
    }

层次遍历

在此,我们需要一个队列,将当前层的结点存入队列,然后遍历队列中的每个结点

在遍历队列中每个结点的时候,再判断它们的子节点,如果有子节点,则放入队列的末尾,等这一层的结点都遍历完成后,才可遍历它们的子节点,这样既可实现层次遍历

    private void levelTraversal(Node node) {
        if (node == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            Node treeNode = queue.poll();
            System.out.print(treeNode.value + " ");
            if (treeNode.leftNode != null) {
                queue.offer(treeNode.leftNode);
            }
            if (treeNode.rightNode != null) {
                queue.offer(treeNode.rightNode);
            }
        }
    }

对比链表和二叉树:链表中的结点只有一个后继结点,而二叉树的结点有两个后继结点(子节点)

发布了34 篇原创文章 · 获赞 20 · 访问量 6974

猜你喜欢

转载自blog.csdn.net/weixin_42193813/article/details/105351928