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

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

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

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

  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. // 打印二进制
  6. void printBits(const unsigned long v) {
  7. unsigned long mask = << ;
  8. while ((mask) > ) {
  9. int bit = (v & mask) ? : ;
  10. cout << bit;
  11. mask >>= ;
  12. }
  13. cout << endl;
  14. }
  15.  
  16. static unsigned long rev_test(unsigned long v) {
  17. unsigned long s = * sizeof(v); // bit size; must be power of 2
  18. unsigned long mask = ~;
  19. cout << "s : ";
  20. printBits(s);
  21. cout << "mask : ";
  22. printBits(mask);
  23.  
  24. while ((s >>= ) > ) {
  25. cout << endl;
  26. cout << "s : ";
  27. printBits(s);
  28. cout << "mask : ";
  29. printBits(mask);
  30. cout << "mask<<s: ";
  31. printBits(mask << s);
  32. mask ^= (mask << s);
  33. cout << "mask^= : ";
  34. printBits(mask);
  35. v = ((v >> s) & mask) | ((v << s) & ~mask);
  36. cout << "v : ";
  37. printBits(v);
  38. }
  39.  
  40. return v;
  41. }
  42.  
  43. int main() {
  44. unsigned long v = ;
  45. cout << "v : ";
  46. printBits(v);
  47. cout << endl;
  48. v = rev_test(v);
  49. cout << endl;
  50. cout << "v : ";
  51. printBits(v);
  52.  
  53. cout << endl << endl << endl;
  54.  
  55. system("pause");
  56. return ;
  57. }

运行上述程序结果如下:

Redis二进制反转算法分析的更多相关文章

  1. Redis二进制安全

    为了便于理解,举一个例子: 在很多编辑器中,都会默认/n是换行字符,也就意味着一串字符存进去,涉及/n都会做一个默认的转义处理,这在编辑语言中,C也有这个特性,例如字符串Hello,\0 World! ...

  2. 关于Redis 二进制内容的 可视化尝试

    二进制内容的 能否可视化?  网上的资料比较少啊! -------------------------------------------------------------------------- ...

  3. Redis二进制安全概念

    二进制安全是指,在传输数据时,保证二进制数据的信息安全,也就是不被篡改.破译等,如果被攻击,能够及时检测出来. 二进制安全包含了密码学的一些东西,比如加解密.签名等. 举个例子,你把数据1111000 ...

  4. ACM_Reverse Bits(反转二进制)

    Reverse Bits Time Limit: 2000/1000ms (Java/Others) Problem Description: Reverse bits of a given 32 b ...

  5. [转]Redis实现分析

    Redis实现分析 浏览次数:1018次 KITERUNNER_T 2014年10月19日 字号: 大 中 小 分享到: QQ空间 新浪微博 腾讯微博 人人网 豆瓣网 开心网 更多 1   1 环境准 ...

  6. Redis 5种主要数据类型和命令

    redis是键值对的数据库,有5中主要数据类型: 字符串类型(string),散列类型(hash),列表类型(list),集合类型(set),有序集合类型(zset) 几个基本的命令: KEYS * ...

  7. 预热一下吧《实现Redis消息队列》

    应用场景 为什么要用redis?二进制存储.java序列化传输.IO连接数高.连接频繁 一.序列化 这里编写了一个java序列化的工具,主要是将对象转化为byte数组,和根据byte数组反序列化成ja ...

  8. go中redis使用小结

    最近做了个关于redis的项目,那么就整理下遇到和未遇到的问题 1.redis的简介安装 2.redis的数据结构 3.Redis基本使用 4.Redis的并发 5.Redis的落地 一.redis的 ...

  9. Linux+Redis实战教程_day02_3、redis数据类型_4、String命令_5、hash命令_6、java操作redis数据库技术

    3. redis数据类型[重点] redis 使用的是键值对保存数据.(map) key:全部都是字符串 value:有五种数据类型 Key名:自定义,key名不要过长,否则影响使用效率 Key名不要 ...

随机推荐

  1. SQL Server的GO语句

    https://www.cnblogs.com/cbattle/p/8784537.html go语句经常加在create.exec.drop等前面.

  2. Linq to XML - C#生成XML

    1.System.Xml.XmlDocument  XML file转成字符串  string path3 = @"C:\Users\test.xml";  XmlDocument ...

  3. 【luoguP2158】 [SDOI2008]仪仗队

    题目描述 作为体育委员,C君负责这次运动会仪仗队的训练.仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图 ...

  4. 「BZOJ 5161」最长上升子序列「状压DP」

    题意 求一个\(1\sim n\)的排列LIS的期望长度,\(n\leq 28\) 题解 考虑朴素的LIS:\(f[i] = min(f[j]) + 1\) 记\(mx[i]\)为\(f\)的前缀最大 ...

  5. poj1737

    Connected Graph POJ - 1737 An undirected graph is a set V of vertices and a set of E∈{V*V} edges.An ...

  6. 学数据分析到底要不要掌握Linux-Python基础前传(2)

    使用Python的数据分析师到底要不要掌握Linux? 对于上面的问题,大部分的答案是Python数据分析在windows的环境下跑跑就可以了,没有必要再花时间来学习Linux; 这里jacky有一个 ...

  7. tracert命令与tracert (IP地址)-d有什么区别?

    他们的意义基本相同,都是路由追踪,返回从源到目标的路由情况:但tracert -d不解析各路由器的名称,只返回路由器的IP地址.而tracert 不仅返回各路由器的IP地址,而且返回其名称.简单来说, ...

  8. docker打包项目部署

    1.首先在本地安装docker,步骤可参考https://www.cnblogs.com/conswin/p/11055853.html 2.在对应项目目录下增加Dockerfile文件,其内容可参考 ...

  9. shell [ ] 和 [[ ]] 区别

    [参考文章]:shell if [[ ]]和[ ]区别 || && [参考文章]:Shell test 命令 1. [ ] 和 test test  等同于 [ ] 可用于判断某个条件 ...

  10. 20182303 2019-2020-1 《数据结构与面向对象程序设计》第2&3周学习总结

    目录 教材学习内容总结 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考试错题总结 结对及互评 点评 学习进度条 教材学习内容总结 教材第二章内容 学习Java基本数据类型以及 ...