【C++】递归填充矩阵的理论解析与实现


在这里插入图片描述

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳]
本文专栏: C++

文章目录

  • 💯前言
  • 💯问题描述
  • 💯递归实现
  • 💯参数解析
    • 函数参数详解
    • 填充顺序分析
    • 递归终止条件
  • 💯示例解析
    • 第一层递归
    • 第二层递归
    • 第三层递归
    • 最终输出
  • 💯递归算法解析
    • 理论基础
    • 优点
    • 缺点
  • 💯优化与拓展
    • 1. 动态内存分配
    • 2. 非递归实现
    • 3. 拓展填充模式
  • 💯小结


在这里插入图片描述


💯前言

  • C++ 编程领域递归 是一种不可或缺的编程范式。它尤其适用于分层结构递归性质的问题,为解决复杂问题提供了优雅的框架。本文将全面剖析 递归填充矩阵问题,深入探讨代码实现理论背景递归特性解析及其优化与拓展。与此同时,还将对递归算法的核心思想进行更深层次的理论分析,并提供实际应用中的潜在扩展方案
    C++ 参考手册
    在这里插入图片描述

💯问题描述

构造一个矩阵,其中每一层以顺时针方向填充数字,从矩阵的外圈向内递归,直至整个矩阵被完整填充。这一问题表面看似简单,但其实隐藏了复杂的分层计算逻辑及递归思想的实践。

示例输入与输出

对于一个 5 × 5 的矩阵,按照递归方式填充后,结果如下:

1   16   15   14   13
2   17   24   23   12
3   18   25   22   11
4   19   20   21   10
5    6    7    8    9

外圈的数字从左上角按顺时针顺序递增,内圈依次类推,直到填充完毕。这种从外向内、逐层递归的填充方法展示了递归算法的分解和简化过程。本文将以递归方法实现这一填充方案,并进一步探讨其可能的扩展方式。


💯递归实现

以下为核心递归实现代码:
FillMatrix函数:

void FillMatrix(int matrix[N][N], int size, int num, int offset) {
    // 递归终止条件1:矩阵大小为0,返回
    if (size == 0)
        return;

    // 递归终止条件2:矩阵大小为1,填充中心点
    if (size == 1) {
        matrix[offset][offset] = num;
        return;
    }

    // 填充外圈的四部分
    for (int i = 0; i < size - 1; i++) {
        matrix[offset + i][offset] = num + i; // 左侧一列
        matrix[offset + size - 1][offset + i] = num + (size - 1) + i; // 底部一行
        matrix[offset + size - 1 - i][offset + size - 1] = num + 2 * (size - 1) + i; // 右侧一列
        matrix[offset][offset + size - 1 - i] = num + 3 * (size - 1) + i; // 顶部一行
    }

    // 递归调用,进入内圈
    FillMatrix(matrix, size - 2, num + 4 * (size - 1), offset + 1);
}

main函数:

int main() {
    const int N = 5; // 定义矩阵大小
    int matrix[N][N] = {0}; // 初始化矩阵为全 0

    // 调用递归函数填充矩阵
    FillMatrix(matrix, N, 1, 0);

    // 打印矩阵
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cout << setw(4) << matrix[i][j]; // 格式化输出,确保对齐
        }
        cout << endl;
    }

    return 0;
}

在这里插入图片描述


💯参数解析


函数参数详解

  1. int matrix[N][N]:目标矩阵,大小固定为 N × N
  2. int size:当前需要填充的子矩阵大小。
  3. int num:填充的起始数字。
  4. int offset:当前子矩阵在整体矩阵中的偏移位置。

填充顺序分析

  1. 左侧一列:从顶部到底部依次填充:matrix[offset + i][offset]
  2. 底部一行:从左到右依次填充:matrix[offset + size - 1][offset + i]
  3. 右侧一列:从底部到顶部依次填充:matrix[offset + size - 1 - i][offset + size - 1]
  4. 顶部一行:从右到左依次填充:matrix[offset][offset + size - 1 - i]

递归终止条件

  • size == 0:无需再填充,递归结束。
  • size == 1:矩阵缩小至单个点,直接填充中心数字。

通过这样的顺序,我们可以层层缩小矩阵的计算范围,最终实现完整的矩阵填充。递归的设计核心在于其逻辑的分层性和简洁性,使得代码能够以最少的复杂度完成较为繁琐的操作。


💯示例解析

以下以 FillMatrix(matrix, 5, 1, 0) 为例:


第一层递归

  1. size = 5offset = 0,起始数字为 1
    • 左侧一列:1, 2, 3, 4, 5
    • 底部一行:6, 7, 8, 9
    • 右侧一列:10, 11, 12, 13
    • 顶部一行:14, 15, 16

第二层递归

  1. 调用 FillMatrix(matrix, 3, 17, 1)
    • 左侧一列:17, 18, 19
    • 底部一行:20, 21
    • 右侧一列:22, 23
    • 顶部一行:24

第三层递归

  1. 调用 FillMatrix(matrix, 1, 25, 2)
    • 中心点:25

最终输出

1   16   15   14   13
2   17   24   23   12
3   18   25   22   11
4   19   20   21   10
5    6    7    8    9

通过该示例,我们能够直观理解递归在每一步是如何逐步分解问题并完成填充的。


💯递归算法解析


理论基础

递归算法通过将问题分解为规模更小的子问题,从而达到解决整体问题的目的。其核心包括以下三要素:

  1. 递归终止条件:防止无限递归。
    • 在本例中,size == 0size == 1 即为递归的终止条件。
  2. 递归子问题:将问题缩小为更简单的版本。
    • 在本例中,矩阵每次递归缩小外圈,最终进入中心点。
  3. 递归递推关系:问题规模如何递减,以及状态如何传递。
    • 本例中递归公式为:FillMatrix(matrix, size - 2, num + 4 * (size - 1), offset + 1)

递归算法之所以高效,是因为它能够自然地实现问题的分治思想,避免了手动控制循环的复杂性。尤其在分层结构中,递归能够显著减少代码冗余并提升逻辑的简洁性。


优点

递归实现能够以最少的代码完成复杂的分层逻辑,其结构直观,便于扩展。其应用场景广泛,从树形结构的遍历到动态规划中的状态转移,递归几乎无处不在。


缺点

递归可能因调用栈深度过大导致性能下降或栈溢出。在实际使用中,需要对递归深度进行评估,并通过优化递归设计来降低潜在风险。


💯优化与拓展


1. 动态内存分配

对于运行时动态确定矩阵大小的情况,可以采用如下动态分配方式:

int** matrix = new int*[N];
for (int i = 0; i < N; i++)
    matrix[i] = new int[N];

这种方式能够显著提升程序的灵活性,使其能够适应更大规模的矩阵计算需求。


2. 非递归实现

递归可以转换为迭代算法以避免调用栈问题:

void FillMatrixIterative(int matrix[N][N], int n) {
    int num = 1;
    for (int offset = 0; offset < (n + 1) / 2; offset++) {
        int size = n - 2 * offset;
        for (int i = 0; i < size - 1; i++) {
            matrix[offset + i][offset] = num++;
            matrix[offset + size - 1][offset + i] = num++;
            matrix[offset + size - 1 - i][offset + size - 1] = num++;
            matrix[offset][offset + size - 1 - i] = num++;
        }
    }
}

通过迭代方式实现矩阵填充,避免了递归可能导致的栈溢出问题,同时在某些场景下也能提升性能。


3. 拓展填充模式

除顺时针填充外,还可以实现:

  • 逆时针填充
  • 对角线填充
  • 双向递归:同时从外圈和内圈向中间填充,提升并行性。

通过拓展填充模式,可以满足不同的应用需求,例如图形处理、数据加密中的分层结构设计等。


💯小结

  • 在这里插入图片描述
    本文深入探讨了 递归填充矩阵实现与理论背景,并结合实例展示了递归在解决分层问题中的独特优势。尽管递归在解决复杂问题时表现出色,但需注意其潜在的性能瓶颈调用栈深度限制。在实际应用中,可根据具体需求选择递归或非递归实现。同时,通过动态内存分配模式拓展,能够进一步提升算法的适用性。
    通过对本文内容的学习,希望读者能够更全面地理解 递归的本质 及其在实际问题中的应用潜力,并能够在未来的实践中灵活运用这些方法与思想来解决更复杂的工程问题

在这里插入图片描述


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/936893.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Git 仓库托管教程

git远程仓库 常用的远程仓库-->托管服务&#xff1a;github、码云、gitlab等 github需要魔法上网&#xff0c;速度较慢因为在国外且仅仅支持Git&#xff0c;如果不是Git项目是不支持的&#xff1b;码云--gitee国内的代码托管平台&#xff0c;服务器在国内速度快一些&#…

[创业之路-190]:《华为战略管理法-DSTE实战体系》-2-华为DSTE战略管理体系概要

目录 一、DSTE战略管理体系与BLM的关系 1、DSTE战略管理体系概述 2、BLM模型概述 3、DSTE与BLM的关系 二、重新认识流程 1. 流程就是业务本身&#xff0c;流程是业务过程的可视化&#xff1a; 2. 流程是业务最佳路径的经验教训总结&#xff1a; 3. 流程是战略知识资产、…

多智能体架构 Insight-V:针对长链视觉推理瓶颈

多智能体架构 Insight-V&#xff1a;针对长链视觉推理瓶颈 https://arxiv.org/abs/2411.14432 推理智能体与总结智能体协作完成任务&#xff0c;实现复杂视觉任务中的高效推理与总结。其中写了一小段&#xff0c;用迭代 DPO 算法&#xff0c;在每一轮训练中&#xff0c;模型会…

ASP.NET |日常开发中连接Oracle数据库详解

ASP.NET &#xff5c;日常开发中连接Oracle数据库详解 前言一、安装和配置 Oracle 数据访问组件1.1 安装ODP.NET&#xff08;Oracle Data Provider for.NET&#xff09;&#xff1a;1.2 引用相关程序集&#xff1a; 二、配置连接字符串2.1 连接字符串的基本组成部分&#xff1a…

生成树协议STP工作步骤

第一步&#xff1a;选择根桥 优先级比较&#xff1a;首先比较优先级&#xff0c;优先级值越小的是根桥MAC地址比较&#xff1a;如果优先级相同&#xff0c;则比较MAC地址。MAC地址小的是根桥。 MAC地址比较的时候从左往右&#xff0c;一位一位去比 第二步&#xff1a;所有非根…

Redis是什么?Redis和MongoDB的区别在那里?

Redis介绍 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的、基于内存的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。以下是关于Redis的详细介绍&#xff1a; 一、数据结构支持 字符串&#xff08;String&#xff09; 这是Redis最…

minio 分布式文件管理

一、minio 是什么&#xff1f; MinIO构建分布式文件系统&#xff0c;MinIO 是一个非常轻量的服务,可以很简单的和其他应用的结合使用&#xff0c;它兼容亚马逊 S3 云存储服务接口&#xff0c;非常适合于存储大容量非结构化的数据&#xff0c;例如图片、视频、日志文件、备份数…

【射频IC学习笔记】4 D类功率放大器PA电路设计/loadpull仿真/输出功率及效率PAE计算

一、功率放大器设计指标及电路结构 1. 设计指标 功率放大器的指标要求如下图所示采用D类的开关类型功率放大器&#xff0c;理论上开关类型的PA能够做到100%的效率&#xff0c;但实际上会有一些偏差。像D类功放并不适合高功率射频信号的输出&#xff0c;因为其在射频功率上面的…

【数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 测试说明 我的通关代码: 测试结果&#xff1a; 任务描述 本关任务&#xff1a;实现二叉排序树的基本算法。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;二叉树的创建、查找和删除算法。具体如下&#xff1a; (1)由…

Unity UGUI图片循环列表插件

效果展示&#xff1a; 下载链接&#xff1a;https://gf.bilibili.com/item/detail/1111843026 概述&#xff1a; LoopListView2 是一个与 UGUI ScrollRect 相同的游戏对象的组件。它可以帮助 UGUI ScrollRect 以高效率和节省内存的方式支持任意数量的项目。 对于具有10,000个…

5G学习笔记之SNPN系列之ID和广播消息

目录 1. 概述 2. SNPN ID 3. SNPN广播消息 1. 概述 SNPN&#xff1a;Stand-alone Non-Public Network&#xff0c;独立的非公共网络&#xff0c;由NPN独立运营&#xff0c;不依赖与PLMN网络。 SNPN不支持的5GS特性&#xff1a; 与EPS交互 emergency services when the UE acce…

(后序遍历 简单)leetcode 101翻转二叉树

将根结点的左右结点看作 两个树的根结点&#xff0c;后序遍历&#xff08;从叶子结点从下往上遍历&#xff09; 两个树边遍历边比较。 左节点就左右根的后序遍历 右根结点就右左根的后序遍历来写 后序遍历&#xff08;从叶子结点从下往上遍历&#xff09; /*** Definition …

通过ajax的jsonp方式实现跨域访问,并处理响应

一、场景描述 现有一个项目A&#xff0c;需要请求项目B的某个接口&#xff0c;并根据B接口响应结果A处理后续逻辑。 二、具体实现 1、前端 前端项目A发送请求&#xff0c;这里通过jsonp的方式实现跨域访问。 $.ajax({ url:http://10.10.2.256:8280/ssoCheck, //请求的u…

Goby AI 2.0 自动化编写 EXP | Mitel MiCollab 企业协作平台 npm-pwg 任意文件读取漏洞(CVE-2024-41713)

漏洞名称&#xff1a;Mitel MiCollab 企业协作平台 npm-pwg 任意文件读取漏洞(CVE-2024-41713) English Name&#xff1a;Mitel MiCollab /npm-pwg File Read Vulnerability (CVE-2024-41713) CVSS core: 6.8 漏洞描述&#xff1a; Mitel MiCollab 是加拿大 Mitel 公司推出…

现代密码学总结(上篇)

现代密码学总结 &#xff08;v.1.0.0版本&#xff09;之后会更新内容 基本说明&#xff1a; ∙ \bullet ∙如果 A A A是随机算法&#xff0c; y ← A ( x ) y\leftarrow A(x) y←A(x)表示输入为 x x x ,通过均匀选择 的随机带运行 A A A,并且将输出赋给 y y y。 ∙ \bullet …

VMware:CentOS 7.* 连不上网络

1、修改网络适配 2、修改网卡配置参数 cd /etc/sysconfig/network-scripts/ vi ifcfg-e33# 修改 ONBOOTyes 3、重启网卡 service network restart 直接虚拟机中【ping 宿主机】&#xff0c;能PING通说明centOS和宿主机网络通了&#xff0c;只要宿主机有网&#xff0c;则 Ce…

Linux —— vim 编辑器

一、什么是vim vim是一个功能强大、高度可定制的文本编辑器。以下是对vim编辑器的具体介绍&#xff1a; 历史背景&#xff1a;vim最初由Bram Moolenaar在1991年开发&#xff0c;作为vi编辑器的增强版&#xff0c;增加了许多新的特性和改进。它继承了vi的基本编辑功能和键盘快捷…

前端(async 和await)

1 async async 将 function 变为成为 async 函数 ●async 内部可以使用 await&#xff0c;也可以不使用&#xff0c;因此执行这个函数时&#xff0c;可以使用 then 和 catch 方法 ●async 函数的返回值是一个 Promise 对象 ●Promise 对象的结果由 async 函数执行的返回值决…

huggingface NLP -Transformers库

1 特点 1.1 易于使用&#xff1a;下载、加载和使用最先进的NLP模型进行推理只需两行代码即可完成。 1.2 灵活&#xff1a;所有型号的核心都是简单的PyTorch nn.Module 或者 TensorFlow tf.kears.Model&#xff0c;可以像它们各自的机器学习&#xff08;ML&#xff09;框架中的…

解决 MyBatis 中空字符串与数字比较引发的条件判断错误

问题复现 假设你在 MyBatis 的 XML 配置中使用了如下代码&#xff1a; <if test"isCollect ! null"><choose><when test"isCollect 1">AND exists(select 1 from file_table imgfile2 where task.IMAGE_SEQimgfile2.IMAGE_SEQ and im…