格雷码的生成

格雷码(Gray Code)

格雷码:在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码,另外由于最大数与最小数之间也仅一位数不同,即“首尾相连”,因此又称循环码或反射码。

DecimalBinaryGrayGray as decimal
00000000
10010011
20100113
30110102
41001106
51011117
61101015
71111004

那么当给你一个数n时,你怎么生成n位格雷码呢?


假设原始的值从0开始,格雷码产生的规律是:
1.改变最右边的位元值。
2.改变右起第一个为1的位元的左边位元。
3.重复1。
4.重复2。
直到所有的格雷码产生完毕。
eg:假设产生3位元的格雷码
原始值位 000
第一步:改变最右边的位元值: 001
第二步:改变右起第一个为1的位元的左边位元: 011
第三步:改变最右边的位元值: 010
第四步:改变右起第一个为1的位元的左边位元: 110
第五步:改变最右边的位元值: 111
第六步:改变右起第一个为1的位元的左边位元: 101
第七步:改变最右边的位元值: 100

vector<string> prograycode(int n)
{
    int num(1 << n);
    vector<string> graycode;
    string start(n, '0');
    graycode.push_back(start);
    num -= 1;
    int state = 0;
    while(num > 0)
    {
        switch(state)
        {
        case 0 :
            start = start.replace(n-1, 1, start[n-1] == '0' ? "1" : "0");
            graycode.push_back(start);
            state = 1;
            break;

        case 1:
            int pos = start.find_last_of('1') - 1;
            start = start.replace(pos, 1, start[pos] == '0' ? "1" : "0");
            graycode.push_back(start);
            state = 0;
            break;
        }
        num--;
    }
    return graycode;
}

上面的方法是最基础最原始的方法,但是实现过程较为繁琐。


另一种方法:假设已经存在了n-1位的格雷码序列,那么只需要在n-1位格雷码的前面加上“0”和“1”就可以生成n位的格雷码,因此,自然而然的想到使用递归来实现。

vector<string> proGraycode(int n)
{
    vector<string> graycode(1 << n);
    if(n == 1)
    {
        graycode[0] = "0";
        graycode[1] = "1";
        return graycode;
    }

    vector<string> last = proGraycode(n-1);

    for(int i = 0; i < (int)last.size(); ++i)
    {
        graycode[i] = "0" + last[i];
        graycode[graycode.size() - 1- i] = "1" + last[i];
    }

    return graycode;
}

补充:格雷码与二进制编码的相互转换。
G(i) = B(i) XOR B(i+1) 即格雷码的第i位等于二进制编码的第i位与第i+1位异或,G的最高位保持B的最高位不变
eg:二进制01101转换成格雷码为01011
0 1 1 0 1
xor * 0 1 1 0
———————— *表示该位不变
0 1 0 1 1


博文参考于:格雷码的实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值