C++ 格雷码位置变化序列 Gray Code
格雷码
数据结构、算法与应用 第一张练习 26
两个代码之间的 海明距离 (Hamming distance) 是对应位不等的数量。 例如:100和010的海明距离是2。 一个(二进制)格雷码是一个代码序列,其中任意相邻的两个代码之间的海明距离是1。 子集生成的序列 000,100,010,001...111 不是格雷码,因为100,010海明距离是2。 而三位代码序列 000,100,110,010,011,111,101,001是格雷码。
在代码序列的一些应用中,从一个代码到下一个代码的代价取决于它们的海明距离。因此我们希望这个代码序列是格雷码。格雷码可以用代码变化的位置序列简洁地表示。 对于上面的格雷码,位置序列是1,2,1,3,1,2,1.
令g(n)是一个n元素的格雷码的位置变化序列。以下是g的递归定义:
1 n=1
g(n-1),n,g(n-1) n>1
注意这个是位置变化序列,并不是格雷码生成。
以下为算法
递归版:
#include <iostream>
#include <cmath>
/*
* 格雷码序列数量是 2^n,相应的变化序列数量是 2^n - 1
*/
int * GrayCodeChangeSequence( int n ){
int len = pow(2,n)-1;
int * arr = new int[len];
if( n<2 ){ arr[0]=1; return arr; }
int half = (len-1)>>1;
int * half_arr = GrayCodeChangeSequence( n-1 );
for( int i=0; i<half; i ++ ){
arr[i] = half_arr[i];
}
arr[half] = n;
for( int i=0; i<half; i ++ ){
arr[i+half+1] = half_arr[i];
}
return arr;
}
void testGCCS( int n ){
int * b = GrayCodeChangeSequence(n);
for( int i = 0; i< pow(2,n)-1 ; i++ ){
std::cout << b[i] << ' ';
}
std::cout << endl;
delete[] b;
}
int main()
{
testGCCS(1);
testGCCS(2);
testGCCS(3);
testGCCS(4);
testGCCS(5);
}
测试分别输出:
1
1 2 1
1 2 1 3 1 2 1
1 2 1 3 1 2 1 4 1 2 1 3 1 2 1
1 2 1 3 1 2 1 4 1 2 1 3 1 2 1 5 1 2 1 3 1 2 1 4 1 2 1 3 1 2 1
优化
实际上格雷码修改序列生成和斐波那契数列的生成效率是需要进一步优化的,原因在于每一次收到递归结果,都需要遍历一次结果并且覆盖到当前的序列中。从渐进意义上来说,复杂度是O(n2) 而且相对于序列的长度增长渐进意义上远大于n,这个时候如果能够在一次遍历的情况下配合少量计算那么可以将复杂度降低至O(n)
最近回复