在《具体数学》4.5中看到了SB-Tree,觉得非常有趣,就去研究了一下。

  首先介绍一下Stern-Brocot Tree。Stern-Brocot Tree是一种能将所有的最简分数都表示出来的结构,这不禁令人联想到一种在NOIP中曾出现的Cantor表,但注意,Contor表所表示的并不全是最简分数。

  图1:Stern-Brocot Tree

  

  观察SB-Tree的结构,我们可以很快发现它的构造方式,即从(0/1,1/0)出发,在两个相邻的分数m/n和m'/n'中插入(m+m')/(n+n'),这个插入的数我们称作m/n和m'/n'的中位分数(mediant)。

  根据这棵树的构造方式,我们不难发现,均有:m'n-mn'=1,当插入一个新的中值分数时,都满足:(m+m')n-m(n+n')=1且m'(n+n')-(m+m')n'=1。那么这棵树中的所有m,n,都必须满足(m,n)=1

  那么会否遗漏呢?答案是不会的,在《具体数学》中给出了一种证明,在此不多赘述。

  Stern-Brocot Tree还与一种有趣的级数列相关:法里级数(Farey serires)。法里级数是介于0和1之间分母不超过N的所有最简分数的集合,且按照递增的次序排序。

  

  图2:Farey serires

  

  wiki上给出了它与几何的一种优美的联系,如下:

  

  图3:Farey diagram

  

  如果仔细观察SB-Tree,我们就可以发现,每一阶的法里级数均是SB-Tree的子树。那么,法里级数的构造方法也就显而易见了,即在相邻的分数m/n和m'/n'中插入(m+m')/N。

   法里级数有一些基于此的奇奇怪怪的应用,有空补上。

  回到Stern-Brocot Tree。我们已经证明了SB Tree可以当作一个有理数的数系。那么每一个有理数都将对应一条唯一从根结点开始的树上路径,每一条从根结点开始的树上路径也将对应一个唯一的有理数。我们考虑怎么找到路径对应的数或者数所对应的路径。

  首先可以证明SB Tree是一棵排序二叉树,我写出自己对某个节点左子树的证明(既然是我自己口胡的,那就不一定对嘛23333):

     假设节点A对应的有理数为a/b,那么在他的左子树中,某一层最大的节点必为最靠右,设为B,的那个,设之为c/d。根据SB Tree的生成方式,它的下一层最靠右的节点为(c+a)/(b+d),化简后可以发现,它与a/b>c/d是等价的,因为B在在A的左子树中,那么上式必定成立。

  右子树的证明也将类似,不多赘述。

  那么我们就可以按照在排序二叉树中寻找元素的方式寻找相应的有理数了,但冷静的思考后我们会发现生成一棵完整的SB-Tree并不是一件容易的事情。

  我们能否在不求出所有节点的情况下解决问题呢?

  我们定义一个路径的表示为一个由L和R组成的字符串,顾名思义,L表示进入左子树,R表示进入右子树。令,f(s)表示串s对应的有理数。如f(LRRL)=5/7

  观察f(s)的数学性质我们可以得出(作者语,观察你个头。。。)2*2的01矩阵可以很好的得出f(s)的数学表示。定义M(s)为s所对应得矩阵,则有:

  

  那么对于任意一个路径譬如:

  

  那么:

   

  更一般的形式为:

   

  那么我们就可以通过矩阵来进行二叉搜索,或者推出路径所对应的有理数,如下:

S:=I;
while m/n<>f(S) do
if m/n<f(S) then (output(L);S:=SL;)
else (output(R);S:=SR;)

  但矩阵运算毕竟较为麻烦,我们考虑更简单的方法。

  首先我们可以发现:

   

  由是可以得出:

   

  于是就可以如是二叉搜索: 

while m<>n do
if m<n then (output(L);n:=n-m;)
else (output(R);m:=m-n;)

  这样的操作比起矩阵有个更大的好处,它可以快速找出逼近某个无理数的有理数,将if语句改一下即可:

if a< then (output(L);a:=a/(-a);)
else (output(R);a:=a-;)

  

  我们考虑用SB Tree来构造一些问题(我胡诌的。。。)

  1.已知两个有共同父亲的节点,求他们的父亲:

    通过矩阵运算列一个四元方程直接求解即可。

  2.求N个节点的LCA:

    求出所有节点的S串,找最长公共前缀即可。(当然这个算法是有优化空间的)

  3.第N层分母分子小于均等于N的数有多少(HDU4556)

    phi(n)的前缀和*2即可

  4.不用高精乘的有理数比较(无聊。。。)

    比较两个有理数路径的字典序即可

  不玩了,干正事去。。。。

Stern-Brocot Tree的更多相关文章

  1. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  2. SAP CRM 树视图(TREE VIEW)

    树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...

  3. 无限分级和tree结构数据增删改【提供Demo下载】

    无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...

  4. 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...

  5. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  6. Leetcode 笔记 100 - Same Tree

    题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...

  7. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

  8. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

  9. Leetcode 笔记 101 - Symmetric Tree

    题目链接:Symmetric Tree | LeetCode OJ Given a binary tree, check whether it is a mirror of itself (ie, s ...

  10. Tree树节点选中及取消和指定节点的隐藏

    指定节点变色 指定节点隐藏 单击节点 未选中则选中该节点 已选中则取消该节点 前台: 1.HTML <ul id="listDept" name="listDept ...

随机推荐

  1. C++ stl 运用(深层)

    1.multiset(set差不多) (1)erase删除,删除指针和键值是不同的. 键值的话是删除所有,指针的话是那个位置的值. (2)统计单个键值个数. (3)对于q.begin(),q.end( ...

  2. 《Spark Python API 官方文档中文版》 之 pyspark.sql (二)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

  3. Special Fish

    Special Fish Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...

  4. python如何将指定路径下的某类型文件,返回一个树形结构体,让前端显示为树形的目录结构

    最近遇到一个问题就是某个linux的目录下有各种文件现在的要求是只需要返回.kml格式的文件,并根据前端要求返回如下结构体即:[{'children': [{'children': [{'title' ...

  5. linux的特殊符号与正则表达式

    第1章 linux的特殊符号 1.1 通配符 * {} 1.1.1 含义 方便查找文件 通配符是用来找文件名字的. 1.1.2  * 通过find 命令找以 .sh 结尾的文件,使用*替代文件名字. ...

  6. Group(), Groups(),& Groupdict()

    group() 返回一个或多个匹配的字串.如果只有一个参数,结果只有单个字符串:如果有多个参数,结果是一个元组,元组里每一项对应一个参数.没有参数,group1默认是0(整个匹配串被返回).如果gro ...

  7. CSS实现自适应不同大小屏幕的背景大图

    在网上搜了好多demo:可总有这样那样的一些小瑕疵,试过几次后发现这样效果是最好的 html: <div class='bg'> <img src="image/bk02. ...

  8. display:none和visibility:hidden区别

    <!-- display:none和visible:hidden都能把网页上某个元素隐藏起来,但两者有区别: --> <!-- display:none 不为被隐藏的对象保留其物理空 ...

  9. Problem F: 合唱比赛开始了!

    Problem F: 合唱比赛开始了! Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 440  Solved: 201[Submit][Status][ ...

  10. QT中槽的使用

    一.建立槽和按钮之间的连接 connect(信号发送者,发送的信号,信号接收者,信号接收者的槽函数) 1.例子 connect(ui->pushButton,SIGNAL(clicked(boo ...