Gray Code实现

来源:互联网 发布:怖客用哪个软件可以看 编辑:程序博客网 时间:2024/05/21 17:20
问题:产生n位元的所有格雷码。

格雷码(Gray Code)是一个数列集合,每个数使用二进位来表示,假设使用n位元来表示每个数字,任两个数之间只有一个位元值不同。
例如以下为3位元的格雷码: 000 001 011 010 110 111 101 100 。
如果要产生n位元的格雷码,那么格雷码的个数为2^n.

假设原始的值从0开始,格雷码产生的规律是:第一步,改变最右边的位元值;第二步,改变右起第一个为1的位元的左边位元;第三步,第四步重复第一步和第二步,直到所有的格雷码产生完毕(换句话说,已经走了(2^n) - 1 步)。

用一个例子来说明:
假设产生3位元的格雷码,原始值位 000
第一步:改变最右边的位元值: 001
第二步:改变右起第一个为1的位元的左边位元: 011
第三步:改变最右边的位元值: 010
第四步:改变右起第一个为1的位元的左边位元: 110
第五步:改变最右边的位元值: 111
第六步:改变右起第一个为1的位元的左边位元: 101
第七步:改变最右边的位元值: 100

如果按照这个规则来生成格雷码,是没有问题的,但是这样做太复杂了。如果仔细观察格雷码的结构,我们会有以下发现:
1、除了最高位(左边第一位),格雷码的位元完全上下对称(看下面列表)。比如第一个格雷码与最后一个格雷码对称(除了第一位),第二个格雷码与倒数第二个对称,以此类推。
2、最小的重复单元是 0 , 1

000
001
011
010
110
111
101
100

所以,在实现的时候,我们完全可以利用递归,在每一层前面加上0或者1,然后就可以列出所有的格雷码。
比如:
第一步:产生 0, 1 两个字符串。
第二步:在第一步的基础上,每一个字符串都加上0和1,但是每次只能加一个,所以得做两次。这样就变成了 00,01,11,10 (注意对称)。
第三步:在第二步的基础上,再给每个字符串都加上0和1,同样,每次只能加一个,这样就变成了 000,001,011,010,110,111,101,100。
好了,这样就把3位元格雷码生成好了。
如果要生成4位元格雷码,我们只需要在3位元格雷码上再加一层0,1就可以了: 0000,0001,0011,0010,0110,0111,0101,0100,1100,1101,1110,1010,0111,1001,1000.

也就是说,n位元格雷码是基于n-1位元格雷码产生的。

如果能够理解上面的部分,下面部分的代码实现就很容易理解了。
[java] view plain copy
  1. public String[] GrayCode(int n) {  
  2.   
  3.     // produce 2^n grade codes  
  4.     String[] graycode = new String[(int) Math.pow(2, n)];  
  5.   
  6.     if (n == 1) {  
  7.         graycode[0] = "0";  
  8.         graycode[1] = "1";  
  9.         return graycode;  
  10.     }  
  11.   
  12.     String[] last = GrayCode(n - 1);  
  13.   
  14.     for (int i = 0; i < last.length; i++) {  
  15.         graycode[i] = "0" + last[i];  
  16.         graycode[graycode.length - 1 - i] = "1" + last[i];  
  17.     }  
  18.   
  19.     return graycode;  
  20. }  
格雷码还有一种实现方式是根据这个公式来的 G(n) =  B(n) XOR B(n+1), 这也是格雷码和二进制码的转换公式。代码如下:
[java] view plain copy
  1. public void getGrayCode(int bitNum){  
  2.     for(int i = 0; i < (int)Math.pow(2, bitNum); i++){  
  3.         int grayCode = (i >> 1) ^ i;  
  4.         System.out.println(num2Binary(grayCode, bitNum));  
  5.     }  
  6. }  
  7. public String num2Binary(int num, int bitNum){  
  8.     String ret = "";  
  9.     for(int i = bitNum-1; i >= 0; i--){  
  10.         ret += (num >> i) & 1;  
  11.     }  
  12.     return ret;  
  13. }  

这是一道google 的面试题,以上代码均是网友peking2 和 SEwind520写成。原题还要求把二进制码转成十进制数。

出处:CSDN

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 卡杰文具密码本如果忘记密码怎么办 火狐浏览器阻止要访问的网页怎么办 点我达被永久停用了怎么办 刚下的软件点开系统显示停用怎么办 红酒洋酒啤酒一起喝胃不舒服怎么办 儿子13岁初一不想读书了怎么办 微信不小心点了注册新账号怎么办 在京东买东西商家不发货怎么办 在京东买东西坏了商家不退货怎么办 苯扎氯铵溶液不小心喝了一口怎么办 苯扎氯铵溶液没有稀释就用了怎么办 牛油果切开了但是没熟怎么办 手机安装程序时解析包出错怎么办 因俩人不合适分手了很难受怎么办 中考结束后成绩不好的该怎么办 在京东自营药房买药没有处方怎么办 平安普惠账号不可以注销怎么办? 京东购物非自营货没到降价了怎么办 实体店商家不承认卖的是假货怎么办 衣服上的装饰圆扣掉下来了怎么办 没在京东买东西却收到退款怎么办 小米分期付款买的手机不要了怎么办 唯品会在线支付后商品有问题怎么办 红米手机把时间删了怎么办 红米桌面上的时间删了怎么办 华为手机玩游戏老是闪退怎么办 别人家无线网距离太远信号差怎么办 微信公众号交话费交错了怎么办 手机卡里还有话费销户的话怎么办 号码忘记交话费变成空号怎么办 多屏互动没办法隔空播放怎么办? 一个人长期受一件事的打击怎么办 物流信息显示快递被别人签收怎么办 现在打工的人被领导骂怎么办 加密狗丢了打不开软件了怎么办 手机微信可以打开网页打不开怎么办 手机中国网打开网速慢该怎么办 在韩国用中国软件网速特别慢怎么办 淘宝退货快递一直没显示到货怎么办 高二美术生集训时文化课怎么办 唯品会不支持7天无理由退货怎么办