一、实验目的
1、 理解递归的概念和分治的基本思想
2、 了解适用递归与分治策略的问题类型,并能设计相应的分治策略算法
3、 掌握递归与分治算法时间复杂度分析,以及实际问题复杂性分析方法
二、实验内容
Gray码是一个长度为2^n的序列。序列中无相同元素,每个元素都是长度为n位的串,相邻元素恰好只有1位不同。请用分治策略设计一个算法对任意的n构造相应的Gray码。
对于给定的正整数n,格雷码为满足如下条件的一个编码序列:
(1)序列由2^n个编码组成,每个编码都是长度为n的二进制位串;
(2)序列中无相同的编码;
(3)序列中位置相邻的两个编码恰有一位不同。
问题的输入与输出:
输入正整数n,即构造n位的格雷码
输出2^n个编码
设计思路:
只看描述有些抽象,首先观察一下一位、二位、三位格雷码
这里将右边视为低位,左边视为高位
二位格雷码可以这样得到:
将一位的格雷码对称复制,作为第一位,第二位的上半部分填0,下半部分填1。
三位格雷码也可以用同样的方法从二位格雷码推出
求解n位格雷码,只需要n-1位格雷码对称复制下来,再加上最高位(一半0,一半1)即可。
这样就将问题分解为了规模更小的子问题。
以下为C语言代码
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
void Gray(int n, int num, int** arr) {
if (n == 1) {
arr[0][0] = 0;
arr[1][0] = 1;
return;
}
else
Gray(n - 1, num / 2, arr);
for (int i = 0; i < n - 1; i++)
{
for (int k = num / 2, j = k - 1; k < num; k++)
{
arr[k][i] = arr[j--][i];
}
}//完成了对称复制
for (int i = 0; i < num / 2; i++)
arr[i][n - 1] = 0;
for (int i = num / 2; i < num; i++)
arr[i][n - 1] = 1;
//完成了对最高位赋值0和1
}
int main() {
int n;
scanf("%d", &n);
int len = pow(2, n);
int** arr = (int**)malloc(sizeof(int*) * len);
//分配一个2^n行,n列的矩阵
for (int i = 0; i < len; i++)
{
arr[i] = (int*)calloc(n, sizeof(int*));
}
Gray(n, len, arr);
for (int i = 0; i < len; i++)
{
for (int j = n - 1; j >= 0; j--) {
printf("%d", arr[i][j]);
}
printf("\n");
}
}
时间复杂度分析
主要考虑两层for循环处,外层循环n-1次,内层2^(n-1)次,最后时间复杂度应为O(n2^n)