【二叉树】基本概念和遍历

二叉树是一种非常重要的数据结构,其在查找、排序等领域有着非常重要的应用。本文简单介绍一些关于二叉树的基本概念,并给出几种二叉树的基本遍历方法。全文代码为Java语言实现。

二叉树的基本概念
1. 二叉树的定义

定义: 二叉树是n(n >= 0)个节点所构成的集合,n=0为空树,n>0是非空树。

  • 有且仅有一个根节点
  • 二叉树的度为小于等于2,即一个父节点最多只会有两个子节点
  • 二叉树天生具有递归的特性
  • 二叉树的子树有左右之分,其次序不能颠倒
2. 二叉树的性质
  • 二叉树的第i层上最多有 2^(i-1) 个节点
  • 深度为k的二叉树最多有 2^k - 1 个节点

二叉树的两种特殊形态:

  • 满二叉树

image

特点: 深度为k且含有2^k - 1 个节点的树

  • 完全二叉树

image

特性:具有n个节点的完全二叉树的深度为 |log2N| + 1

二叉树的构造与遍历
1. 二叉树的构造

在Java中,一个节点可以用一个类来描述,其三个成员变量分别为:数据域(value)、指向左子树节点的引用(left)、指向右子树节点的引用(right)

构造节点的代码实现:

/**
 * 二叉树节点
 */
private static class TreeNode {
    // 数据域
    private String value;
    // 指向左子树的引用
    private TreeNode left;
    // 指向右子树的引用
    private TreeNode right;

    public TreeNode(String value, TreeNode left, TreeNode right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public TreeNode getLeft() {
        return left;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }
}
2. 二叉树的遍历

二叉树遍历的三种方式如下:

(1) 先序遍历:根节点->左子树->右子树

下面是两种实现方式:递归实现和非递归实现

/**
 * 递归实现 先序遍历:根节点->左子树->右子树
 * 1. 访问根节点
 * 2. 先序遍历左子树
 * 3. 先序遍历右子树
 */
private void preOrderR(TreeNode node) {
    if (node != null) {
        // 1. 访问根节点
        System.out.print(node.getValue() + " ");
        // 2. 先序遍历左子树
        preOrderR(node.getLeft());
        // 3. 先序遍历右子树
        preOrderR(node.getRight());
    }
}

/**
 * 非递归实现 先序遍历
 */
private void preOrder() {
    Stack<TreeNode> stack = new Stack<TreeNode>();
    stack.push(root);
    TreeNode current = null;
    while (!stack.isEmpty()) {
        current = stack.pop();
        System.out.print(current.getValue() + " ");
        if (current.getRight() != null) {
            stack.push(current.getRight());
        }
        if (current.getLeft() != null) {
            stack.push(current.getLeft());
        }
    }
    System.out.println();
}

(2) 中序遍历:左子树->根节点->右子树

下面是两种实现方式:递归实现和非递归实现

/**
 * 递归实现 中序遍历:左子树->根节点->右子树
 * 1. 中序遍历左子树
 * 2. 访问根节点
 * 3. 中序遍历右子树
 */
private void inOrderR(TreeNode node) {
    if (node != null) {
        // 1. 中序遍历左子树
        inOrderR(node.getLeft());
        // 2. 访问根节点
        System.out.print(node.getValue() + " ");
        // 3. 中序遍历右子树
        inOrderR(node.getRight());
    }
}

/**
 * 非递归实现 中序遍历
 */
private void inOrder() {
    Stack<TreeNode> stack = new Stack<TreeNode>();
    TreeNode current = root;
    while (current != null || !stack.isEmpty()) {
        while (current != null) {
            stack.push(current);
            current = current.getLeft();
        }
        if (!stack.isEmpty()) {
            current = stack.pop();
            System.out.print(current.getValue() + " ");
            current = current.getRight();
        }
    }
    System.out.println();
}

(3) 后续遍历:左子树->右子树->根节点

下面是两种实现方式:递归实现和非递归实现

/**
 * 递归实现 后序遍历:左子树->右子树->根节点
 * 1. 后续遍历左子树
 * 2. 后续遍历右子树
 * 3. 访问根节点
 */
private void lastOrderR(TreeNode node) {
    if (node != null) {
        // 1. 后序遍历左子树
        lastOrderR(node.getLeft());
        // 2. 后序遍历右子树
        lastOrderR(node.getRight());
        // 3. 访问根节点
        System.out.print(node.getValue() + " ");
    }
}

/**
 * 非递归实现 后续遍历
 */
private void lastOrder() {
    TreeNode rNode = null;
    TreeNode current = root;
    Stack<TreeNode> stack = new Stack<TreeNode>();
    while (current != null || !stack.isEmpty()) {
        while (current != null) {
            stack.push(current);
            current = current.getLeft();
        }
        current = stack.pop();
        while (current != null && (current.getRight()) == null || current.getRight() == rNode) {
            System.out.print(current.getValue() + " ");
            rNode = current;
            if (stack.isEmpty()) {
                System.out.println();
                return;
            }
            current = stack.pop();
        }
        stack.push(current);
        current = current.getRight();
    }
}

(4) 验证结果

下面是任意给出的一棵二叉树:

image

验证上面的三种遍历方式:

public class ConstructBinaryTree {
    // 根节点
    private TreeNode root;

    public ConstructBinaryTree(TreeNode root) {
        this.root = root;
    }

    public TreeNode getRoot() {
        return root;
    }

    public void setRoot(TreeNode root) {
        this.root = root;
    }

    public static void main(String[] args) {
        // 第三层节点
        TreeNode l3_1 = new TreeNode("F", null, null);
        TreeNode l3_2 = new TreeNode("G", null, null);
        TreeNode r3 = new TreeNode("H", null, null);
        // 第二层节点
        TreeNode l2 = new TreeNode("E", l3_2, r3);
        TreeNode r2 = new TreeNode("D", l3_1, null);
        // 第一层节点
        TreeNode l1 = new TreeNode("B", null, r2);
        TreeNode r1 = new TreeNode("C", l2, null);
        TreeNode root = new TreeNode("A", l1, r1);

        ConstructBinaryTree cbt = new ConstructBinaryTree(root);

        System.out.println("递归 先序遍历:");
        cbt.preOrderR(cbt.getRoot());
        System.out.println("\n非递归 先序遍历:");
        cbt.preOrder();

        System.out.println("\n递归 中序遍历:");
        cbt.inOrderR(cbt.getRoot());
        System.out.println("\n非递归 中序遍历:");
        cbt.inOrder();

        System.out.println("\n递归 后序遍历:");
        cbt.lastOrderR(cbt.getRoot());
        System.out.println("\n非递归 后序遍历:");
        cbt.lastOrder();
    }
}

结果如下:
递归 先序遍历:
A B D F C E G H 
非递归 先序遍历:
A B D F C E G H 

递归 中序遍历:
B F D A G E H C 
非递归 中序遍历:
B F D A G E H C 

递归 后序遍历:
F D B G H E C A 
非递归 后序遍历:
F D B G H E C A 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值