Python数据结构---线段树

线段树(Segment Tree)是一种常见的数据结构,常用于解决区间查询问题,例如区间最大值、最小值、区间和、区间平均值等。

下面讲一下如何在Python 中实现线段树。

1.定义节点类

首先,我们需要定义一个节点类来表示线段树中的节点。每个节点包含一个左右子节点、区间起始和结束位置以及一些其他信息(如区间和、区间最大值、最小值等)。

在 Python 中,可以使用以下代码定义一个节点类:

class SegmentTreeNode:
    def __init__(self, start, end):
        self.start = start  # 区间起始位置
        self.end = end  # 区间结束位置
        self.left = None  # 左子节点
        self.right = None  # 右子节点
        self.sum = 0  # 区间和
        # 其他信息(例如区间最大值、最小值等)可以根据需要添加

2.构建线段树

构建线段树的过程可以使用递归的方式实现。
首先,定义一个 build 函数,该函数接收一个数组以及区间起始和结束位置,返回构建好的线段树的根节点。
在函数内部,首先创建一个新节点表示当前区间,然后递归构建左右子树,最后将左右子树的区间和相加作为当前节点的区间和。

def build(nums, start, end):
    if start > end:
        return None
    root = SegmentTreeNode(start, end)
    if start == end:
        root.sum = nums[start]
        return root
    mid = (start + end) // 2
    root.left = build(nums, start, mid)
    root.right = build(nums, mid+1, end)
    root.sum = root.left.sum + root.right.sum
    return root

3.区间查询

线段树最常见的用途就是区间查询。
例如,查询一个区间的和、最大值、最小值等。
以下是一个实现区间查询的示例代码:

def query(root, start, end):
    if not root:
        return 0
    if start <= root.start and end >= root.end:
        return root.sum
    mid = (root.start + root.end) // 2
    res = 0
    if start <= mid:
        res += query(root.left, start, end)
    if end > mid:
        res += query(root.right, start, end)
    return res

这个函数接收一个根节点、区间起始和结束位置,返回区间和。如果当前节点的区间包含在查询区间内,则直接返回当前节点的区间和;否则,将查询区间分别递归到左右子树中查询,并将左右子树的查询结果相加作为最终结果。

4.区间修改

除了区间查询之外,线段树还可以用来实现区间修改。例如,修改一个区间中的数值,或者给一个区间加上一个定值。
以下是一个实现区间修改的示例代码:

def update(root, start, end, val):
    if not root:
        return
    if start <= root.start and end >= root.end:
        root.sum += val
        return
    mid = (root.start + root.end) // 2
    if start <= mid:
        update(root.left, start, end, val)
    if end > mid:
        update(root.right, start, end, val)
    root.sum = root.left.sum + root.right.sum

这个函数接收一个根节点、区间起始和结束位置以及要修改的值,将指定区间的数值修改为指定的值。如果当前节点的区间包含在修改区间内,则直接修改当前节点的值;否则,将修改区间分别递归到左右子树中修改。

综上所述,线段树是一种非常有用的数据结构,可以用来解决各种区间查询和修改问题。在 Python 中,实现线段树的方法和其他语言类似,可以通过定义节点类、递归构建线段树、实现区间查询和修改等操作来实现线段树。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
算法有兴趣的可以来看看 在自然数,且所有的数不大于30000的范围内讨论一个问题:现在已知n条线段,把端点依次输入告诉你,然后有m个询问,每个询问输入一个点,要求这个点在多少条线段上出现过; 最基本的解法当然就是读一个点,就把所有线段比一下,看看在不在线段中; 每次询问都要把n条线段查一次,那么m次询问,就要运算m*n次,复杂度就是O(m*n) 这道题m和n都是30000,那么计算量达到了10^9;而计算机1秒的计算量大约是10^8的数量级,所以这种方法无论怎么优化都是超时 因为n条线段是固定的,所以某种程度上说每次都把n条线段查一遍有大量的重复和浪费; 线段树就是可以解决这类问题的数据结构 举例说明:已知线段[2,5] [4,6] [0,7];求点2,4,7分别出现了多少次 在[0,7]区间上建立一棵满二叉树:(为了和已知线段区别,用【】表示线段树中的线段) 【0,7】 / \ 【0,3】 【4,7】 / \ / \ 【0,1】 【2,3】 【4,5】 【6,7】 / \ / \ / \ / \ 【0,0】 【1,1】 【2,2】 【3,3】 【4,4】 【5,5】 【6,6】 【7,7】 每个节点用结构体: struct line { int left,right; // 左端点、右端点 int n; // 记录这条线段出现了多少次,默认为0 }a[16]; 和堆类似,满二叉树的性质决定a[i]的左儿子是a[2*i]、右儿子是a[2*i+1]; 然后对于已知的线段依次进行插入操作: 从树根开始调用递归函数insert // 要插入的线段的左端点和右端点、以及当前线段树中的某条线段 void insert(int s,int t,int step)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值