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版的重要解析:

列格雷码 opencv 格雷码编程_java实现格雷码