二叉索引树范围更新和范围查询

2024年8月28日 | 阅读 7 分钟

二叉索引树(BIT),也称为 Fenwick 树,是一种数据结构,可以高效地查询和更新数组中的前缀和。它对于解决需要累积频率或范围查询的问题特别有用。BIT 有效地处理范围更新和范围查询。

在 BIT 中,值数组表示为树结构,每个节点包含原始数组中某个范围值的累积和。这利用了索引的二进制表示来实现快速更新和查询。

范围更新和范围查询是复杂的程序,涉及更改和检查数组或数据结构中特定范围内的多个元素。这些操作经常用于各种技术和情况下,以有效地处理数据段的更新和搜索。让我们更详细地探讨范围更新和范围查询。

范围更新

范围更新涉及更改数组或数据结构的特定子集元素。当您希望对给定范围内所有项目进行特定更改时,此操作很有用。范围更新涉及将范围内所有元素更改为特定值,或将值添加到范围内所有元素。

在二叉索引树(BIT)或 Fenwick 树的上下文中,范围更新通过执行两次更新操作来完成,一次在范围的起始索引处,另一次在结束索引之后的索引处。起始索引处的更新提高了该索引和所有后续索引的累积和,而结束索引处的更新则减少了该点之后索引的累积和。通过此方法,可以有效地捕获指定范围内的更改。

范围更新涉及调整数组或数据结构的特定子集元素。当您希望在设定的时间段内有效地将修改应用于多个元素时,此操作很有用。需要同时更新多个值的算法和问题经常使用范围更新。

示例:考虑数组中的一组数字。您希望向定义范围内每个值添加特定数量。

假设您有以下数组

[3, 8, 2, 6, 5, 1, 4]

此外,您希望向 [2, 5] 范围添加 4 个值。范围修改后,数组将变为

[3, 12, 6, 10, 9, 1, 4]

BIT(Fenwick 树)方法

范围的初始索引和结束索引之后的索引都必须接收更改,才能使用二叉索引树(BIT)完成范围更新。起始索引处的更新提高了该索引和所有后续索引的累积和,而结束索引处的更新则减少了该点之后索引的累积和。这有效地捕获了预期范围内的更改。

以下是使用 BIT 实现范围更新的方法

将 BIT 数组的初始值设置为零。

将增量值添加到范围的起始索引和所有后续索引,直到数组末尾,以更新该索引。

从结束索引之后的索引以及其后每个索引(直到数组末尾)减去增量值,以在该点执行更新。

使用 BIT 的范围更新伪代码

在此伪代码中,l 代表范围的初始索引,r 代表其结束索引,delta 代表需要应用的增量。

您可以通过应用这两个更新来更改范围 [l, r] 中的累积和,然后相应地更改后续累积和。

范围更新受益于 BIT 快速更新累积和并生成前缀和的能力,从而使利用 BIT 数据结构进行范围更新变得高效。它们成为解决涉及更改数组中值范围的众多算法问题的宝贵工具。

Python 代码

输出

Updated array: [3, 12, 6, 10, 9, 1, 4]

在此示例中,更新函数将特定值应用于 BIT 中的特定索引。range_update 方法对更新函数进行两次调用以创建范围更新效果。使用 BIT,prefix_sum 函数确定直到指定索引的前缀和。

请注意,此代码将使用 1-基于系统索引数组和 BIT,以快速导航 BIT 结构,索引 & -索引操作提取最右边的设置位。无论您的问题使用 0-基于索引还是 1-基于索引,请相应地调整索引。

范围查询

在数组或数据结构中,范围查询涉及获取特定范围元素的详细信息。此操作用于计算范围内元素的聚合值或属性。范围查询的示例是计算范围内的总和、最小值、最大值或其他统计信息。

前缀和技术可以有效地响应二叉索引树或 Fenwick 树上下文中的范围查询。范围内的项目总和可以通过从范围结束索引处的前缀和中减去起始索引之前的索引处的前缀和来计算。此方法利用 BIT 累积和的能力来快速计算所需结果。

在数组或数据结构中,范围查询涉及获取特定范围元素的详细信息。使用此方法,您可以有效地计算范围内组件的某些聚合值或属性。范围查询经常用于需要分析数据间隔或段的各种算法问题。下面提供了对查询范围的更详细描述

示例:您希望快速获取给定值数组中给定范围内的元素总和。

假设您有以下数组

[3, 8, 2, 6, 5, 1, 4]

您正在寻找 [2, 5] 范围内的数字总和。值 8 + 2 + 6 + 5 相加为 21。

BIT(Fenwick 树)方法

对二叉索引树(BIT)上的范围查询使用前缀和方法。范围内的项目总和可以通过从范围结束索引处的前缀和中减去起始索引之前的索引处的前缀和来计算。

以下是使用 BIT 实现范围查询的方法

  1. 使用 prefix_sum 函数确定直到范围终止索引的前缀和。
  2. 使用相同的 prefix_sum 函数,计算直到范围起始索引的前缀和。
  3. 通过比较步骤 1 和 2 中获得的前缀和,您可以确定落在所需范围内的元素总和。

使用 BIT 的范围查询伪代码

RangeQuery(l, r)

返回 PrefixSum(r) - PrefixSum(l - 1)

在此伪代码中,“1”表示范围的开始索引,“r”表示其结束索引。

无需显式遍历数组,您可以通过计算前缀和之间的差异来快速提取有关值范围的数据。

由于范围搜索使用 BIT 数据结构有效的​​前缀和计算能力,因此范围查询运行速度很快。分析或查询数组中数据范围的能力使它们对解决各种算法挑战很有用。

Python 代码

输出

Sum of values in range [2, 5]: 21

在此示例中,初始 BIT 是使用累积和和更新函数构建的。使用 BIT,prefix_sum 函数确定直到指定索引的前缀和。使用前缀和之间的区别,range_query 函数确定落在指定范围内的总值。

在用累积和初始化 BIT 后,代码演示了如何使用范围查询来检索特定范围内的值总和。

无论您的问题使用 0-基于索引还是 1-基于索引,请相应地调整索引。