[underscore源码学习]——`>>` 运算符和二分查找
2017-09-07 16:32
330 查看
这是一篇记录学习 underscore v0.0.5 的fragment,觉得有点意思,和大家分享一下。
先看_.sortedIndex的源码,它用来确定 obj 在 array中的位置(array升序):
代码虽短却两个我们不常用的姿势:
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;
那么,代码
由归纳法可得
(1)我们已经知晓,mid 取得了一个中间数值,在(2)中是一个三元运算符,解释起来,就是用一个有序数组 array 的中间数和目标数进行比较,则如果中间数比目标数小,就只需要比较中间数右侧的值,反之亦然。然后继续循环...
等价于下面的代码,由此差距立显:
继而
有了前面的铺垫,我这里一步到位,假设有
最后的最后,由于水平有限(大家看出来了,忍住不要笑:-D),文章内容连蒙带猜,没有经过特别严谨的证明,欢迎拍砖!!!
先看_.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) >> 1mid 变量取值是多少呢?因为好(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),文章内容连蒙带猜,没有经过特别严谨的证明,欢迎拍砖!!!
相关文章推荐
- C源码@数据结构与算法->二分查找树(Binary Search Tree)
- 查找(二):二分查找----<学习总结>
- 二分查找(Binary Search)需要注意的问题,以及在数据库内核中的实现[谁有源码麻烦贴过来个链接学习学习]
- List<T>线性查找和二分查找BinarySearch效率分析
- 算法导论学习2.3-5 二分查找的递归形式
- 二分查找的递归算法(附源码)_AX
- <<精通Spring2.x>>笔记:第2章学习源码
- <学习记录>Queue源码学习
- 【二分查找】学习总结
- 算法学习---基本数据类型的数组二分查找实现
- Delphi-IOCP学习笔记<九>======性能测试和IOCP源码下载<5000个连接数>
- java的Collections中二分查找源码分析
- 二分查找bsearch.c源码分析
- Tinyhttpd源码学习(httpd.c)<四>
- JavaScript系统学习之一 <基本语法,运算符,流程控制语句>
- Java学习资料-Java常用算法-二分查找算法
- 算法学习---基本数据类型的数组二分查找实现
- 折半查找<二分查找>
- 二分查找【重复学习】
- C#学习笔记—数组的折半查找(二分查找)