目录

  • p-sum理解
  • 代码

最近在论文"Private and Continual Release of Statistics"中了解到了一个这样的structure:

Definition 3.2 (p-sum). A p-sum is a partial sum of consecutive items. Let 1 ≤ i ≤j. We use the notation ∑[i,j]:=∑jk=iσ(k) to denote a partial sum involving items i through j.

其实关于这个结构到底是干嘛的我还不是很理解(文章讲了有关它的许多内容,但是我只看得懂最后两段描述)。文中是利用这个结构为一个二进制机制服务,后来有文章似乎用它来添加呈对数增长的噪音。它能为计算连续序列的部分和省下计算内存(但是单单从计算和的这部分,难道是累加的意思吗?如果单纯是累加,那似乎这个机制又没什么作用),对于一个长度为T的序列,只需要int(logT)+1的长度即可计算它们的区间累积和。

记录本博客一是觉得这个结构有点意思,二是太久没写代码,而且也一直打算写的另一篇博客也好几个月了都没动工…所以先来适应一下。本博客主要是按照自己对文中描述的理解来实现这个结构。

p-sum理解

p-sum结构用图表示是一颗二叉区间数,叶子结点代表每个参加计算的item,它们都有自己的值,内部结点代表区间和,即他下面的叶子结点之和。从1开始,每到达一个item(叶节点),到达的时间count+=1,这个count也可以理解为到达的次序,根据它的值来进行结点的更新。 树里的每一个结点都可以称作是一个p-sum。 如下图,count=1,2,3…8。

对于每一个count,将它转化为二进制之后,如果二进制中第j位为1,那么就意味着它包含一个2j个item的p-sum 。以T=7为例,二进制为111,即在j=0,1,2 的位上值都为1,那么它包含20=1,21=2,22=4个item,对应三个p-sum,即下图中的7,[5,6],[1,4]。

因此,根据这颗二叉区间数可以看出,当新到达结点可以参与合并的时候,结点就会不断向上合并直到无法合并。以下图为例,同样颜色的结点可以合并,不同层的结点之间无法合并。

例如:当第一个(count=1)到达时,没有能够合并的点,因此只存下结点1的value。第二个结点到达时,可以进行合并,于是1和2结点值合并成[1,2](相加),一旦结点参与合并,那么它就不再有作用,因此可以释放储存它的空间,即释放储存结点1和2的空间,将[1,2]值覆盖到原本存结点1的位置。这就达到了节约内存的目的。
此时内存中列表只存下了一个结点[1,2]值,当count=3的结点到达时,无法合并,存下它的值。当count=4的结点到达时,可以进行合并,3和4合并成[3,4],同时[3,4]和[1,2]也可以进行合并,合并成[1,4]。此时又只需要存一个结点的值即可,将原来存[1,2],3,4结点空间释放,将[1,4]存入原来储存[1,2]的位置即可。

在这个过程中,我们可以发现一些规律:对于第count时刻达到的item,最多只需要log(count)取整+1个单位空间即可完成上述操作
比如当count=1时候,需要1个单位空间存下;
当count=2时,需要存下1和2,然后合并成[1,2],在这个过程中,最多只需要2个单位空间;
…;
当count=7的时候,空间中只存有[1,4],[5,6],7,需要三个单位;
当count=8时,多增加储存结点8的空间,共4个单位,然后进行合并,最终只需要消耗一个单位。
换句话说,当一个结点达到时,对节点进行储存或更新时所需要的最大内存量就是它能参与构成二叉区间数的层高。

上面为了方便理解,举了具体例子,接下来介绍它的一般更新方法。
定义当前储存在列表中的结点值为αj,αj代表它是2j个item的和。对于count时刻到达的item,首先将count二进制化,找到这个二进制表示最低位非0的位数j。count由count-1进位得来,对于count-1的二进制表示,它的i<j位都是1,因此才能在进位后导致第j位=1,后面都是0。因此当进位之后,就产生了一个2j个item之和的p-sum——αj其中αj=∑(i<j)αi+valcount。即由原来的所有αi(i<j)+当前item值合并成一个新的结点αj 合并之后αi(i<j)失去作用,可以被覆盖,将αj存入原来储存最大i的αi位置即可,此时αj作为列表中最后一位有效位(优化的做法是“失去作用”的αi不用被真的清除,只需要用一个指针记录最后一位有效位即可)。

p-sum列表中αj中j是递减的,在实际的代码中,当找到当前count的最低非0下标j之后,只要往p-sum列表最后一位有效位开始累加j项即可。

代码

import random
from cmath import log#测试数据
nums=[random.randint(1,500) for i in range(100)]#psum结点值记录
psum_lst=[]
#psum_lst中最后一个有效结点的指针
p_last=-1#转二进制,也可以直接使用python自带的bin()函数
def to_bin(num):bin_Str=[]while(num!=0):bin_Str.append(str(num%2))num//=2return ''.join(reversed(bin_Str))#更新p_sum结构
def p_sum(bin_str,val):global p_last,psum_lstlens=len(bin_str)idx=0now_sum=val#计算当前count(二进制格式)最低位有效‘1’之后的位数个数for i in range(lens-1,-1,-1):if(bin_str[i]=='1'):idx=lens-1-ibreak#如果这个idx>0说明发生了进位,需要更新节点if(idx>0):for i in range(p_last,p_last-idx,-1):now_sum+=psum_lst[i]   #将低位结点都累加,形成新的结点值p_last=p_last-idx+1            #更新p_last,p_last之后的结点无意义,可以被后面的结点更新psum_lst[p_last]=now_sum       #将新节点填入列表中#总函数
def cal_psum():global p_last,psum_lst#初始化psum_lst长度total_cnt=len(nums)psum_lst=[0 for i in range(int(log(total_cnt,2).real)+1)]for i in range(total_cnt):cnt_bin=to_bin(i+1)p_sum(cnt_bin,nums[i])#测试函数
def test():print('realsum: ', sum(nums)) #真实的总和cal_psum()# 计算有效结点的总和cal_sum=0for i in range(p_last+1):cal_sum+=psum_lst[i]print('cal_sum: ',cal_sum)test()

多次测试结果都正确:

p-sum结构解释+代码 二叉区间树相关推荐

  1. 下拉菜单实现树状结构_二叉索引树(树状数组)的原理

    背景 了解到二叉索引树这个数据结构,是在 leetcode 的 307 题,题目是要求实现一个数据结构,可以返回数组任意区间的和以及更新数组的某个值. 307.Range Sum Query - Mu ...

  2. 统计学习方法第五章作业:ID3/C4.5算法分类决策树、平方误差二叉回归树代码实现

    ID3/C4.5算法分类决策树 import numpy as np import math class Node:def __init__(self,feature_index=None,value ...

  3. 二叉索引树 -- 区间信息的维护与查询

    二叉索引树,俗称树状数组,也叫Fenwick树. 例: 给定一个n个元素的数组A1, A2, A3, --, An, 设计一个数据结构,支持以下两种操作. 1.Add  x  y       :让Ax ...

  4. 树形结构:二叉排列树,二叉搜索树

    二叉排列树,二叉搜索树 这个数听见得比较多,含义是:左边<=中间<=右边,换句话来说使用中序遍历最后得到结果就是一个有序得序列. 建立一颗二叉排列树 class BinTNode:def ...

  5. 二叉线索树的先序、中序、后序的线索化及其遍历

    线索二叉树 注意:源码 二叉线索树的概念 二叉线索树是在传统二叉树结构的基础上,加上判断结点左右孩子是否为空的标志–LTag,RTag. 当左孩子为空的时候,lchild指向该节点的前驱结点,当右孩子 ...

  6. “后序遍历二叉运算树进行Lambda演算的化简”带来的联系

    今天闲来无事,想到一个自以为绝妙的想法,那就是用后序遍历二叉树Lambda演算的化简. 数据结构与算法中,我们想写个计算器就必须遇到一个问题,表达式求值!其实表达式很多就是我们所谓的现实生活中的问题解 ...

  7. 数据结构---二叉线索树

    数据结构-二叉线索树 原理:参考趣学数据结构 代码: #include<stdio.h> #include<stdlib.h> typedef struct bmTree {i ...

  8. 数据结构学习记录(二)——折半查找二叉判定树的画法

    以下给出我在学习中总结的一种比较简便的构造折半二叉判定树的思路以及方法: 思路分析: 在计算mid值时,使用的时mid=(low+high)/2  .这里由于mid为int类型,自动默认为向下取整,因 ...

  9. 1597. 根据中缀表达式构造二叉表达式树 双端队列

    1597. 根据中缀表达式构造二叉表达式树 给定 pushed 和 popped 两个序列,每个序列中的 值都不重复,只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时 ...

最新文章

  1. Java Date类
  2. java 中的 viewUtils框架
  3. [转]移动应用统一化的谎言:一次编译,到处运行不可能
  4. activiti候选人的多个场景应用
  5. 算法 - 排序稳定性总结
  6. java技术教程视频_Spring开发视频教程高级篇+源码(400M)33讲
  7. linux大文件系统管理,Linux 磁盘和文件系统管理
  8. Linux的奖励机制是啥意思,Linux能力(capability)机制的继承
  9. oracle分区键使用大于小于会失效吗_大规模使用 Apache Kafka 的20个最佳实践
  10. Oracle ORA-03113错误解决办法
  11. Selenium官网打不开,这里看过来☺
  12. 系统集成项目管理工程师中高级一次通过经验之谈
  13. 新手小白做短视频自媒体,入门级教程分享,抓紧收藏
  14. plc用c语言编程实例,化学反应生产过程的PLC控制编程实例
  15. 利用两台苹果电脑实现扩展屏幕【双屏】
  16. python画球面_matplotlib中的球面坐标图
  17. 若菜光个人小档案(dambolo)
  18. 【解决笔记本电脑声音音量低的方法】
  19. 语义计算_语义多态性如何在量子计算中起作用
  20. Python一行代码能做什么,30个实用案例代码详解

热门文章

  1. 前后期绑定Excel/Word对象的应用
  2. 对计算机应用领域的CAE,我对CAE的了解和想要进行研究的方面
  3. 服务器必备工具软件推荐
  4. 遇见你是我最美的意外
  5. c语言中lookup函数功能,查询引用之王——Lookup函数实用技巧解读!
  6. java实现的聊天程序
  7. H5实时上传位置定位 pc生成轨迹;h5保持后台运行
  8. pr 调整图层缩放移动无效
  9. 一、软件/软件工程/软件开发模型概述
  10. 【元宵快乐】猜灯谜吃元宵 元气满满闹元宵~(附猜灯谜小游戏)