当前位置: 首页 > article >正文

递归分治法格雷码

一、实验内容

Gray码是一个长度为2^n的序列,序列中无相同元素,每个元素都是长度为n位的(0,1)串,相邻元素恰好只有一位不同。用分治策略设计一个算法对任意的n构造相应的Gray 码。

实验目的:掌握分治法

  1. 递归分解问题:将大问题分解为多个小规模的子问题。
  2. 处理小问题:对于足够小的子问题,直接解决(称为“基本情形”)。
  3. 合并结果:通过合并子问题的解,得到原问题的解。

二、实验原理

基本情形:当 n = 1 时,直接生成格雷码 [0] 和 [1]。

递归分解:如果 n > 1,调用 grayCode(n - 1, a / 2, ans) 递归地生成 n-1 位的格雷码,计算出前半部分的格雷码。通过递归调用生成较小规模的子问题(即 n-1 位的格雷码),这是分治法中的“递归分解问题”部分。

合并结果:递归返回后,利用已经生成的 n-1 位的格雷码来构建 n 位的格雷码。具体来说,前半部分的格雷码保持不变,后半部分的格雷码是前半部分格雷码的逆序,并在最高位设置 1。

 三、调试分析

  • 1. a 和 n 的值在这时并不确定,应该在动态分配内存之前根据 n 计算 a = 2^n。将 a 和 n 的初始化放在 main 函数中,并且根据输入的 n 计算 a = 2^n,然后再进行内存分配。
  • 2. ans[i + a / 2][j] = ans[a - i - 1][j]; 这样写会导致后半部分的格雷码顺序不正确,从而无法满足格雷码相邻元素只有一位不同的特性。
  • 需要修正为 ans[i + a / 2][j] = ans[a / 2 - i - 1][j];,确保后半部分是前半部分的逆序。
  • 3. 最高位的设置:前半部分的最高位设置为 0,后半部分的最高位设置为 1。
  • 4. 递归终止条件:当 n == 1 时,直接生成 [0, 1] 作为基础格雷码。

 

#include <stdio.h>
#include <stdlib.h>

int n, a;//n代表位数,a=2^n代表格雷码元素个数

void grayCode(int n, int a, int **ans){
    if(n == 1){
        ans[0][0] = 0;
        ans[1][0] = 1;
        return;
    }

    grayCode(n - 1, a / 2, ans);//递归生成n-1位的格雷码.取倒数第二列,重复,直到n=1
   
    // 复制生成的前半部分到后半部分并设置最后一列
    for (int i = 0; i < a / 2; i++){//i代表第i行
        // 前半部分的最高位设置为0
        ans[i][n - 1] = 0;
        // 后半部分的最高位设置为1
        ans[i + a / 2][n - 1] = 1;
        // 复制前半部分的逆序
        for (int j = 0; j < n - 1; j++) {
            ans[i + a / 2][j] = ans[a / 2 - i - 1][j]; 
        }
    }
}

int main(){
    printf("请输入gray码的位数n:\n");
    scanf("%d", & n);
    a = 1 << n;  // a = 2^n, 将数字 1 左移 n 位,使得 1 变为 2^n
    int **ans = (int **)malloc(a * sizeof(int *));  // 动态分配二维数组
    for (int i = 0; i < a; i++) {
        ans[i] = (int *)malloc(n * sizeof(int));
    }

    grayCode(n, a, ans);

    // 打印格雷码
    printf("生成的Gray码是:\n");
    for (int i = 0; i < a; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d", ans[i][j]);
        }
        printf("\n");
    }

    // 释放内存
    for (int i = 0; i < a; i++) {
        free(ans[i]);
    }
    free(ans);

    return 0;
}


http://www.kler.cn/a/592573.html

相关文章:

  • 刷题练习笔记
  • 基于SpringBoot + Vue 的图书馆座位预约系统
  • 红日靶场(二)——个人笔记
  • HarmonyOS开发,console.log和hilog的区别,如何选择使用?
  • 两矩阵相乘(点乘和乘的区别)
  • Matrix-breakout-2-morpheus靶机实战攻略
  • 算法、数据结构、计算机网络,编译原理,操作系统常考题
  • Node.js系列(4)--微服务架构实践
  • 数据结构之链表(双链表)
  • 如何在 GoLand 中设置默认项目文件夹
  • JAVA中关于图形化界面的学习(GUI)动作监听,鼠标监听,键盘监听
  • SpringBoot项目controller层接收对应格式请求的相关RequestMapping配置
  • Vue3 核心特性解析:Suspense 与 Teleport 原理深度剖析
  • k8s基础资源管理指令
  • 《鸿蒙开发实战:音频录制、文件读取与播放功能全解析》
  • Java 集合框架
  • linux 内核 定时器(timer)
  • AI 是什么?核心概念与发展历程(人工智能的发展、基本概念、机器学习 vs 深度学习)
  • PyCharm 5的Python IDE的功能(附工具下载)
  • sql小记,20250319