您的位置:首页 > 其它

[underscore源码学习]——`>>` 运算符和二分查找

2017-09-07 16:32 330 查看
这是一篇记录学习 underscore v0.0.5 的fragment,觉得有点意思,和大家分享一下。

先看_.sortedIndex的源码,它用来确定 obj 在 array中的位置(array升序):

_.sortedIndex = function(array, obj, iterator) {
iterator = iterator || _.identity;
var low = 0, high = array.length;
while (low < high) {
var mid = (low + high) >> 1;
iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
}
return low;
};

_.identity = function(value) {return value};

代码虽短却两个我们不常用的姿势:
>>
运算符和二分查找。

右移运算符 >>

右移运算符的计算规则如下


int a = 8; int b = a >> 1; // b ?

先将 8 转化为二进制数,(在 C 中,32位操作系统下int 类型占2个字节,即16bit)

0000 0000 0000 1000

整体右移 1 位,高位不足添 0

0000 0000 0000 0100

再将新的二进制数转化为十进制得到 b = 4;


那么,代码
var mid = (low + high) >> 1
mid 变量取值是多少呢?因为好(dou)奇(bi),我作了一点尝试:

0 >> 1  // 0
1 >> 1  // 0
2 >> 1  // 1
3 >> 1  // 1
4 >> 1  // 2
5 >> 1  // 2
...
10 >> 1 // 5
11 >> 1 // 5
12 >> 1 // 6
...

由归纳法可得
a >> 1 === parseInt(a / 2)
。这点相信眼尖的同学早就看出来了。

二分查找

既然我们已经知晓
mid >> 1 === parseInt((low + high) / 2)
,我们再来回顾下代码片段:

while (low < high) {
var mid = (low + high) >> 1;                                        // (1)
iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; // (2)
}

(1)我们已经知晓,mid 取得了一个中间数值,在(2)中是一个三元运算符,解释起来,就是用一个有序数组 array 的中间数和目标数进行比较,则如果中间数比目标数小,就只需要比较中间数右侧的值,反之亦然。然后继续循环...

等价于下面的代码,由此差距立显:

while (low < high) {
var mid = (low + high) >> 1;
var a = iterator(array[mid]);
var b = iterator(obj)
if(a == b) {
return mid;
} else if(a < b) {
low = mid + 1;
} else {
high = mid
}
}

题外话

内容照理说已经讲完了,但对于
>>
运算符我还是有些疑虑。既然有
a >> 1 === parseInt(a / 2)
那么可否假设
a >> 2 === parseInt(a / (2*2))
呢?

0 >> 2  // 0
3 >> 2  // 0

4 >> 2  // 1
7 >> 2  // 1

8 >> 2  // 2
11 >> 2 // 2

12 >> 2 // 3

继而
a >> 3 === parseInt(a / (2*2*2))
,可得
a >> n === parseInt(a / (X))
X 为 2 的 n 次方。

左移运算符 <<

与右移运算符相对的叫左移运算符,记为
<<
,相信它也不是吃干饭的。

有了前面的铺垫,我这里一步到位,假设有
a << n === parseInt(a * (X))
X 为 2 的 n 次方。简单验证下:

1 << 1 // 1*2 = 2
2 << 1 // 2*2 = 4
3 << 2 // 3 * (2*2) = 12
5 << 4 // 5 * (2*2*2*2) = 80
...

最后的最后,由于水平有限(大家看出来了,忍住不要笑:-D),文章内容连蒙带猜,没有经过特别严谨的证明,欢迎拍砖!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: