📜  斯特恩-布罗科序列(1)

📅  最后修改于: 2023-12-03 15:10:24.645000             🧑  作者: Mango

斯特恩-布罗科序列

简介

斯特恩-布罗科序列(Stern-Brocot sequence)又称为斯特恩-布罗科树(Stern-Brocot tree),是一棵无限完全二叉树,其每一个节点的分数值为两个相邻兄弟节点的分数值之和,最初的分数值为1/1和0/1。该序列在数论、计算几何和编程等领域都有广泛的应用。

构造方法

斯特恩-布罗科树的构造方法如下:

  1. 将一个整数区间[0,1]表示为节点(0/1,1/1)对应的完全二叉树的根节点。
  2. 对根节点(0/1,1/1)而言,它的左儿子为(0/1,1/2),右儿子为(1/1,1/2)。
  3. 对于每个节点(u/v,w/x),它的左儿子为(u/v,u+w/v),右儿子为(u+w/v,w+x/v)。

如下图所示:

Stern-Brocot-Tree

应用场景

斯特恩-布罗科序列在数论、计算几何和编程领域都有广泛的应用,以下是一些常见的应用场景:

1. 生成无理数

Stern-Brocot序列可以生成无理数的近似值,例如对于一个无理数a,我们可以使用该序列逼近这个数,从而得到它的近似分数值,这个分数值越接近无理数,节点所表示的分数就越接近。

2. 二分查找

Stern-Brocot序列可以用于二分查找,例如在有序数组中查找某个元素的时候,可以将数组元素插入到斯特恩-布罗科树上,从而快速定位到元素的位置。

3. 旋转卡壳

旋转卡壳是一种计算多边形外包圆、最大距离等几何量的方法,斯特恩-布罗科序列可以用于计算旋转卡壳中的“重心段”的长和宽。

代码实现

下面是以Python为例的斯特恩-布罗科序列构造及应用代码示例:

# 构造斯特恩-布罗科树
def stern_brocot_tree():
    root = (0, 1), (1, 1)
    nodes = [root]
    while True:
        parent = nodes.pop(0)
        left = parent[0], (parent[0][0] + parent[1][0], parent[1][0])
        right = (parent[0][0] + parent[1][0], parent[1][0]), parent[1]
        parent += (left, right)
        nodes.extend(left, right)
        yield parent

# 生成前n项斯特恩-布罗科序列
def stern_brocot_sequence(n):
    tree = stern_brocot_tree()
    nums = []
    for i in range(n):
        node = next(tree)
        nums.append(node[0])
    return nums

# 二分查找
def binary_search(data, item):
    left, right = 0, len(data) - 1
    while left <= right:
        mid = (left + right) // 2
        if data[mid][0] < item:
            left = mid + 1
        elif data[mid][0] > item:
            right = mid - 1
        else:
            return mid
    return None

# 计算旋转卡壳的重心段长和宽
def rotating_calipers(nodes):
    b, c = (0, 0), (0, 0)
    max_area = 0
    for a in nodes:
        while (c[0]-b[0])*(a[1]-c[1])-(c[1]-b[1])*(a[0]-c[0]) < 0:
            b, c = c, nodes.pop()
        distance = max((a[0]-b[0])**2 + (a[1]-b[1])**2, (c[0]-a[0])**2 + (c[1]-a[1])**2)
        width = abs((c[0]-b[0])*(a[1]-b[1])-(a[0]-b[0])*(c[1]-b[1]))/distance
        max_area = max(max_area, distance * width)
    return max_area

# 示例代码
if __name__ == '__main__':
    # 生成前10项斯特恩-布罗科序列
    nums = stern_brocot_sequence(10)
    print(nums)
    # 查找序列中分母为7的分数
    index = binary_search(nums, 7)
    print(index)
    # 计算旋转卡壳重心段的长和宽
    nodes = [(1, 1), (2, 2), (3, 6), (4, 4), (5, 3)]
    max_area = rotating_calipers(nodes)
    print(max_area)

以上代码实现了斯特恩-布罗科序列的构造方法、二分查找方法以及旋转卡壳计算“重心段”的长和宽方法。在实际应用中,可能还需要根据具体场景进行适当的修改。