说在前面的话
作者普通本科计算机专业学生,这是第一次写文章,文章关于 Python 解决 Gray码构造算法 ,有诸多问题,劳烦各位不吝赐教。
进入正题
问题说明
Gray码是一个长度为 2 n 2^{n} 2n的序列,序列中无相同元素,且每个元素都是长度为n位的二进制位串,相邻元素恰好只有1位不同。例如长度为 2 3 2^{3} 23的格雷码为(000,001,011,010,110,111,101,100),设计分治算法对任意的n值构造相应的格雷码。
问题分析
对Gray码序列规律进行分析,定义序列中每个元素的位数称为元素的“宽度”。下面给出一组宽度为3位的Gray码,并以此为例,对它的编码规律进行分析。
如图,对于宽度为3的Gray码,除最高位以外,虚线①的上下两侧是对称的,对称的两组码字恰好均是宽度为2的Gray码,并且虚线①上方最高位全为“0”,下方全为“1”;对于宽度为2的Gray码,除最高位以外,虚线②的上下两侧也是对称的,对称的两组码字恰好均是宽度为1的Gray码,并且虚线②上方最高位同样全为“0”,下方全为“1”。同理,向上推广至宽度为4、5、…、n。通过上述分析可以发现,这种规律对于任意宽度的Gray码都是适用的。
这样,总结出Gray码序列的构造规律,即宽度为n的Gray码,共有2个元素,前2个元素可由宽度为(n-1)的Gray码和第n位的“0”构成,后2个元素可由之前生成的经过逆序的Gary码和第n位的“1”构成。
0 | 0 | 0
0 | 0 | 1
|----------------②
0 | 1 | 1
0 | 1 | 0
|----------------①
1 | 1 0
1 | 1 1
1 | 0 1
1 | 0 0
算法设计
由以上分析可得,基于格雷码是反射码的事实,利用递归方法构设计造出如下规律。
(1)1位格雷码有两个码字;
(2)(n+1)位格雷码中的前个码字等于n位格雷码的码字,按顺序书写,加前缀0;
(3)(n+1)位格雷码中的后个码字等于n位格雷码的码字,按逆序书写,加前缀1;
(4)(n+1)位格雷码的集合=n位格雷码集合(顺序)加前缀0+n位格雷码集合(逆序)加前缀1。
从上节中总结出的规律中可以得出,用分治算法构造Gray码的问题可形式地表示如下:
算法实现
具体实现代码如下:
# 构造w位格雷码,n为格雷码的个数
def gray(w, n):
# 如果格雷码宽度为1
if w == 1:
arr[0][0] = 0
arr[1][0] = 1
return
# 格雷码最高位
for i in range(int(n/2)):
# 生成的格雷码前一半最高位填“0”
arr[i][int(w-1)] = 0
# 后一半最高位位填“1”
arr[int(n/2 + i)][int(w-1)] = 1
# Output(arr)
gray(w-1, int(n/2))
# 生成w - 1位格雷码,填写到目标码高半部分
n1 = int(n/2)
# print(n1)
for i in range(n1, n):# 填入格雷码低半部分
for j in range(w - 1):
arr[i][j] = arr[n-i-1][j]
# 输出函数
def Output(arr):
for i in range(int(len(arr))):
print(arr[i])
#主函数
if __name__ == '__main__':
width = int(input("输入Gray码的宽度:"))
num = 2**width
arr = [[None for i in range(width)] for i in range(num)] # 定义Gray码的存储结构
gray(width, num)
Output(arr)
运行结果
运行结果如图:
结果分析
这里设计的算法基于分治思想,利用Gray码具有的自身特性,将问题的规模不断缩小,从而实现Gray码的生成。若用T(n)表示生成宽度为n的Gray码所需要的时间复杂度,则整个算法的时间复杂度可表示为:
O(n), (n = l)
T(n) ={
T(n - 1)+ O(n·2), (n > 1)
解此递归式可得:T(n)=O(n·2 )。
算法的空间复杂度为:O(n·2 )。
结束后的话
能力有限,多多包涵!
文章参考资料:Gray码的分治构造算法.