#每日一題#騰訊筆試題

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

發佈了65 篇原創文章 · 獲贊 19 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章