簡介
Gray Code,是幾十年前貝爾實驗室的科學家Frank Gray提出的一種編碼方案,當時主要用于傳輸信號以防止出錯。Gray Code 除了在通信,硬件設計領域中應用以外,在計算機相關科學的其他方面也有廣泛的應用,例如按序產生集合的所有子集。
Gray Code實現按序產生集合的所有子集
子集的按序產生,這個概念很簡單,舉個例子,假設我們的集合為{a,b,c},那么按序產生的子集應該是:
空集 (000) —— 0(編號 從0開始按順序排序)
a (100) —— 1
ab (110) —— 2
abc (111) —— 3
ac
b
bc
c
那么Gray Code是如何產生這樣的序列的呢?
Gray Code的思想非常的巧妙,我們可以將所產生的子集編號(范圍為0~2^n-1),第一個子集為空集(編號為0,是偶數)。在其后的每個子集由前一個子集來決定,如果前一個子集編號為偶數,那么則改變前一個子集的第一位(從左邊數)的二進制值(0變成1或者1變成0)作為新的子集。如果前一個子集的編號為奇數,那么就將前一個子集二進制左邊數第一個1后面的那位改變其值(0變成1或者1變成0)作為新的子集。
根據上面的Gray Code的思想,還是以集合{a,b,c}為例,第一個子集(000)的編號為0(偶數),推算出第二個子集是第一個子集改變左邊數的第一位的數值所產生,為100,也就是a(只取為1的字符,a為最左邊的字符對應100中的1)。那么根據第二個子集的編號1(奇數),推算出第三個子集是由第二個子集改變從左數第一個1后面那一位的值所產生(100->110),那么110對應的是ab。后面的子集都以此類推即可全部按順序產生。
Gray Code非遞歸的C語言實現
以下代碼在VS2008下調試通過
- int sum(int n)
- {
- if(1<=n) return n+sum(n-1);
- else return 0;
- }
-
- void gray(char *ptr)
- {
- int len=strlen(ptr);
- int num=(1<<len);
- // printf("num=%d \n",num);
- int i,j,k;
- int mod,tmp,mask,tmp1,tmp2;
- mask=1<<len-1;
- // printf("mask=%d \n",mask);
- mod=0;//(1<<len)-1;
- for(i=0;i<num-1;i++)
- {
- if(i%2==0)
- {
- tmp=mod&mask;
- // printf("tmp=%d ",tmp);
- if(0!=tmp) {mod=mod&(~mask);}
- else {mod=mod|(mask);}
- }
- else
- {
- tmp1=1<<(len-1);
- for(j=0;j<len;j++)
- {
- // printf(" in else");
- if(mod&tmp1) break;
- tmp1=tmp1>>1;
- // printf("tmp1=%d ",tmp1);
- }
- tmp1=tmp1>>1;
- // printf(">>1 tmp1=%d ",tmp1);
- if(tmp1!=0)
- {
- tmp=mod&tmp1;
- if(0!=tmp) {mod=mod&(~tmp1);}
- else {mod=mod|(tmp1);}
- }
- }
- tmp2=1<<len-1;
- for(k=0;k<len;k++)
- {
- if(mod&tmp2) printf("%c",ptr[k]);
- tmp2=tmp2>>1;
- }
- printf("\n");
- }
- }
-
- int main()
- {
- // printf(" result=%d ",sum(4));
- char *p="abcd";
- gray(p);
- system("pause");
- }