1、什么是格雷码
Gray Code是一个数列集合,每个数使用二进制来表示,假设使用n位元来表示每个数字,那么任两个数之间只有一个位元值不同。
例如: 生成4位元的格雷码就是: 0000 0001 0011 0010 0110 0111 0101 0100 1100 1101 1111 1110 1010 1011 1001 1000
Gray Code的顺序并不是唯一的,可以是上面的所形成的数列的任意一种。Gray Code是由贝尔实验室的Frank Gray在1940年代提出的,用来在使用PCM(Pusle Code Modulation)方法传送讯号时避免出错,并于1953年三月十七日取得美国专利。如果要产生n位的格雷码,那么格雷码的个数为2^n个。
2、生成格雷码的原理
假设原始的值从0开始,格雷码产生的规律是:
第一步,改变最右边的位元值;
第二步,改变右边起第一个为1的位元的左边的位元;
第三步,第四步重复第一步和第二步,直到所有的格雷码产生完毕
举个例子来将:生成一个3位元的格雷码,假设原始值为 000
第一步: 改变最右边的位元值,则生成:001
第二步:改变右边起第一个为1的位元的左边的位元值,则生成011
第三步:改变最右边的位元值,则生成:010
第四步:改变右边起第一个为1的位元的左边的位元值,则生成110
第五步:改变最右边的位元值,则生成:111
第六步:改变右边起第一为1的位元的左边位元值:101
第七步:改变最右边的位元值,则生成:100
最后,3位元的格雷码全部生成。
按照这格雷码生成的规律,我们可以编写生成格雷码的代码(请看C语言版)
3、格雷码的实现
1、C语言实现格雷码(深度优先遍历)
#include <stdio.h>
#include <malloc.h>
void grayCode(char *a, int size, int index);
void grayCode(char *a, int size, int index){
if(index == size){
//到达底部就输出
printf("%s\n", a);
}else{
//深度优先遍历
grayCode(a, size, index+1);
if(a[index] == '0'){
a[index] = '1';
}else{
//把当前为逆转
a[index] = '0';
}
//继续向下搜索
grayCode(a, size, index+1);
}
}
void main(void){
char * arr = NULL;
int index = 0;
arr = (char *)calloc(sizeof(char), 4);
//先给字符串中没一位都赋值为'0';
for(index = 0 ; index < 4; ++index){
arr[index] = '0';
}
//生成格雷码
grayCode(arr, 4, 0);
}
看代码时,请看代码注释,会有对深度优先遍历解决生成格雷码有更进一步的理解。
2、Java实现格雷码(递归)
我们仔细观察一个3位元的格雷码:
000
001
011
010
110
111
101
100
仔细观察,如果除去最高位(最左边的第一位),格雷码中是上下对称的,所以我们完全可以使用递归的方法,在每一层的前面加上0或1,所以我们可以分析:
1、产生0、1两个字符串。
2、在第一步的基础上,每一个字符串都加上0 和1 ,所以就生成了00、01、10、11
3、在第二步的基础上,每一个字符串再加上0和1,所以就生成了000、001、010、011、100、101、110、111
所以3元的格雷码就生成了, 所以我们可以找到规律n位元格雷码是基于n-1位元格雷码产生的。
知道了这规律之后,就可以写出java的实现了:
public class GrayCode{
public static String[] GrayCode(int n){
// 生成 2^n个存储空间用于保存生成格雷码的种类
String[] grayCode = new String[(int)Math.pow(2, n)];
//如果是生成一位的格雷码,那么就是直接 返回 两种情况
if(n ==1){
grayCode[0] = "0";
grayCode[1] = "1";
return grayCode;
}
//求取n-1 位的格雷码
String[] last = GrayCode(n-1);
//拼接字符串,因为格雷码除去最高位为0或者为1 外,其余的都是对称的。所以
//后面的才有 grayCode[grayCode.length-1-i] = "1" + alst[i];
for(int i = 0; i < last.length; ++i){
grayCode[i] = "0" + last[i];
grayCode[grayCode.length -1 -i] = "1" + last[i];
}
return grayCode;
}
public static void main(String[] args){
String[] arr = GrayCode(4);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
下面附上java版的重要解析: