在一組數的編碼中,若任意兩個相鄰的代碼只有一個二進制數不同,則稱這種編碼爲格雷碼(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”,只是字符的連接,這一點比較重要!!!個人還是覺得第二種方法比較好。。。