《空间复杂度(C语言)》
文章目录
- 前言
- 一、什么是空间复杂度?
- 通俗理解:
- 二、空间复杂度的数学定义
- 三、常见空间复杂度举例(含C语言代码)
- 🔹 O(1):常数空间
- 🔹 O(n):线性空间
- 🔹 O(n^2):平方空间
- 四、输入数据占用的空间算吗?
- 五、递归中的空间复杂度
- 六、时间复杂度 vs 空间复杂度
- 七、优化空间复杂度的常见方法
- 总结
前言
当你写出一段能“跑得起来”的C语言程序时,也许你会觉得:“OK,搞定了!”
但你有没有想过:
- 这段程序在处理大数据量时,会不会把内存撑爆?
- 有没有可能用了太多没必要的变量和数组,浪费了资源?
- 如果要在嵌入式系统或内存有限的设备上跑,它还能正常运行吗?
这时,我们就得引入另一个重要的概念 —— 空间复杂度(Space Complexity)。
空间复杂度,简单来说,就是分析你的程序到底“吃”了多少内存。它不仅能帮助我们优化程序效率,也能避免内存泄漏、程序崩溃等一系列问题。

一、什么是空间复杂度?
在学习编程时,我们经常关心程序运行的速度,而空间复杂度关注的则是程序运行时**“占用了多少内存”**。
举个例子:
如果你写了一个程序,它在处理数据时需要开辟额外的数组、结构体、变量等存储信息,那么这些就算作了额外空间。空间复杂度就是用来衡量这部分空间使用情况的。
通俗理解:
你可以把程序比作一个人在做题:
- 他眼前的试卷是输入数据(这些不算在空间复杂度里)
- 他额外准备的草稿纸、笔、计算器就是辅助空间(这些要算)
空间复杂度,关注的就是:这个人需要准备多少张草稿纸?
二、空间复杂度的数学定义
空间复杂度一般用大写的 O 符号表示,例如:
O(1):常数空间,只用很少的变量O(n):线性空间,比如要开一个数组来存储 n 个元素O(n^2):平方空间,常见于二维数组或矩阵问题
我们不关心精确的字节数,只看输入规模 n 增加时,额外内存的增长趋势。
三、常见空间复杂度举例(含C语言代码)
🔹 O(1):常数空间
程序只用固定几个变量,不随输入变化而变化。
int max(int arr[], int n) {int maxVal = arr[0];for (int i = 1; i < n; i++) {if (arr[i] > maxVal) {maxVal = arr[i];}}return maxVal;
}
分析:
maxVal和i是两个变量,和n的大小无关- 所以空间复杂度是
O(1)
🔹 O(n):线性空间
程序根据输入的大小,分配了等量的内存空间。
int* duplicate(int arr[], int n) {int* result = (int*)malloc(n * sizeof(int));for (int i = 0; i < n; i++) {result[i] = arr[i];}return result;
}
分析:
- 申请了一个新的数组
result,长度为n - 所以空间复杂度为
O(n)
🔹 O(n^2):平方空间
使用了二维数组,如矩阵、图的邻接矩阵等情况。
int** createMatrix(int n) {int** matrix = (int**)malloc(n * sizeof(int*));for (int i = 0; i < n; i++) {matrix[i] = (int*)malloc(n * sizeof(int));}return matrix;
}
分析:
- 共申请了
n × n个整数的空间 - 所以空间复杂度为
O(n^2)
四、输入数据占用的空间算吗?
不算!
空间复杂度只考虑算法运行过程中新增的内存。输入数据(比如函数参数)默认已经存在,不属于算法“额外使用”的空间。
五、递归中的空间复杂度
递归函数往往会消耗较多空间,因为每一次递归调用都会压入一个栈帧。
int factorial(int n) {if (n == 1) return 1;return n * factorial(n - 1);
}
分析:
- 递归深度为
n,每次调用都占一份栈空间 - 所以空间复杂度为
O(n)
六、时间复杂度 vs 空间复杂度
| 对比项 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 含义 | 程序运行需要的“时间” | 程序运行需要的“空间” |
| 衡量单位 | 步数(操作次数) | 字节数/变量个数等 |
| 关注点 | 程序快不快 | 程序占不占内存 |
| 示例 | 排序算法耗时 | 哈希表占用内存 |
有时需要做取舍,比如:
- 用 更多空间 来加快处理速度(空间换时间)
- 用 更少空间,但处理得慢一些(时间换空间)
七、优化空间复杂度的常见方法
| 方法 | 举例说明 |
|---|---|
| 尽量复用变量 | 不重复创建数组 |
| 能用原地修改就原地修改 | 冒泡排序直接在原数组上操作 |
| 使用位运算压缩空间 | 布尔数组压缩成位图(bitset) |
| 及时释放动态内存 | 使用 free() 释放 malloc() 空间 |
总结
- 空间复杂度衡量的是程序运行时占用的额外内存大小
- 通常只考虑临时变量、辅助数组、递归栈帧等
- 表达形式用
O(1)、O(n)、O(n^2)等 - 递归和大数据处理时要特别注意空间使用
- 编程中要学会在时间与空间之间做平衡
相关文章:
《空间复杂度(C语言)》
文章目录 前言一、什么是空间复杂度?通俗理解: 二、空间复杂度的数学定义三、常见空间复杂度举例(含C语言代码)🔹 O(1):常数空间🔹 O(n):线性空间🔹 O(n^2):平…...
Kaggle-Store Sales-(回归+多表合并+xgboost模型)
Store Sales 题意: 给出很多商店,给出商店的类型,某时某刻卖了多少销售额。 给出了油价表,假期表,进货表。 让你求出测试集合中每个商店的销售额是多少。 数据处理: 1.由于是多表,所以要先把其他表与tr…...
在 Tailwind CSS 中优雅地隐藏滚动条
在开发中,我们经常需要隐藏滚动条但保持滚动功能,这在构建现代化的用户界面时很常见。 本文将介绍两种在 Tailwind CSS 项目中实现这一目标的方法,方便同学们记录和查阅。 方法一:使用 tailwind-scrollbar-hide 插件 这是一种更…...
智能合约安全审计平台——以太坊虚拟机安全沙箱
目录 以太坊虚拟机安全沙箱 —— 理论、设计与实战1. 引言2. 理论背景与安全原理2.1 以太坊虚拟机(EVM)概述2.2 安全沙箱的基本概念2.3 安全证明与形式化验证3. 系统架构与模块设计3.1 模块功能说明3.2 模块之间的数据流与安全性4. 安全性与密码学考量4.1 密码学保障在沙箱中…...
std::unordered_map(C++)
std::unordered_map 1. 概述2. 内部实现3. 性能特征4. 常用 API5. 使用示例6. 自定义哈希与相等比较7. 注意事项与优化8. 使用建议9. emplace和insert异同相同点不同点例子对比何时优先使用哪种? 1. 概述 定义:std::unordered_map<Key, T, Hash, KeyE…...
【MCP教程】Claude Desktop 如何连接部署在远程的remote mcp server服务器(remote host)
前言 最近MCP特别火热,笔者自己也根据官方文档尝试了下。 官方文档给的Demo是在本地部署一个weather.py,然后用本地的Claude Desktop去访问该mcp服务器,从而完成工具的调用: 但是,问题来了,Claude Deskto…...
Android Input——输入事件回调完成(十四)
前面几篇文章介绍了事件回调的相关流程,以及回调事件处理函数的相关内容,最后我们再来看一下事件处理完后,如何通知 InputDispatcher 去回调 Callback。 一、客户端回调 在 Android 的事件分发机制中,当客户端(即应用层)完成事件处理后,最终会调用 ViewRootImpl 的 fin…...
数据通信学习笔记之OSPF配置命令
华为 [huawei]ospf 10 router-id 1.1.1.1 //创建ospf进程,本地有效area 1 // 进入区域1network 192.168.1.0 0.0.0.255 // 宣告网段,使用反掩码stub // 配置为stub区域stub no-summary // 配置为Totally Stub 完全末节区域。在ABR上配置࿰…...
Python -yield 在python 中什么意思
在 Python 中,yield 是一个关键字,用于定义生成器函数(generator function)。它的作用是将一个普通函数转变为可迭代的生成器,具有惰性计算的特性。以下是关键要点: 核心概念 生成器函数: 当函数…...
多个路由器互通(静态路由)无单臂路由(简单版)
多个路由器互通(静态路由)无单臂路由(简单版) 开启端口并配ip地址 维护1 Router>en Router#conf t Router(config)#int g0/0 Router(config-if)#no shutdown Router(config-if)#ip address 192.168.10.254 255.255.255.0 Ro…...
OpenCV 图形API(38)图像滤波-----Sobel 算子操作函数Sobel()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::gapi::Sobel 函数是 OpenCV 的 G-API 模块中用于执行 Sobel 算子操作的一个函数,主要用于图像的边缘检测。Sobel 算子通过计算图…...
3DS 转 STL 全攻略:传统工具与迪威模型网在线转换深度解析
在 3D 建模与 3D 打印的技术领域中,常常会遇到需要将不同格式的文件进行转换的情况。其中,把 3DS 文件转换为 STL 格式是较为常见的操作。3DS 文件作为一种旧版 Autodesk 3D Studio 使用的 3D 图像格式,存储着丰富的信息,包括网格…...
windows系统安装驱动、cuda和cudnn
一、首先在自己的电脑里安装了nvidia的独立显卡 显卡的查找方式: CtrlShiftEsc打开任务管理器,点击性能,点击GPU 0查看显卡型号,如下图所示: 只要电脑中有nvidia的独立显卡,就可以暗转显卡驱动、cuda和cu…...
嵌入式开发--STM32软件和硬件CRC的使用--续篇
本文是《嵌入式开发–STM32软件和硬件CRC的使用》的续篇,又踩到一个坑,发出来让大家避一下坑。 按照G0系列的设置,得出错误的结果 前文对应的是STM32G0系列,今天在用STM32G4系列时,按照前文的设置,用硬件…...
2.深入剖析 Rust+Axum 类型安全路由系统
摘要 详细解读 RustAxum 路由系统的关键设计原理,涵盖基于 Rust 类型系统的路由匹配机制、动态路径参数与正则表达式验证以及嵌套路由与模块化组织等多种特性。 一、引言 在现代 Web 开发中,路由系统是构建 Web 应用的核心组件之一,它负责…...
c# 委托和事件的区别及联系,Action<T1,T2>与Func<T1,T2>的区别
定义与本质 委托: 委托是一种类型,用于存储对方法的引用。它允许将方法作为参数传递、存储和调用。委托可以绑定一个或多个方法,并通过和-操作符动态添加或移除方法。 事件: 事件是基于委托的封装,提供了一种发布/订阅机制。事件…...
【Python入门】文件读取全攻略:5种常用格式(csv/excel/word/ppt/pdf)一键搞定 | 附完整代码示例
大家好,我是唐叔!今天给大家带来一篇Python文件读取的终极指南。无论是数据分析、办公自动化还是爬虫开发,文件读取都是Python程序员必须掌握的核心技能。本文将详细介绍Python处理5大常用文件格式的方法,包含完整可运行的代码示例…...
【Git】git的简单使用
文章目录 1. 基础概念2. 简单使用2.1 git配置2.1.1 git的配置文件2.1.2 .gitignore文件 2.2 创建仓库2.2.1 创建本地仓库2.2.2 github创建远程仓库step1:github新建一个代码仓step2:创建密钥远程仓库相关指令2.2.3 本地仓库 关联 远程仓库 2.3 分支2.3.1…...
WebSocket 实现数据实时推送原理
WebSocket 实现数据实时推送的核心机制在于其全双工通信能力和持久的连接特性。以下是其工作原理的详细步骤: 1. 握手阶段(HTTP 升级协议) 客户端发起请求:通过发送一个带有特殊头部的 HTTP 请求,请求协议升级。 GET …...
LeetCode 2919 使数组变美的最小增量运算数
动态规划解题:最小操作次数使数组变为美丽数组 问题描述 给定一个下标从0开始、长度为n的整数数组nums和一个整数k。你可以对数组中的任意一个元素进行加1操作,操作次数不限。如果数组中任意长度大于或等于3的子数组的最大值都大于或等于k,…...
[Web 安全] Web 信息收集 —— 信息收集流程
🌟 想系统化学习 Web 渗透?看看这个:[Web 安全] Web 安全攻防 学习手册 提示:本章不涉及任何具体信息收集技术,仅仅是讲解收集这些信息我能干啥,以及如何才能比较全面的收集信息。 0x01:信息收…...
内部聊天软件,BeeWorks-安全的企业内部通讯软件
企业在享受数据便利的同时,如何保障企业数据安全已经成为无法回避的重要课题。BeeWorks作为一款专为企业设计的内部通讯软件,通过全链路的安全能力升维,为企业提供了一个安全、高效、便捷的沟通协作平台,全面保障企业数据安全。 …...
线程安全学习
1 什么是线程 线程是cpu调度的最小单位,在Linux 下 实现线程的方式为轻量级进程,复用进程的结构体,使用clone函数创建 2 线程安全 所谓线程安全,更确切的应该描述为内存安全 #include <stdio.h> #include <pthread.h…...
应用篇02-镜头标定(上)
本节主要介绍相机的标定方法,包括其内、外参数的求解,以及如何使用HALCON标定助手实现标定。 计算机视觉——相机标定(Camera Calibration)_摄像机标定-CSDN博客 1. 原理 本节介绍与相机标定相关的理论知识,不一定全,可以参考相…...
【UE5 C++】“ProceduralMeshComponent”的使用记录
效果 如下所示,通过“ProceduralMeshComponent”创建了一个自定义形状的Mesh,并且该Mesh包含碰撞信息,然后2s后更新Mesh形状。 步骤 1. 在“xxx.Build.cs”中引入“ProceduralMeshComponent”模块 2. 新建一个Actor类,这里命名为…...
解决PIP 安装出错ERROR: cp310-cp310-manylinux_2_28_x86_64.whl is not a supported wheel
ERROR: torch-2.8.0.dev20250325cu128-cp310-cp310-manylinux_2_28_x86_64.whl is not a supported wheel on this platform. 可以 pip debug --verbose | grep manylinux | grep cp310 WARNING: This command is only meant for debugging. Do not use this with automation f…...
通过helm在k8s中安装mysql 8.0.37
使用 Helm 在 Kubernetes 中安装 MySQL 8.0.37 是一个相对简单的过程。以下是详细步骤: 下载helm包 #添加 Helm 仓库 helm repo add bitnami https://charts.bitnami.com/bitnami#搜索mysql helm search repo mysql --versions NAME CHAR…...
【暴力求解】1534. 统计好三元组
1534. 统计好三元组 - 力扣(LeetCode) 给你一个整数数组 arr ,以及 a、b 、c 三个整数。请你统计其中好三元组的数量。 如果三元组 (arr[i], arr[j], arr[k]) 满足下列全部条件,则认为它是一个 好三元组 。 0 < i < j &l…...
前端页面效果收集
文章目录 数字雨元素融化动画电子签名共享屏幕 数字雨 <canvas id"matrix"></canvas> <script>const canvas document.getElementById(matrix);const ctx canvas.getContext(2d);canvas.width window.innerWidth;canvas.height window.innerH…...
(leetcode算法题)309. 买卖股票的最佳时机含冷冻期
按照题目要求,研究对象是最后一天结束后获得的最大利润 那么就可以把问题拆分成 第 1 天结束后获得的最大利润, 第 2 天结束后获得的最大利润, 第 i 天结束后获得的最大利润, 由于规则中强调不能同时参与多笔交易,…...
