hnust 1004: 格雷码

hnust 1004: 格雷码

题目描述
对于给定的正整数n,格雷码为满足如下条件的一个编码序列:
(1) 序列由2^n个编码组成,每个编码都是长度为n的二进制位串。
(2) 序列中无相同的编码。
(3) 序列中位置相邻的两个编码恰有一位不同。
例如:n=2时的格雷码为:{00, 01, 11, 10}。

输入
m个测试例的数据,每个测试例的数据由一个正整数n(n <= 20) 组成,以0结束。

输出
对于每个测试例n,输出2^n个长度为n的格雷码。(为方便查看,在每个格雷码内,两个位之间没有空格如,00输出为:00)。两个测试例的输出数据之间用一个空行隔开,最后一个测试例后两个空行。

样例输入 Copy
4
5
0
样例输出 Copy
0000
0001
0011
0010
0110
0111
0101
0100
1100
1101
1111
1110
1010
1011
1001
1000

00000
00001
00011
00010
00110
00111
00101
00100
01100
01101
01111
01110
01010
01011
01001
01000
11000
11001
11011
11010
11110
11111
11101
11100
10100
10101
10111
10110
10010
10011
10001
10000

解题过程

看到题目的时候觉得好熟悉,是小编高中的时候练过的
看着题目里的定义,小编觉得有点复杂,所以整理了一下写出格雷码的步骤
其实就是3个步骤,

第一步,改变最右边的位元值;

第二步,改变右起第一个为1的位元的左边位元;

第三步,第四步重复第一步和第二步,直到所有的格雷码产生完毕(换句话说,已经走了(2^n) - 1 步)。

举例3位元的产生步骤:

  假设产生3位元的格雷码,原始值位 000
  第一步:改变最右边的位元值: 001
  第二步:改变右起第一个为1的位元的左边位元: 011

重复1:
  第三步:改变最右边的位元值: 010
  第四步:改变右起第一个为1的位元的左边位元: 110

重复2:
  第五步:改变最右边的位元值: 111
  第六步:改变右起第一个为1的位元的左边位元: 101

重复3:
  第七步:改变最右边的位元值: 100 #已经走了(2^n) - 1  = 7步,完成所有码字的产生。

对代码的详细解析:

  1. 头文件

    • 包含 <iostream><cstring><cstdio> 头文件,分别提供输入输出流、字符串操作和标准输入输出功能。
  2. 命名空间

    • 使用 using namespace std; 来避免在标准库类型和函数前加 std::
  3. 辅助函数 toString

    • 将整数 x 转换为字符串表示形式。
    • 使用 static char buff[20] 作为缓冲区,以存储转换后的字符串。
    • 使用 sprintf 函数将整数格式化为字符串。
  4. 辅助函数 num2Binary

    • 将整数 num 转换为 bitNum 位的二进制字符串表示形式。
    • 使用循环和位运算来构建二进制字符串。
  5. 函数 getGrayCode

    • 根据输入的位数 bitNum 生成所有可能的格雷码。
    • 使用循环从 0 到 (1 << bitNum) - 1,计算每个整数的格雷码。
    • 使用异或操作 (i >> 1) ^ i 来计算格雷码,其中 i >> 1 是将整数 i 右移一位,然后与 i 进行异或操作。
    • 使用 num2Binary 函数将格雷码转换为二进制字符串,并打印。
  6. 主函数 main

    • 读取整数 n,直到输入结束或 n 为 0。
    • 对于每个有效的 n,调用 getGrayCode 函数来打印 n 位的格雷码序列。
  7. 输入和输出

    • 使用 scanf 函数读取输入的位数 n
    • 使用 cout 输出格雷码序列,每个格雷码占一行,序列结束后输出一个空行。
  8. 程序结束

    • 当输入结束或用户输入 0 时,程序结束。

代码逻辑分析

  • 这段代码首先定义了两个辅助函数,用于将整数转换为字符串和二进制字符串。
  • getGrayCode 函数实现了格雷码的生成逻辑,它基于输入的位数,生成所有可能的格雷码,并使用 num2Binary 函数将它们转换为易读的格式。

潜在问题

  • toString 函数使用了静态缓冲区,这意味着在多次调用时,它可能会覆盖之前的转换结果。

改进建议

  • 考虑使用 std::to_string 替换 toString 函数,这是C++11中引入的标准字符串转换方法。
  • 如果需要支持大量位数的格雷码生成,可以考虑优化内存使用和输出效率。
  • 可以添加对输入数据有效性的检查,确保读取的是正整数。

部分代码

代码如下( 将整数 x 转换为字符串表示形式。使用 static char buff[20] 作为缓冲区,以存储转换后的字符串。使用 sprintf 函数将整数格式化为字符串。):

char *toString(int x){
    static char buff[20];
    sprintf(buff, "%d", x);
    return buff;
}

代码如下( 将整数 num 转换为 bitNum 位的二进制字符串表示形式。):

string num2Binary(int num, int bitNum){
    string ret="";
    for(int i = bitNum - 1; i >= 0; i--){
        ret += toString((num >> i) & 1);
    }
    return ret;
}

代码如下( 根据输入的位数 bitNum 生成所有可能的格雷码。):

void getGrayCode(int bitNum){
    for(int i = 0; i < (1 << bitNum); i++){
        int grayCode = (i >> 1) ^ i;
        cout << num2Binary(grayCode, bitNum) <<"\n";
    }
    cout << '\n';
}

AC代码

#include<iostream>
#include<cstring>
#include<cstdio>
  
using namespace std;
  
char *toString(int x){
    static char buff[20];
    sprintf(buff, "%d", x);
    return buff;
}
string num2Binary(int num, int bitNum){
    string ret="";
    for(int i = bitNum - 1; i >= 0; i--){
        ret += toString((num >> i) & 1);
    }
    return ret;
}
void getGrayCode(int bitNum){
    for(int i = 0; i < (1 << bitNum); i++){
        int grayCode = (i >> 1) ^ i;
        cout << num2Binary(grayCode, bitNum) <<"\n";
    }
    cout << '\n';
}
int main(){
    int n;
    while(scanf("%d", &n) == 1 && n){
        getGrayCode( n );
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值