Gray Code简介及生成
在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code),另外由于最大数与最小数之间也仅一位数不同,即“首尾相连”,因此又称循环码或反射码。
-
格雷码是一种绝对编码方式,典型格雷码是一种具有反射特性和循环特性的单步自补码,它的循环、单步特性消除了随机取数时出现重大误差的可能,它的反射、自补特性使得求反非常方便。
-
典型格雷码是一种采用绝对编码方式的准权码,其权的绝对值为2^i-1(设最低位i=1)。
-
格雷码的十进制数奇偶性与其码字中1的个数的奇偶性相同。
根据格雷码的特性,其每一位的编码都能由前一位编码得到,方法是做镜面对称,然后在最左侧上半部分补0,下半部分补1,可以通过数组简单模拟得到,缺点是数字大的时候就存不下来了
#include <cstdio>
#include <cstring>
#define num 20
bool g[1 << num][num];
int main()
{
g[0][0] = 0;
g[1][0] = 1;
for(int i = 1; i < num; i++)
{
int k = 0;
while(k < i)
{
for(int j1 = 0; j1 < (1 << i); j1++)
{
int j2 = (1 << (i + 1)) - 1 - j1;
g[j2][k] = g[j1][k];
}
k++;
}
for(int j1 = 0; j1 < (1 << i); j1++)
{
int j2 = (1 << (i + 1)) - 1 - j1;
g[j1][k] = 0;
g[j2][k] = 1;
}
k++;
}
int n;
while(true)
{
printf("Please input\nn = ");
scanf("%d", &n);
if(n == 0)
break;
printf("\nShow %d Gray Code :\n", n);
for(int i = 0; i < (1 << n); i++)
{
for(int j = n - 1; j >= 0; j--)
printf("%d ", g[i][j]);
printf("\n");
}
printf("\n");
}
}
老师出的题是输出无穷大位数的格雷码,显然不能使用任何数据结构,我们再回到格雷码,观察其规律可以发现对于同一位数的第奇数组和偶数组序列,奇数组是都是先0后1,偶数组都是先1后0,通过这个规律和格雷码本身的性质我们可以直接计算出格雷码
#include <cstdio>
#define judge (i % (1 << j)) < ((1 << j) >> 1)
int main()
{
int bit;
while(true)
{
printf("Please input\nn = ");
scanf("%d", &bit);
if(bit == 0)
break;
printf("\nShow %d Gray Code :\n", bit);
int n = (1 << bit);
for(int i = 0; i < n; i++)
for(int j = bit; j >= 1; j--)
if((i / (1 << j)) & 1)
printf("%d%c", judge ? 1 : 0, j == 1 ? '\n' : ' ');
else
printf("%d%c", judge ? 0 : 1, j == 1 ? '\n' : ' ');
printf("\n");
}
}