求二叉树父节点索引的多种写法
我们都知道堆结构有一个有趣的特性:对于数组 a 的每个元素,总有 a[k] <= a[2*k+1] 以及 a[k] <= a[2*k+2],假设 k 从 0 开始。
我们可以画出如下的二叉树,其中每个数字指的是元素的下标。
0
1 2
3 4 5 6
7 8 9 10 11 12 13 14
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
那么每个父节点的值都要比它的两个子节点小。
假设我们已经知道了子节点的下标,存在变量 pos 中,如果要求它父节点的下标,根据上面提到的堆的特性,可以将其减去一除以二之后取整,具体操作如下:
parentpos = int((pos - 1) / 2)
parentpos = (pos - 1) // 2
pos 为 29 或者 30 时 parentpos 都为 14
下面有另外两种写法:
parentpos = (pos - 1) >> 1
这个是针对二进制的右移一位运算,以数字 29 为例,其二进制为 11101,移位之后是 01110,也就是十进制的 14。以数字 28 为例,其二进制为 11100,移位之后也是 01110,十进制的 14。二进制决定奇偶数的最后一位在右移后直接消失,转换成十进制后的数也从类似2**2+2*3*+2**4
变成了2**1+2**2+2**3
的形式,前者正好可以写成后者乘二的结果。
下面分别用 timeit 模块在命令行模式下计算两种写法的运行效率:
C:\Users>python -m timeit "int((30 - 1) / 2)"
10000000 loops, best of 3: 0.134 usec per loop
C:\Users>python -m timeit "(30 - 1) >> 1"
100000000 loops, best of 3: 0.0107 usec per loop
C:\Users>python -m timeit "(30 - 1) // 2"
100000000 loops, best of 3: 0.0107 usec per loop
可以看到,采用 int 类型转换的写法会将运行时间从 0.0107 微妙增加到 0.134 微妙,是一个数量级的区别。
study
还是没明白,我先补课去 😆
刚才没写完,你重新看一下好了
zzz 这个有点意思,不过没太看懂 😥 太菜了