堆式存储线段树空间大小为4N的证明

前言

众所周知,堆式存储线段树空间要开到四倍,动态开点线段树空间要开到二倍。接下来给出证明。

动态开点线段树

动态开点线段树的空间大小只与线段树实际的节点数有关。一般开到 2 n 2n 2n

堆式存储线段树

静态线段树一般采用堆式存储,空间与最大节点编号有关。一般开到 4 n 4n 4n

证明

定理1

⌊ x + 1 2 ⌋ = ⌈ x 2 ⌉ \left\lfloor\frac {x+1}2\right\rfloor=\left\lceil\frac x2\right\rceil 2x+1=2x

显然。

定理2

⌊ x 2 ⌋ + ⌈ x 2 ⌉ = x \left\lfloor\frac {x}2\right\rfloor+\left\lceil\frac x2\right\rceil=x 2x+2x=x

显然。

定理3

节点 [ l , r ] ( l ≠ r ) , r − l + 1 = l e n [l,r](l\not=r),r-l+1=len [l,r](l=r),rl+1=len的两个子节点分别为 [ l , ⌊ l + r 2 ⌋ ] , [ ⌊ l + r 2 ⌋ + 1 , r ] \left[l,\left\lfloor\frac{l+r}2\right\rfloor\right],\left[\left\lfloor\frac{l+r}2\right\rfloor+1,r\right] [l,2l+r],[2l+r+1,r],其宽度分别为: ⌈ l e n 2 ⌉ , ⌊ l e n 2 ⌋ \lceil\frac {len}2\rceil,\lfloor\frac{len}2\rfloor 2len,2len

其左区间宽度为:
⌊ l + r 2 ⌋ − l + 1 \left\lfloor\frac{l+r}2\right\rfloor-l+1 2l+rl+1

我们知道:
x − 1 < ⌊ x ⌋ ≤ x x-1<\lfloor x\rfloor \leq x x1<xx

则:
l + r 2 − 1 < ⌊ l + r 2 ⌋ ≤ l + r 2 \frac {l+r}2-1<\left\lfloor\frac{l+r}2\right\rfloor\leq \frac{l+r}2 2l+r1<2l+r2l+r

即:
r − l + 2 2 − 1 < ⌊ l + r 2 ⌋ − l + 1 ≤ r − l + 2 2 \frac {r-l+2}2-1<\left\lfloor\frac{l+r}2\right\rfloor-l+1\leq \frac{r-l+2}2 2rl+21<2l+rl+12rl+2

我们还知道:
r − l + 2 2 − 1 < ⌊ r − l + 2 2 ⌋ ≤ r − l + 2 2 \frac {r-l+2}2-1<\left\lfloor\frac{r-l+2}2\right\rfloor\leq \frac{r-l+2}2 2rl+21<2rl+22rl+2

( r − l + 2 2 − 1 , r − l + 2 2 ] \left(\frac {r-l+2}2-1,\frac{r-l+2}2\right] (2rl+21,2rl+2]范围内显然只有一个整数,因此
⌊ l + r 2 ⌋ − l + 1 = ⌊ r − l + 2 2 ⌋ = ⌈ r − l + 1 2 ⌉ = ⌈ l e n 2 ⌉ \left\lfloor\frac{l+r}2\right\rfloor-l+1=\left\lfloor\frac{r-l+2}2\right\rfloor=\left\lceil\frac{r-l+1}2\right\rceil=\left\lceil\frac{len}2\right\rceil 2l+rl+1=2rl+2=2rl+1=2len

同理我们可以得知右区间宽度为 l e n − ⌈ l e n 2 ⌉ = ⌊ l e n 2 ⌋ len-\left\lceil\frac{len}2\right\rceil=\lfloor\frac{len}2\rfloor len2len=2len

定理4

两个线段树。宽度相同则图形态完全相同(区分左右儿子)。

应用数学归纳法容易证明。

定理5

宽度为 2 k 2^k 2k的线段树是一颗满二叉树,它的节点数目为 2 k + 1 − 1 2^{k+1}-1 2k+11

首先我们考虑维护区间 [ 1 , n = 2 k ] [1,n=2^k] [1,n=2k]的线段树。

显然它的形态是满二叉树。
那它的节点数量为: ∑ k i = 0 2 i = 2 k + 1 − 1 \underset{i=0}{\overset {k}\sum}2^i=2^{k+1}-1 i=0k2i=2k+11

定理6

k = ⌈ log ⁡ 2 n ⌉ k=\lceil\log_2 n\rceil k=log2n,则有:
⌊ n 2 ⌋ ≤ ⌊ 2 k 2 ⌋ \left\lfloor\frac n2\right\rfloor\leq\left\lfloor\frac {2^k}2\right\rfloor 2n22k

⌈ n 2 ⌉ ≤ ⌈ 2 k 2 ⌉ \left\lceil\frac n2\right\rceil\leq\left\lceil\frac {2^k}2\right\rceil 2n22k

显然。

定理7

线段树是一个Leafy Tree,即它的一个节点要么没有儿子,要么有左右儿子。

假设一个节点的宽度为 l e n = 1 len=1 len=1,那么它为叶子,若 l e n ≠ 1 len\not=1 len=1,则它有左右儿子。且根据3可知左右儿子宽度均不为 0 0 0

定理8

假设根节点深度为 0 0 0,宽度为 n n n的线段树中一个深度为 k k k的节点的宽度等于所有下式中的至少一个:
( ∘ k i = 1 h i ) ( n ) = ( h 1 ∘ h 2 ∘ . . . ∘ h k ) ( n ) \left(\underset{i=1}{\overset k\circ}h_i\right)(n)=(h_1\circ h_2\circ ...\circ h_k )(n) (i=1khi)(n)=(h1h2...hk)(n)

其中 h i ∈ { f , g } , f ( x ≠ 1 ) = ⌊ x 2 ⌋ , g ( x ≠ 1 ) = ⌈ x 2 ⌉ h_i\in\{f,g\},f(x\not=1)=\lfloor\frac x2\rfloor,g(x\not=1)=\lceil\frac x2\rceil hi{f,g},f(x=1)=2x,g(x=1)=2x

应用归纳法显然。

定理9

( ∘ k i = 1 h i ) ( x ) ≤ g ( k ) ( y ) \left(\underset{i=1}{\overset k\circ}h_i\right)(x)\leq g^{(k)}(y) (i=1khi)(x)g(k)(y),其中 x ≤ y x\leq y xy

应用归纳法显然。

定理10

一颗宽度为 2 k 2^k 2k的线段树上一个深度为 x x x的节点的宽度可以表示为 2 k 2 x = ( ∘ x i = 1 h i ) ( 2 k ) \frac{2^k}{2^x}=\left(\underset{i=1}{\overset x\circ}h_i\right)(2^k) 2x2k=(i=1xhi)(2k),其中任意 h i h_i hi可以自由的取到 f / g f/g f/g

也就是说此节点宽度对应的 h h h序列为所有可能的长度为 x x x h h h序列。

也就说明此线段树上存在这样一个深度为 x x x的节点,是 2 k 2 x = ( ∘ x i = 1 h i ) ( 2 k ) \frac{2^k}{2^x}=\left(\underset{i=1}{\overset x\circ}h_i\right)(2^k) 2x2k=(i=1xhi)(2k)的必要条件。

这说明存在一组 h h h使得 2 k 2 x = ( ∘ x i = 1 h i ) ( 2 k ) \frac{2^k}{2^x}=\left(\underset{i=1}{\overset x\circ}h_i\right)(2^k) 2x2k=(i=1xhi)(2k)是此线段树上存在深度为 x x x的节点的充分条件。

应用归纳法显然。

定理11

一颗宽度为 n n n的线段树的图形态,是宽度为 2 k = ⌈ log ⁡ 2 n ⌉ 2^{k=\lceil\log_2{n}\rceil} 2k=log2n的线段树图形态的一个包含根节点的生成树(根节点不变)。

这里指的不是同构,而是区分左右儿子方向的完全相同。

证明:
我们考虑线段树,宽度为 [ 1 , n ] [1,n] [1,n]

假设线段树中必定存在叶子节点 x x x,其深度为 d > k d>k d>k

假设存在这样的叶子节点,那我们知道 l e n x = ( ∘ d i = 1 h i ) ( n ) = 1 len_x=\left(\underset{i=1}{\overset d\circ}h_i\right)(n)=1 lenx=(i=1dhi)(n)=1

则: g ( d ) ( 2 k ) ≥ ( ∘ d i = 1 h i ) ( n ) = 1 g^{(d)}(2^k)\geq \left(\underset{i=1}{\overset d\circ}h_i\right)(n)=1 g(d)(2k)(i=1dhi)(n)=1

根据10,我们知道,这充分说明在宽度为 2 k 2^k 2k的线段树上存在一个节点其深度 > k >k >k,这显然是不可能的。因此矛盾。

这说明宽度为 n n n的线段树上没有任何一个节点的深度比宽度为 2 k 2^k 2k的线段树的节点的深度更大。而宽度为 2 k 2^k 2k的线段树是有 k + 1 k+1 k+1层节点的满二叉树,所以说明前者没有任何一个部分是后者没有的,因此得证。

定理12

由定理11可知:

宽度为 n n n的线段树的节点数,以及树高,均对应小于等于对应的 2 k 2^k 2k的线段树。

定理13

2 ⌈ log ⁡ 2 n ⌉ < 2 n 2^{\lceil\log_2n\rceil}< 2n 2log2n<2n

证明:
2 ⌈ log ⁡ 2 n ⌉ < 2 l o g 2 n + 1 = 2 n 2^{\lceil\log_2n\rceil}<2^{log_2n+1}=2n 2log2n<2log2n+1=2n

定理14

由5,12,13可知,动态开点线段树最多有 2 n − 1 2n-1 2n1个节点,所以空间可以开到 2 n 2n 2n

定理15

根节点、图形态和左右儿子方向完全相同的两颗二叉树,在堆式存储中占用的空间位置完全相同。

显然。

定理16

由定理15可知,我们只需要讨论宽度为 2 k = ⌈ log ⁡ 2 n ⌉ 2^{k=\lceil\log_2n\rceil} 2k=log2n的满二叉树的节点编号的最大值即可。

显然这个最大编号为 2 k + 1 − 1 2^{k+1}-1 2k+11,即 < 4 n − 1 <4n-1 <4n1。因此我们就知道了堆式存储二叉树的可能的节点编号最大值小于 4 n − 1 4n-1 4n1

后话

原来证明这东西这么麻烦的。

是不是有什么简单方法。

如果您知道请您联系我。

定理17

仿照定理11,容易发现线段树去除了最后一层之后是一个满二叉树。

后记

于是皆大欢喜。

你可能感兴趣的:(线段树,空间复杂性)