数据结构:树形数据结构

1. 树的基本概念

在计算机科学中,树是一种非常重要的数据结构,用于模拟现实世界中的层次关系。它由一组节点和一组连接这些节点的边组成,节点之间的关系是一对多的关系,其中一个节点称为父节点,它下面的节点称为子节点。

1.1 树的定义

树是由节点和边组成的非线性数据结构,其中每个节点最多有一个父节点和多个子节点。树中最顶层的节点称为根节点,没有子节点的节点称为叶子节点。树是一种递归定义的数据结构,其中每个子树也是一棵树。

1.2 树的术语

为了更好地理解树,让我们来解释一些常见的树术语:

  • 根节点 (Root): 树的顶层节点,没有父节点。
  • 叶子节点 (Leaf): 没有子节点的节点。
  • 子树 (Subtree): 树中的任意节点及其所有后代节点构成的子结构称为子树。
  • 深度 (Depth): 从根节点到当前节点的唯一路径长度。
  • 高度 (Height): 从当前节点到最远叶子节点的路径长度。

为了更好地理解这些术语,让我们通过示例代码来创建一个简单的树结构:

class TreeNode {int val;List<TreeNode> children;public TreeNode(int val) {this.val = val;this.children = new ArrayList<>();}
}// 创建树的根节点
TreeNode root = new TreeNode(1);// 添加子节点
root.children.add(new TreeNode(2));
root.children.add(new TreeNode(3));// 创建子树
TreeNode child = new TreeNode(4);
child.children.add(new TreeNode(5));
root.children.add(child);

在这个示例中,根节点是1,它有两个子节点2和3,以及一个子树,其中子树的根节点是4,它有一个子节点5。

2. 二叉树 (Binary Tree)

二叉树是一种常见且重要的树形数据结构,它具有简单的定义和丰富的应用场景。本节将详细介绍二叉树的定义、特性、遍历算法以及应用,并附带示例代码以帮助读者更好地理解和掌握这一概念。

2.1 二叉树的定义和特性

二叉树是每个节点最多有两个子节点的树结构。节点由一个存储数据元素的值和两个指向其左子节点和右子节点的指针组成。下面是一个简单的二叉树示例:

      1/ \2   3/ \4   5

在这个示例中,数字表示节点的值,斜线表示指向子节点的指针。根节点的值为1,它的左子节点为2,右子节点为3,以此类推。

2.2 二叉树的遍历算法

二叉树的遍历是指按照一定顺序访问树中的所有节点。常见的遍历算法包括前序遍历、中序遍历和后序遍历。

  • 前序遍历 (Preorder Traversal): 先访问根节点,然后递归地前序遍历左子树和右子树。
  • 中序遍历 (Inorder Traversal): 先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。
  • 后序遍历 (Postorder Traversal): 先递归地后序遍历左子树和右子树,然后访问根节点。

下面是这三种遍历算法的Java示例代码:

class TreeNode {int val;TreeNode left;TreeNode right;public TreeNode(int val) {this.val = val;}
}class BinaryTree {// 前序遍历public void preorderTraversal(TreeNode root) {if (root != null) {System.out.print(root.val + " ");preorderTraversal(root.left);preorderTraversal(root.right);}}// 中序遍历public void inorderTraversal(TreeNode root) {if (root != null) {inorderTraversal(root.left);System.out.print(root.val + " ");inorderTraversal(root.right);}}// 后序遍历public void postorderTraversal(TreeNode root) {if (root != null) {postorderTraversal(root.left);postorderTraversal(root.right);System.out.print(root.val + " ");}}
}

这段代码定义了一个简单的二叉树类和节点类,并实现了前序、中序和后序遍历三种算法。通过调用不同的遍历方法,可以按照不同的顺序访问二叉树中的节点。

2.3 二叉树的应用

二叉树在计算机科学和工程中有着广泛的应用,例如:

  • 表达式树 (Expression Tree): 用于表示数学表达式的树形结构,方便进行表达式的求值和转换。
  • 二叉搜索树 (Binary Search Tree, BST): 一种有序二叉树,常用于实现关联数组和集合,支持快速的查找、插入和删除操作。
  • 堆 (Heap): 一种特殊的二叉树结构,常用于实现优先队列等数据结构,支持快速的最大值或最小值查找。

3. 二叉搜索树 (Binary Search Tree, BST)

二叉搜索树是一种有序的二叉树,具有以下特性:对于树中的每个节点,其左子树中的所有节点的值都小于该节点的值,而右子树中的所有节点的值都大于该节点的值。这种特性使得二叉搜索树在查找、插入和删除等操作上具有较高的效率。

3.1 BST的定义和特性

二叉搜索树的定义非常简单,但其特性却十分重要:

  • 对于任意节点 node,其左子树中的所有节点的值都小于 node 的值。
  • 对于任意节点 node,其右子树中的所有节点的值都大于 node 的值。
  • 左右子树也分别是二叉搜索树。

这个特性使得在二叉搜索树中进行查找、插入和删除等操作的平均时间复杂度为 O(log n),其中 n 是树中节点的数量。

3.2 BST的操作

二叉搜索树支持以下基本操作:

  • 查找 (Search): 在二叉搜索树中查找指定的元素。
  • 插入 (Insert): 向二叉搜索树中插入新的元素。
  • 删除 (Delete): 从二叉搜索树中删除指定的元素。

这些操作都可以通过递归或迭代的方式实现。下面是一个简单的Java示例代码,实现了二叉搜索树的基本操作:

class BinarySearchTree {class TreeNode {int val;TreeNode left;TreeNode right;public TreeNode(int val) {this.val = val;}}private TreeNode root;public TreeNode search(int target) {TreeNode curr = root;while (curr != null && curr.val != target) {if (target < curr.val) {curr = curr.left;} else {curr = curr.right;}}return curr;}public void insert(int val) {root = insertNode(root, val);}private TreeNode insertNode(TreeNode root, int val) {if (root == null) {return new TreeNode(val);}if (val < root.val) {root.left = insertNode(root.left, val);} else if (val > root.val) {root.right = insertNode(root.right, val);}return root;}public void delete(int val) {root = deleteNode(root, val);}private TreeNode deleteNode(TreeNode root, int val) {if (root == null) {return null;}if (val < root.val) {root.left = deleteNode(root.left, val);} else if (val > root.val) {root.right = deleteNode(root.right, val);} else {if (root.left == null) {return root.right;} else if (root.right == null) {return root.left;}TreeNode minNode = findMin(root.right);root.val = minNode.val;root.right = deleteNode(root.right, root.val);}return root;}private TreeNode findMin(TreeNode node) {while (node.left != null) {node = node.left;}return node;}
}

这段代码定义了一个简单的二叉搜索树类,并实现了查找、插入和删除操作。通过调用这些方法,可以在二叉搜索树中执行相应的操作,保持树的有序性。

3.3 BST的平衡性

在进行插入和删除操作时,二叉搜索树可能会因为失去平衡而导致性能下降。为了维持树的平衡性,常见的做法是使用平衡BST算法,如AVL树、红黑树等。这些算法保证了树的高度始终保持在一个较小的范围内,从而保持了操作的高效性。

4. 平衡树 (Balanced Tree)

平衡树是一种高度平衡的树结构,其任意节点的左右子树高度差不超过一个固定常数。这种平衡性能够保证树的高度始终保持在一个较小的范围内,从而保持了操作的高效性。

4.1 平衡树的定义和特性

平衡树的定义相对简单,但其特性十分重要:

  • 任意节点的左子树和右子树的高度差不超过一个固定常数(通常为1)。
  • 平衡树中的节点按照一定的规则进行插入和删除操作,以保持树的平衡性。

由于平衡树的平衡性,其查找、插入和删除等操作的时间复杂度通常为 O(log n),其中 n 是树中节点的数量。

4.2 平衡树的实现

实现平衡树的方式有多种,常见的包括 AVL 树、红黑树、B 树等。这些算法通过在插入和删除节点时进行旋转、调整等操作,来保持树的平衡性。

  • AVL 树: AVL 树是一种自平衡二叉搜索树,其中任意节点的左子树和右子树的高度差不超过1。在插入和删除操作后,AVL 树通过旋转操作来保持平衡。

  • 红黑树: 红黑树是一种具有红色和黑色节点的二叉搜索树,它满足以下性质:(1)每个节点要么是红色,要么是黑色;(2)根节点是黑色;(3)每个叶子节点(NIL 节点)是黑色;(4)如果一个节点是红色,则它的两个子节点都是黑色。红黑树通过旋转和着色操作来保持平衡。

  • B 树: B 树是一种多路搜索树,其内部节点可以有多个子节点。B 树常用于数据库和文件系统中,能够高效地支持大量数据的插入、删除和查找操作。

4.3 平衡树的应用

平衡树在计算机科学和工程中有着广泛的应用,例如:

  • 数据库索引: 在数据库中使用平衡树来实现索引结构,支持快速的数据查找和检索。
  • 文件系统: 文件系统中的文件和目录通常使用平衡树来进行组织和管理,以支持快速的文件访问和操作。
  • 编译器: 在编译器中使用平衡树来表示符号表、语法树等数据结构,支持快速的语法分析和编译过程。

5. 平衡树的定义和特性

平衡树的定义相对简单,但其特性十分重要:

  • 任意节点的左子树和右子树的高度差不超过一个固定常数(通常为1)。
  • 平衡树中的节点按照一定的规则进行插入和删除操作,以保持树的平衡性。

由于平衡树的平衡性,其查找、插入和删除等操作的时间复杂度通常为 O(log n),其中 n 是树中节点的数量。

5.1 平衡树的实现

实现平衡树的方式有多种,常见的包括 AVL 树、红黑树、B 树等。这些算法通过在插入和删除节点时进行旋转、调整等操作,来保持树的平衡性。

  • AVL 树: AVL 树是一种自平衡二叉搜索树,其中任意节点的左子树和右子树的高度差不超过1。在插入和删除操作后,AVL 树通过旋转操作来保持平衡。

  • 红黑树: 红黑树是一种具有红色和黑色节点的二叉搜索树,它满足以下性质:(1)每个节点要么是红色,要么是黑色;(2)根节点是黑色;(3)每个叶子节点(NIL 节点)是黑色;(4)如果一个节点是红色,则它的两个子节点都是黑色。红黑树通过旋转和着色操作来保持平衡。

  • B 树: B 树是一种多路搜索树,其内部节点可以有多个子节点。B 树常用于数据库和文件系统中,能够高效地支持大量数据的插入、删除和查找操作。

5.2 平衡树的应用

平衡树在计算机科学和工程中有着广泛的应用,例如:

  • 数据库索引: 在数据库中使用平衡树来实现索引结构,支持快速的数据查找和检索。
  • 文件系统: 文件系统中的文件和目录通常使用平衡树来进行组织和管理,以支持快速的文件访问和操作。
  • 编译器: 在编译器中使用平衡树来表示符号表、语法树等数据结构,支持快速的语法分析和编译过程。

平衡树作为一种高效的数据结构,在各个领域都有着重要的应用价值。在实际开发中,选择合适的平衡树算法并加以应用,能够提高程序的性能和效率。

6. B树和B+树

B树和B+树是常见的多路搜索树,它们被广泛用于数据库系统和文件系统中,以支持高效的数据插入、删除和查找操作。

6.1 B树的定义和特性

B树是一种多路搜索树,其内部节点可以有多个子节点。B树的特点包括:

  • 每个节点可以包含多个关键字和指针。
  • 所有叶子节点位于同一层,形成一个有序的链表。
  • B树的节点分裂和合并操作可以保持树的平衡性。

B树的平衡性能够保证在进行插入和删除操作时,树的高度始终保持在一个较小的范围内,从而保持了操作的高效性。

6.2 B树的操作和实现

B树支持以下基本操作:

  • 查找 (Search): 在B树中查找指定的元素。
  • 插入 (Insert): 向B树中插入新的元素。
  • 删除 (Delete): 从B树中删除指定的元素。

这些操作都可以通过递归或迭代的方式实现,保持树的平衡性。

下面是一个简单的B树的插入操作示例代码(使用Python实现):

class BTreeNode:def __init__(self, leaf=False):self.leaf = leafself.keys = []self.children = []class BTree:def __init__(self, t):self.root = BTreeNode(True)self.t = tdef insert(self, k):root = self.rootif len(root.keys) == (2 * self.t) - 1:new_root = BTreeNode()self.root = new_rootnew_root.children.append(root)self._split_child(new_root, 0)self._insert_non_full(new_root, k)else:self._insert_non_full(root, k)def _insert_non_full(self, x, k):i = len(x.keys) - 1if x.leaf:x.keys.append(0)while i >= 0 and k < x.keys[i]:x.keys[i + 1] = x.keys[i]i -= 1x.keys[i + 1] = kelse:while i >= 0 and k < x.keys[i]:i -= 1i += 1if len(x.children[i].keys) == (2 * self.t) - 1:self._split_child(x, i)if k > x.keys[i]:i += 1self._insert_non_full(x.children[i], k)def _split_child(self, x, i):t = self.ty = x.children[i]z = BTreeNode(y.leaf)x.children.insert(i + 1, z)x.keys.insert(i, y.keys[t - 1])z.keys = y.keys[t:(2 * t - 1)]y.keys = y.keys[0:(t - 1)]if not y.leaf:z.children = y.children[t:(2 * t)]y.children = y.children[0:(t - 1)]

6.3 B+树

B+树是在B树的基础上优化而来的树结构,其特点包括:

  • 所有关键字只出现在叶子节点中,内部节点只包含子树的最大(或最小)关键字。
  • 叶子节点之间形成一个有序链表,便于范围查询。
  • B+树的内部节点不保存数据,只作为索引,因此能够容纳更多的子树。

B+树相比于B树,更适合用于范围查询和顺序访问。

7. 其他树形数据结构

除了常见的二叉树、平衡树和多路搜索树之外,还有一些其他类型的树形数据结构,在不同的应用场景中发挥着重要作用。

7.1 红黑树 (Red-Black Tree)

红黑树是一种自平衡的二叉搜索树,具有以下特性:

  • 每个节点要么是红色,要么是黑色。
  • 根节点是黑色。
  • 每个叶子节点(NIL 节点)是黑色。
  • 如果一个节点是红色,则它的两个子节点都是黑色。
  • 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

红黑树通过旋转和着色操作来保持平衡,其插入、删除和查找等操作的时间复杂度为 O(log n),其中 n 是树中节点的数量。

7.2 Trie树 (Trie Tree)

Trie树,也称为字典树或前缀树,是一种树形数据结构,用于存储字符串集合。其特点包括:

  • 每个节点代表一个字符串的前缀。
  • 从根节点到每个子节点的路径构成一个字符串。
  • 在Trie树中,不同的路径可以代表不同的字符串。

Trie树常被用于字符串的存储和检索,例如单词查找、自动补全等场景。

7.3

哈夫曼树 (Huffman Tree)

哈夫曼树是一种用于数据压缩的树形结构,通过构建最优前缀编码来实

现数据的压缩。其特点包括:

  • 频率越高的字符在哈夫曼树中的深度越浅。
  • 哈夫曼树的路径长度与字符的出现频率成正比。

哈夫曼树常被用于数据压缩算法中,例如在无损压缩和通信领域中广泛应用。

以上是一些常见的树形数据结构,它们在不同的领域中发挥着重要的作用。在实际应用中,选择合适的树形数据结构能够提高程序的效率和性能,从而更好地满足各种需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/699360.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何将建筑白模叠加到三维地球上?

​ 通过以下方法可以将建筑白模叠加到三维地球上。 方法/步骤 下载三维地图浏览器 http://www.geosaas.com/download/map3dbrowser.exe&#xff0c;安装完成后桌面上出现”三维地图浏览器“图标。 2、双击桌面图标打开”三维地图浏览器“ 3、点击“建筑白模”菜单&…

我一直想给自己辩护

哈喽&#xff0c;大家好&#xff0c;我叫人宅&#xff0c;这里特意和大家聊聊关于我的课程问题。 很多学员私下讨论我的课程&#xff0c;太难了&#xff0c;有的甚至准备去报个培训班。即使我们花了那么大精力来做入门引导&#xff0c;还是觉得有难度。 还有课程中有嵌套课程…

欢迎 Gemma: Google 最新推出开源大语言模型

今天&#xff0c;Google 发布了一系列最新的开放式大型语言模型 —— Gemma&#xff01;Google 正在加强其对开源人工智能的支持&#xff0c;我们也非常有幸能够帮助全力支持这次发布&#xff0c;并与 Hugging Face 生态完美集成。 Gemma 提供两种规模的模型&#xff1a;7B 参数…

ES6中的Map数据结构的键可以是哪些数据类型

Map 的键可以是任何数据类型&#xff0c;包括对象、函数、原始类型等。 1. 原始类型作为键&#xff1a; let primitiveKeyMap new Map(); primitiveKeyMap.set(1, One); // 数字作为键 primitiveKeyMap.set(name, Alice); // 字符串作为键 primitiveKeyMap.set(true, True);…

浅拷贝导致的bug

错误代码&#xff1a; //初始化formTableData的值 const formTableData ref({saleOrderTime:,saleOrderDetails:[] });const showModal async (item) > {//调接口获取后端返回的数据let data (await api.searchSaleOrderById({saleOrderId:item.id})).dataconsole.log(&…

文本处理三驾马车之 sed

sed 是 stream editor 的缩写&#xff0c;中文称之为“流编辑器”。 sed command file command 部分&#xff0c;针对每行要进行的处理file&#xff0c;要处理的文件 Actions d&#xff1a;删除该行p&#xff1a;打印该行i&#xff1a;在行的前面插入新行a&#xff1a;在行的后…

全流程点云机器学习(一)使用CloudCompare自制sharpNet数据集

前言 这不是高支模项目需要嘛&#xff0c;他们用传统算法切那个横杆竖杆流程复杂耗时很长&#xff0c;所以想能不能用机器学习完成这些工作&#xff0c;所以我就来整这个工作了。 工欲善其事&#xff0c;必先利其器&#xff0c;在正式开始之前&#xff0c;我们先要搞懂如何切…

API接口实现自动化数据同步

一、API的核心作用 API是现代电子商务生态系统中不可或缺的组成部分&#xff0c;它使得不同平台和服务之间的数据共享变得可能。通过API&#xff0c;开发者可以访问到商品信息、用户评价、销售数据等&#xff0c;这些数据对于市场分析、库存管理和用户体验优化至关重要。 二、…

每日leetcode--删除有序数组中的重复项

问题描述 给定一个包含重复元素的整数列表nums&#xff0c;我们需要移除其中的重复元素&#xff0c;并返回去重后的列表长度。 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 解决方案&#xff1a; 我们可以使用一个额外的列表来存储不重复的元素&#xff…

Linux 开启防火墙 --- FirewallD is not running 问题修复

问题 在配置SSL认证后&#xff0c;需要放开防火墙的443端口&#xff0c;出现了FirewallD is not running错误 [rootxxx ~]# firewall-cmd --zonepublic --add-port443/tcp --permanent FirewallD is not running解决 只需要开启防火墙即可。 【1】先通过systemctl status fir…

旅游分享系列之:福建旅游攻略

旅游分享系列之&#xff1a;福建旅游攻略 一、漳州1.福建土楼2.云水谣3.四菜一汤景点 二、厦门1.园林博览苑2.海上自行车道3.山海步道4.海滩5.闽南菜6.落日 三、泉州1.衙口沙滩2.海上日出3.珞珈寺4.海滩烟花 一、漳州 游玩2个景点&#xff1a;云水谣&#xff0c;四菜一汤可以住…

基于Java+SpringBoot+Vue前后端分离仓库管理系统设计实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

QT常用类

五、常用类 QString 字符串类&#xff08;掌握&#xff09; QString是Qt的字符串类&#xff0c;与C的std::string相比&#xff0c; 不再使用ASCII编码。QString使用的是Unicode编码。 QString中每个字符都是一个16位的QChar&#xff0c;而不是8位的char。 QString完全支持中文&…

深入探究node搭建socket服务器

自从上篇中sokect实现了视频通话&#xff0c;但是是使用ws依赖库实现的服务端&#xff0c;所以最近再看ws源码&#xff0c;不看不知道&#xff0c;一看很惊讶。 接下来一点点记录一下&#xff0c;如何搭建一个简易的服务端socket&#xff0c;来实现上次的视频通讯。 搭建一个…

详解AP3216C(三合一sensor: 光照、距离、照射强度)驱动开发

目录 概述 1 认识AP3216C 1.1 AP3216C特性 1.2 AP3216C内部结构 1.3 AP3216C 硬件电路 1.4 AP3216C工作时序 1.4.1 I2C 写数据协议 1.4.2 I2C 读数据协议 1.5 重要的寄存器 1.5.1 系统配置寄存器 1.5.2 和中断相关寄存器 1.5.3 IR数据寄存器 1.5.4 ALS 数据寄存器 …

十二、线性代数二-二次型:

目录 1、二次型的定义: 2、二次矩阵与二次型的理解: 3、二次型矩阵的性质: 4、二次型的标准型: 5、二次型的正定型: ①正定型的概念: ②二次型正定型的判定:

代码随想录算法训练营第59天 | 583.两个字符串的删除操作 + 72.编辑距离 + 编辑距离总结篇

今日任务 583. 两个字符串的删除操作 72. 编辑距离 编辑距离总结篇 583.两个字符串的删除操作 - Medium 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以…

tombstone常见崩溃信号说明

一、概念说明 在应用崩溃的时候&#xff0c;我们将会获取到两个信息: signal: 信号量&#xff0c;下文将会详细的说明不同的信号量及其含义。code: 错误码, 除了几个所有信号量(signal) 公共的错误码(code)&#xff0c;一般不同信号量(signal)有特定的错误码(code)&#xff0c;…

LeetCode题练习与总结:三数之和

一、题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。 请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组…

【数学建模规则】2024年第九届数维杯大学生数学建模挑战赛参赛指南

一、竞赛介绍 数维杯大学生数学建模挑战赛每年分为两场&#xff0c;每年上半年为数维杯国赛&#xff08;5月&#xff0c;俗称小国赛&#xff09;&#xff0c;下半年为数维杯国际赛(11月)&#xff0c;2023年第八届数维杯大学生数学建模挑战赛共有近1.4万名学生参赛&#xff0c;…