在一组数的编码中,若任意两个相邻的代码只有一个二进制数不同,则称这种编码为格雷码(Gary Code),请编写一个函数,使用递归的方法生成N位的格雷码。给定一个整数n,请返回n位的格雷码,顺序为从0开始。
测试样例:
输入:1
返回:“0”,“1”。
(1)首先给出二进制--->格雷码的转换:
此方法从对应的n位二进制字中直接得到n位格雷码字,步骤如下:
(1)对n位二进制的码字,从右向左,以0到n- 1编号
(2)如果二进制码字的第 i 位和第i + 1位相同,则对应的格雷码第 i 位为0,否则为1(当i + 1 = n时,二进制码的第n位被认为是0,即第n - 1位不变)
例如:
二进制码0101,为4位数,所以其所转化为格雷也必为4位数,因此可取转成之二进制位码第五位为0,即0 b3 b2 b1 b0。
根据上面的方法可得出0101对应的格雷码为0111。
(2)格雷码--->二进制码(解码)
从左边第二位起,将每位与左边一位解码后的值异或,作为该位解码后的值(最左边一位依然不变)。依次异或,直到最低位。依次异或转换后的值(二进制数)就是格雷码转换后的二进制码的值。
例如:格雷码1010
(a)最左边的1不变,则二进制位 1 b2 b1 b0
(b)b2 = 1 异或 0 = 1,则二进制为 1 1 b1 b0
(c)b1 = 1 异或 1 = 0,则二进制为 1 1 0 b0
(d)b0 = 0 异或 0 = 1,则二进制为 1 1 0 0
下面给出我自己编写的转换程序:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define N 100 //获取整数的二进制码 void getbinary(int x,char *s) { if(x == 0){ *s = 0 + '0'; return; } if(x){ *s = x % 2 + 48; x = x / 2; getbinary(x,s + 1); } } //获取整数的格雷码 // // B = 0 b3 b2 b1 b0 // \ / \ / \ / \ / // G = g3 g2 g1 g0 // // void getgray_code(int x) { int n = x >> 1; int len1,len2,i; char s1[N] = {0}; char s2[N] = {0}; getbinary(x,s1); getbinary(n,s2); len1 = strlen(s1); len2 = strlen(s2); for(i = len2 - 1;i >= 0;i--){ s1[i] = ((s1[i] - '0') ^ (s2[i] - '0')) + 48; } for(i = len1 - 1;i >= 0;i--){ printf("%c ",s1[i]); } printf("\n"); } int main(int argc,char **argv) { int n; int len; int i ; char s[N] = {0}; while(1){ printf("请输入一个整数n:(-1 代表退出)\n"); scanf("%d",&n); if(n == -1){ printf("error!\n"); exit(1); } #if 1 printf("binary code:\n"); getbinary(n,s); len = strlen(s); for(i = len - 1;i >= 0;i--){ printf("%c ",s[i]); } printf("\n"); #endif printf("gray code:\n"); getgray_code(n); } return 0; }
该程序将二进制码和格雷码都进行了打印,在程序中用到字符数组来进行存储。。。
下面给出另一种解法:该思路就是整数n的格雷码等于整数n - 1的格雷码前一部分加“0”,后一部分加上“1”.
具体的代码如下:
#include <iostream> #include <string> #include <stdlib.h> using namespace std; //格雷码 string * getgray(int n) { int count = 1 << n; int len; string *strArr = new string[count]; if(n == 0){ cout<<"格雷码转换n值大于0!!!"<<endl; exit(1); } if(n == 1){ strArr[0] = "0"; strArr[1] = "1"; return strArr; }else{ string *strArr1 = getgray(n - 1); len = count / 2; for(int i = 0;i< len;i++){ strArr[i] = "0" + strArr1[i]; } for(int i = 0;i < len;i++){ strArr[count - i - 1] = "1" + strArr1[i]; } return strArr; } } int main(int argc,char**argv) { int n; int len; int i; string *b; while(1){ cout<<"请输入整数n:(-1 == quit)"<<endl; cin>>n; if(n == -1){ cout<<"error!"<<endl; exit(1); } len = 1 << n; b = getgray(n); #if 0 for(int i = 0;i < len;i++){ cout<<b[i]<<endl; } #endif cout<<b[n]<<endl; b = NULL; } }
这里使用到了C++中的string类,还要说明一下string对象进行加法时,比如:“0” + “1” = “01”,只是字符的连接,这一点比较重要!!!个人还是觉得第二种方法比较好。。。