在 redis 源码中 dictScan 算法中用到了用到了非常经典的二进制反转算法,该算法对二进制的反转高效而实用,同时对于理解位运算也有非常大的帮助。先呈现源码:

/* Function to reverse bits. Algorithm from:
* http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel */
static unsigned long rev(unsigned long v) {
unsigned long s = * sizeof(v); // bit size; must be power of 2, 此处为32
unsigned long mask = ~; //
while ((s >>= ) > ) { //循环5次
mask ^= (mask << s); // 取得想要局部对换的掩码
// 左移s位并保留低位,右移s位并保留高位,然后两部分或运算
// 这里是实现移位的精华所在,结合下面打印信息有助于理解
v = ((v >> s) & mask) | ((v << s) & ~mask);
}
return v;
}

源码的总体思路是:用迭代的思想将32位的二进制数先将前16位和后16位对换,然后将前16位二进制数的前8位和后8位对换,后16位类似,再讲前8位的二进制数的前4位和后4位对换。。。最终实现整个二进制的反转。当然这里的实现过程非常巧妙,这也是位运算神秘而神奇的特点,理解这个过程,对于理解计算机的原理都有很大的帮助。

但上面的描述得还是比较抽象,还不足以帮助理解上面的算法实现,下面来对算法的实现过程加一些打印,以便更好的理解算法的实现原理。

#include <iostream>

using namespace std;

// 打印二进制
void printBits(const unsigned long v) {
unsigned long mask = << ;
while ((mask) > ) {
int bit = (v & mask) ? : ;
cout << bit;
mask >>= ;
}
cout << endl;
} static unsigned long rev_test(unsigned long v) {
unsigned long s = * sizeof(v); // bit size; must be power of 2
unsigned long mask = ~;
cout << "s : ";
printBits(s);
cout << "mask : ";
printBits(mask); while ((s >>= ) > ) {
cout << endl;
cout << "s : ";
printBits(s);
cout << "mask : ";
printBits(mask);
cout << "mask<<s: ";
printBits(mask << s);
mask ^= (mask << s);
cout << "mask^= : ";
printBits(mask);
v = ((v >> s) & mask) | ((v << s) & ~mask);
cout << "v : ";
printBits(v);
} return v;
} int main() {
unsigned long v = ;
cout << "v : ";
printBits(v);
cout << endl;
v = rev_test(v);
cout << endl;
cout << "v : ";
printBits(v); cout << endl << endl << endl; system("pause");
return ;
}

运行上述程序结果如下:

最新文章

  1. ZooKeeper学习总结 第二篇:ZooKeeper深入探讨(转载)
  2. 前端菜鸟的编程之路之css的用法
  3. java常用方法总结
  4. Easyui Combotree问题及其相关
  5. Throwable和Exception的区别
  6. WPF动画 storyboard
  7. eclipse下安装Extjs的插件spket
  8. JavaScript trim 实现(去除字符串首尾指定字符)
  9. 【随记】关于List集合用Linq GroupBy分组过后的遍历小记
  10. 在IntelliJ IDEA里创建简单的基于Maven的SpringMVC项目
  11. node.js使用scp2来进行scp操作
  12. [Treap][学习笔记]
  13. AKA “Project” Milestone
  14. 融云亮相GDG谷歌女性开发者大会 揭秘IMSDK网络优化策略
  15. viewport定义,弹性布局,响应式布局及LESS和SASS框架应用
  16. Python创建空DataFrame及添加行数据
  17. C#、AE开发入门之打开CAD文件并显示
  18. PageHelper的使用方法
  19. CentOS7单节点部署redis主从复制和sentinel
  20. Mantis邮件服务器配置

热门文章

  1. sqlite3-python
  2. contents() 查找匹配元素内部所有的子节点(包括文本节点)。如果元素是一个iframe,则查找文档内容
  3. java+http文件夹上传
  4. 阿里云Ubuntu安装LNMP环境之PHP7
  5. td中文字居中
  6. 【java设计模式】-01设计模式简介
  7. 一、微服务(Microservices)【翻译】
  8. C#操作 Access 2013(.accdb)的方法
  9. java随机生成6位随机数 5位随机数 4位随机数
  10. Liferay使用Structure和Template制作Video Portlet