Java数据结构二叉树难点解析

Java数据结构二叉树难点解析

什么是二叉树

二叉树是一种非常常见的数据结构,它具有以下特点:

  • 每个节点都最多有两个子节点。
  • 左子节点的值小于等于父节点的值,右子节点的值大于等于父节点的值。

二叉树可以用递归的方式实现,如下所示:

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public class BinaryTree {
    public TreeNode root;

    public void insert(int val) {
        root = insert(root, val);
    }

    private TreeNode insert(TreeNode node, int val) {
        if (node == null) {
            return new TreeNode(val);
        }
        if (val < node.val) {
            node.left = insert(node.left, val);
        } else {
            node.right = insert(node.right, val);
        }
        return node;
    }
}

二叉树遍历

二叉树遍历有三种方式:

前序遍历

前序遍历的顺序是:根节点,左子树,右子树。

public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    if (root == null) {
        return result;
    }
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        result.add(node.val);
        if (node.right != null) {
            stack.push(node.right);
        }
        if (node.left != null) {
            stack.push(node.left);
        }
    }
    return result;
}

中序遍历

中序遍历的顺序是:左子树,根节点,右子树。

public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    Stack<TreeNode> stack = new Stack<>();
    TreeNode current = root;
    while (current != null || !stack.isEmpty()) {
        while (current != null) {
            stack.push(current);
            current = current.left;
        }
        current = stack.pop();
        result.add(current.val);
        current = current.right;
    }
    return result;
}

后序遍历

后序遍历的顺序是:左子树,右子树,根节点。

public List<Integer> postorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    if (root == null) {
        return result;
    }
    Stack<TreeNode> stack1 = new Stack<>();
    Stack<TreeNode> stack2 = new Stack<>();
    stack1.push(root);
    while (!stack1.isEmpty()) {
        TreeNode node = stack1.pop();
        stack2.push(node);
        if (node.left != null) {
            stack1.push(node.left);
        }
        if (node.right != null) {
            stack1.push(node.right);
        }
    }
    while (!stack2.isEmpty()) {
        result.add(stack2.pop().val);
    }
    return result;
}

二叉树的应用

二叉树常常被用来实现搜索和排序算法。一个常见的例子是二叉搜索树,它支持快速插入,删除和查找操作,时间复杂度为O(log n)。

例如,我们可以使用二叉搜索树实现一个简单的数据管理系统,该系统支持以下操作:

  • Add(key, value) 将一个key-value对添加到数据管理系统中。
  • Remove(key) 从数据管理系统中删除key-value对。
  • Get(key) 获取key对应的value。

下面是一个用Java实现的二叉搜索树:

class BSTNode {
    int key;
    String value;
    BSTNode left;
    BSTNode right;

    public BSTNode(int key, String value) {
        this.key = key;
        this.value = value;
    }
}

public class BinarySearchTree {
    private BSTNode root;

    public void add(int key, String value) {
        root = add(root, key, value);
    }

    private BSTNode add(BSTNode node, int key, String value) {
        if (node == null) {
            return new BSTNode(key, value);
        }
        if (key < node.key) {
            node.left = add(node.left, key, value);
        } else if (key > node.key) {
            node.right = add(node.right, key, value);
        } else {
            node.value = value;
        }
        return node;
    }

    public void remove(int key) {
        root = remove(root, key);
    }

    private BSTNode remove(BSTNode node, int key) {
        if (node == null) {
            return null;
        }
        if (key < node.key) {
            node.left = remove(node.left, key);
        } else if (key > node.key) {
            node.right = remove(node.right, key);
        } else {
            if (node.left == null) {
                return node.right;
            } else if (node.right == null) {
                return node.left;
            } else {
                BSTNode minNode = findMin(node.right);
                node.key = minNode.key;
                node.value = minNode.value;
                node.right = remove(node.right, minNode.key);
            }
        }
        return node;
    }

    private BSTNode findMin(BSTNode node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    public String get(int key) {
        return get(root, key);
    }

    private String get(BSTNode node, int key) {
        if (node == null) {
            return null;
        }
        if (key < node.key) {
            return get(node.left, key);
        } else if (key > node.key) {
            return get(node.right, key);
        } else {
            return node.value;
        }
    }
}

上述代码中,我们用二叉搜索树来管理key-value对,实现了Add,Remove,Get三个操作。例如,添加一个key-value对:

BinarySearchTree bst = new BinarySearchTree();
bst.add(1, "a");

示例说明

示例1

我们有一个如下图所示的二叉树:

     1
   /   \
  2     3
 / \   / \
4   5 6   7

我们可以使用前序遍历和中序遍历的结果来重建这个二叉树:

  • 前序遍历:1 2 4 5 3 6 7
  • 中序遍历:4 2 5 1 6 3 7

其中,前序遍历的第一个节点是根节点,而中序遍历的根节点在中间。我们可以通过中序遍历找到根节点的位置,分别构建左子树和右子树,递归进行下去即可。

public TreeNode buildTree(int[] preorder, int[] inorder) {
    if (preorder.length == 0 || inorder.length == 0) {
        return null;
    }
    return buildTree(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}

private TreeNode buildTree(int[] preorder, int preStart, int preEnd, int[] inorder, int inStart, int inEnd) {
    if (preStart > preEnd || inStart > inEnd) {
        return null;
    }
    TreeNode root = new TreeNode(preorder[preStart]);
    int inIndex = 0;
    for (int i = inStart; i <= inEnd; i++) {
        if (inorder[i] == root.val) {
            inIndex = i;
            break;
        }
    }
    root.left = buildTree(preorder, preStart + 1, preStart + inIndex - inStart, inorder, inStart, inIndex - 1);
    root.right = buildTree(preorder, preStart + inIndex - inStart + 1, preEnd, inorder, inIndex + 1, inEnd);
    return root;
}

示例2

我们有一个如下图所示的二叉树:

       1
      / \
     2   3
    /   / \
   4   5   6
      / \
     7   8

我们要求二叉树中和为8的路径。我们可以使用递归的方式,遍历整棵树,在遍历的同时将当前路径的和作为参数传入。如果当前节点是叶子节点并且路径和等于给定值,则打印当前路径,否则递归遍历左子树和右子树。

public List<List<Integer>> pathSum(TreeNode root, int sum) {
    List<List<Integer>> result = new ArrayList<>();
    if (root == null) {
        return result;
    }
    List<Integer> path = new ArrayList<>();
    pathSum(root, sum, path, result);
    return result;
}

private void pathSum(TreeNode node, int sum, List<Integer> path, List<List<Integer>> result) {
    if (node == null) {
        return;
    }
    path.add(node.val);
    sum -= node.val;
    if (sum == 0 && node.left == null && node.right == null) {
        result.add(new ArrayList<>(path));
    }
    pathSum(node.left, sum, path, result);
    pathSum(node.right, sum, path, result);
    path.remove(path.size() - 1);
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java数据结构二叉树难点解析 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言数据结构与算法之排序总结(二)

    C语言数据结构与算法之排序总结(二) 本篇文章是关于C语言数据结构与算法中排序算法的详细讲解,涉及了八种排序算法。 冒泡排序(Bubble Sort) 冒泡排序是一种简单的排序算法。在排序过程中,它会重复地交换相邻的元素,这是它名称的由来。 示例代码: c void bubble_sort(int arr[], int n) { for (int i = 0…

    数据结构 2023年5月17日
    00
  • C++实现LeetCode(211.添加和查找单词-数据结构设计)

    首先,我们需要先了解一下题目的要求和限制,以及具体的解题思路。 题目描述 设计一个支持添加、删除、查找单词的数据结构。添加和删除单词的操作需要支持普通词和通配符’.’。查找单词只支持普通词,不支持通配符’.’。所有单词都是非空的。 解题思路 这道题可以使用前缀树(Trie树)来实现。 首先,我们需要定义一个单词类,它包含两个字段:单词字符串和单词长度。然后,…

    数据结构 2023年5月17日
    00
  • C语言数据结构与算法之图的遍历(一)

    我来给您详细讲解一下“C语言数据结构与算法之图的遍历(一)”的完整攻略。 简介 本篇攻略主要介绍了图的遍历问题。图是由若干个点和连接这些点的边构成的数据结构,常用来表示复杂的关系和网络。图的遍历就是从图的某一点开始,按照一定的规则沿着边逐个访问图中所有的点,不重不漏地遍历整个图。 在本篇攻略中,我们将探讨图的深度优先遍历(DFS)和广度优先遍历(BFS)两种…

    数据结构 2023年5月17日
    00
  • JavaScript的Set数据结构详解

    JavaScript中的Set数据结构详解 什么是Set? Set 是一种 Javascript 内置的数据结构。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,可以通过new关键字来创建 Set 数据结构。 let mySet = new Set(); Set的基本用法 Set实例对象有以下常用方法: add(value):…

    数据结构 2023年5月17日
    00
  • C语言数据结构之单链表存储详解

    C语言数据结构之单链表存储详解 什么是单链表 链表是一种非顺序存储的数据结构,其每个节点都保存下一个节点的地址。单链表是最简单的链表,每个节点只包含下一个节点的地址。 单链表节点的定义 单链表的节点定义一般包括两个部分:数据域和指针域。数据域存放节点的数据,指针域存放下一个节点的地址。 以下是单链表节点的定义: typedef struct node { i…

    数据结构 2023年5月17日
    00
  • C#模拟链表数据结构的实例解析

    C#模拟链表数据结构的实例解析 简介 链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个数据元素和指向下一个节点的指针。本篇文章将介绍如何使用 C# 来模拟链表数据结构,并通过两个示例展示如何实现链表的操作。 链表的基本结构 链表是由一系列节点组成的,每个节点包含一个数据元素和指向下一个节点的指针。我们可以通过以下代码定义一个链表节点的类: pu…

    数据结构 2023年5月17日
    00
  • MySQL索引结构详细解析

    MySQL索引结构是MySQL数据库中非常重要的一部分,它能够显著提升数据库查询效率。本文将详细解析MySQL索引结构,包括索引的基本概念、常见的索引类型、索引的创建、索引的使用和索引的优化等方面。 索引的基本概念 索引是一种数据结构,它可以加速数据库中的查询操作。索引一般是在表中一个或多个列上创建的,这些列的值被按照一定的规则存储在索引中。当查询时,可以通…

    数据结构 2023年5月17日
    00
  • 浅谈PHP链表数据结构(单链表)

    介绍 链表是一种常见的数据结构,它包括单链表和双链表,本文中我们将会介绍PHP的单链表数据结构实现,具体而言我们将会实现一个包括插入节点,删除节点,打印节点等基本操作的单链表,帮助读者深入理解PHP链表数据结构。 创建节点 链表数据结构是由一个个节点组成的,我们首先要实现一个节点的创建函数,这个函数接受两个参数,一个是节点数据,另一个是下一个节点的指针地址。…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部