|
现代计算机一般采用二进制来表示数据,即用0和1的组合来表示各种信息。格雷码是这样一种排列数字的方式,所有相邻整数在它们的二进制表示中只有一个位不同。例如,下面是3bit的格雷码(注意开始和结束的数字也只有一位不同):
000 001 011 010 110 111 101 100
0 1 3 2 6 7 5 4
格雷码具有很多重要的用途。例如,信息在传输的过程中,可能发生问题,某一位从0变到1或者反过来,格雷码的特性能够容易地检测到可能出现的奇数个错误;在数模转换中,格雷码每次的数据变化量小,因此产生的电流脉冲变化也小,出现故障的几率会下降。格雷码还可以应用在集成电路优化、超立方体结构优化,甚至包括图书馆书架上的书的摆放方法的优化等问题上。
1个bit的格雷码序列只有0,1;
两个bit的格雷码通过一个bit的格雷码序列产生:
(1) 每一个原始序列前面加上"0",得到总数一半的格雷码;
(2) 把原始序列反序,然后每一个前面加上"1",得到另一半的格雷码,最后放在一起形成两个bit的格雷码:
00 01 11 10
三个bit的格雷码用类似的方法从两个bit的格雷码产生。
方法一(循环实现)
import java.util.Scanner;
public class Gray {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int num = (int)Math.pow(2, n);//根据输入的整数,计算出此Gray序列大小
String[] s1 = {"0","1"};//第一个Gray序列
for(int i=2;i<=n;i++){//循环根据第一个Gray序列,来一个一个的求
int p = (int)Math.pow(2, i);//到了第几个的时候,来计算出此Gray序列大小
String[] si = new String[p];
for(int j=0;j< p;j++){//循环根据某个Gray序列,来一个一个的求此序列
if(j< (p/2)){
si[j] = "0" + s1[j];//原始序列前面加上"0"
}else{
si[j] = "1" + s1[p-j-1];//原始序列反序,前面加上"1"
}
}
s1 = si;//把求得的si,附给s1,以便求下一个Gray序列
}
for(int i=0;i< num;i++){
System.out.println(s1);
}
}
}
方法二(递归实现)
import java.util.Scanner;
public class Gray1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
String gray[]=GeLeiMa(n);
for(int i=0;i< gray.length;i++){
System.out.println(gray);
}
}
public static String[] GeLeiMa(int n)
{
double num=Math.pow(2,n);
String[] s=new String[(int)num];
if(n==1)
{
s[0]="0";
s[1]="1";
}
else if(n>1)
{
String[] tm=GeLeiMa(n-1);
for(int i=0;i< tm.length;i++)
{
s="0 "+tm;
s[2*(tm.length)-1-i]="1 "+tm;
}
}
return s;
}
}
运行:
C:\test>java Gray1
1
0
1
C:\test>java Gray1
2
0 0
0 1
1 1
1 0
C:\test>java Gray1
3
0 0 0
0 0 1
0 1 1
0 1 0
1 1 0
1 1 1
1 0 1
1 0 0
C:\test>java Gray1
4
0 0 0 0
0 0 0 1
0 0 1 1
0 0 1 0
0 1 1 0
0 1 1 1
0 1 0 1
0 1 0 0
1 1 0 0
1 1 0 1
1 1 1 1
1 1 1 0
1 0 1 0
1 0 1 1
1 0 0 1
1 0 0 0 |
|