格雷码(Gray Code)的生成

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


 


 

 

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二进制转码转二进制 十进制转二进制 二进制转十进制等,在Delphi xe2下通过测试。码(英文:Gray Code, Grey Code,又称作葛莱码,二进制循环码)是1880年由法国工程师Jean-Maurice-Emlle Baudot发明的一种编码[,因Frank Gray于1953年申请专利“Pulse Code Communication”得名。当初是为了机械应用,后来在电报上取得了巨大发展.压缩包里含该源代码. 二进制和码转换: 最佳答案: 十进制 586 = 二进制 1001001010 = 码 1101101111。 二进制码 ----> 码(编码): 从最右边一位起,依次将每一位与左边一位异或(XOR),作为对应码该位的值,最左边一位不变(相当于左边是0)。 码的特点是: 相邻两数的码,仅仅有一位二进制发生变化。 而且在其范围内的最小值和最大值,也仅仅有一位二进制发生变化。 例如下面两数: 最小:二进制0000=码0000 最大:二进制1111=码1000 看到了吧,0000 和 1000,仅仅有一位数发生变化。 ------- 如果在变换的过程中,先把十进制转换成BCD码,这就失去了码的特点。 因为在BCD码中: 最小:二进制0000=码0000 最大:二进制1001=码1101 可以看出,它们之间有三位发生变化。 通过BCD码来变换码,思路不对。变换出来的,并不是原数的码。 自然二进制数与码的互换公式与电路: 自然二进制数转换到码 ------------ 设有 N 位二进制数 B(i),其中 0 <= i <= N - 1;它可以变换成为同样位数的码 G(i)。 二进制数与码的转换公式如下:   G(i) = B(i 1) XOR B(i) ; 0 <= i < N - 1   G(i) = B(i) ; i = N - 1 如果是通过编程计算进行变换,就需要使用这个公式逐位的计算; 如果是使用硬件电路进行变换,就可以使用做而论道前面在回答问题时给出的电路。 码转换到自然二进制数 ------------ 设有 N 位码 G(i),把它转换成自然二进制数的算法如下。 自然二进制码的最高位等于码的最高位; 自然二进制码的次高位为最高位自然二进制码与次高位码相异或; 自然二进制码的其余各位与次高位自然二进制码的求法相类似。 转换公式如下:   B(i) = G(i) ; i = N - 1   B(i) = B(i 1) XOR G(i) ; 0 <= i < N - 1 二进制码转换器截图:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值