算法设计 格雷码问题

2022/1/14 14:36:43

本文主要是介绍算法设计 格雷码问题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

算法设计 格雷码问题

1. 问题描述
对于给定的正整数n,格雷码为满足如下条件的一个编码序列:
(1) 序列由2n个编码组成,每个编码都是长度为n的二进制位串。
(2) 序列中无相同的编码。
(3) 序列中位置相邻的两个编码恰有一位不同。
例如:n=2时的格雷码为:{00, 01, 11, 10}。
设计求格雷码的递归算法并实现。
2. 具体要求
输入的第一行是一个正整数m,表示测试例个数。接下来几行是m个测试例的数据,每个测试例的输入数据由一行组成,用一个正整数n (n<=20),表示格雷码的位数。
输出:对于每个测试例输出2n行,表示2n个长度为n的格雷码。第一行为最长递增子序列的长度,第二行为最长递增子序列,整数之间用一个空格隔开。两个测试例的输出数据之间用一个空行隔开。
3. 测试数据
输入:
2
4
5
输出:
0 0
0 1
1 0
1 1

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

0 0 0 0 0
0 0 0 0 1
0 0 0 1 1
0 0 0 1 0
0 0 1 1 0
0 0 1 1 1
0 0 1 0 1
0 0 1 0 0
0 1 1 0 0
0 1 1 0 1
0 1 1 1 1
0 1 1 1 0
0 1 0 1 0
0 1 0 1 1
0 1 0 0 1
0 1 0 0 0
1 1 0 0 0
1 1 0 0 1
1 1 0 1 1
1 1 0 1 0
1 1 1 1 0
1 1 1 1 1
1 1 1 0 1
1 1 1 0 0
1 0 1 0 0
1 0 1 0 1
1 0 1 1 1
1 0 1 1 0
1 0 0 1 0
1 0 0 1 1
1 0 0 0 1
1 0 0 0 0

思路:
N位的格雷码都是在n-1位的格雷码前加0或1得到的,但需要注意顺序,加0要按n-1位格雷码的正序加,而加1要按n-1位格雷码的倒序加。最后的结果就是加0到加1的结果顺序排列。
如:
1位的格雷码只有0,1。
在此基础上,在1位的格雷码前分别加0和1可以得到2位的格雷码,但加0时要按正序,加1时要按倒序。首先按正序加0,正序为0,1,得到00,01;再按倒序加1,倒序为1,0,得到11,10。所以2位的格雷码为00,01,11,10。
同理,3位的格雷码按2位的正序加0,正序为00,01,11,10,所以得到的结果为000,001,011,010。然后按倒序加1,倒序为10,11,01,00,所以加1后为110,111,101,100。所以最后3位的格雷码为000,001,011,010,110,111,101,100。
以此类推。

代码:

#include <iostream>
#include <list>

using namespace std;

/// <summary>
/// 求n位格雷码
/// </summary>
/// <param name="n">位数</param>
/// <param name="result">最终结果</param>
/// <param name="codes">辅助链表,存放中间过程,最后存储的也是最终结果</param>
void grayCode(int n, list<string>& result, list<string>& codes)
{
	if (n == 1)
	{
		codes.push_back("0");
		codes.push_back("1");
	}
	else
	{
		grayCode(n - 1, result, codes);
		result.clear();

		//按顺序,在所有n-1位的格雷码前加上0
		for (list<string>::iterator itr = codes.begin(); itr != codes.end(); itr++)
		{
			result.push_back("0" + *itr);
		}

		//在所有n-1位的格雷码前加上1,注意顺序是从最后一个往前
		for (list<string>::reverse_iterator ritr = codes.rbegin(); ritr != codes.rend(); ritr++)
		{
			result.push_back("1" + *ritr);
		}
		codes.assign(result.begin(), result.end());
	}
}

int main()
{
	int m, n;
	cin >> m;
	while(m-- > 0)
	{
		cin >> n;
		list<string> codes;
		list<string> result;
		grayCode(n, result, codes);
		for (list<string>::iterator itr = result.begin(); itr != result.end(); itr++)
		{
			cout << *itr << endl;
		}
	}

	return 0;
}

截图:
在这里插入图片描述
在这里插入图片描述



这篇关于算法设计 格雷码问题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程