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

数据结构之算法复杂度

目录

前言

一、复杂度的概念

二、时间复杂度

三、大O的渐进表示法

四、空间复杂度

五、常见复杂度对比

总结



前言

        本文主要讲述数据结构中的算法复杂度


一、复杂度的概念

算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度空间复杂度

  • 时间复杂度主要衡量一个算法的运行快慢。
  • 空间复杂度主要衡量一个算法运行所需要的额外空间。

        在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注⼀个算法的空间复杂度。


二、时间复杂度

在计算机科学中,算法的时间复杂度是一个函数式T(N),它定量描述了该算法的运行时间。时间复杂度是衡量程序的时间效率。

那么为什么不去计算程序的运行时间呢?

  1. 因为程序运行时间和编译环境和运行机器的配置都有关系,比如同一个算法程序,用⼀个老编译器进行编译和新编译器编译,在同样机器下运行时间不同。
  2. 同一个算法程序,用⼀个老低配置机器和新高配置机器,运行时间也不同。
  3. 并且时间只能程序写好后测试,不能写程序前通过理论思想计算评估。

那么算法的时间复杂度是一个函数式T(N),到底是什么呢?

答:这个T(N)函数式计算了程序的执行次数。

通过c语言编译链接章节学习,我们知道算法程序被编译后生成二进制指令,程序运行,就是cpu执行这些编译好的指令。那么我们通过程序代码或者理论思想计算出程序的执行次数的函数式T(N),假设每句指令执行时间基本一样(实际中有差别,但是微乎其微),那么执行次数和运行时间就是等比正相关, 这样也脱离了具体的编译运行环境。执行次数就可以代表程序时间效率的优劣。比如解决一个问题的算法a程序T(N)=N,算法b程序T(N)=N^2,那么算法a的效率⼀定优于算法b。

示例:

//请计算⼀下Func1中++count语句总共执行了多少次?void Func1(int N)
{int count = 0;for (int i = 0; i < N; ++i){for (int j = 0; j < N; ++j){++count;}}for (int k = 0; k < 2 * N; ++k){++count;}int M = 10;while (M--){++count;}
}

画图表示:

解析:实际中我们计算时间复杂度时,计算的也不是程序的精确的执行次数,精确执行次数计算起来还是很麻烦的(不同的⼀句程序代码,编译出的指令条数都是不⼀样的),计算出精确的执行次数意义也不大, 因为我们计算时间复杂度只是想比较算法程序的增长量级,也就是当N不断变大时T(N)的差别,上面我们已经看到了当N不断变大时常数和低阶项对结果的影响很小,所以我们只需要计算程序能代表增长量级的大概执行次数,复杂度的表示通常使用大O的渐进表示法。


三、大O的渐进表示法

大O符号(BigOnotation):是用于描述函数渐进行为的数学符号

推导大O阶规则:

  1. 时间复杂度函数式 T(N) 中,只保留最高阶项,去掉那些低阶项,因为当 N 不断变大时, 低阶项对结果影响越来越小,当 N 无穷大时,就可以忽略不计了。
  2. 如果最高阶项存在且不是 1 ,则去除这个项目的常数系数,因为当 N 不断变大,这个系数对结果影响越来越小,当 N 无穷大时,就可以忽略不计了。
  3. T(N) 中如果没有 N 相关的项目,只有常数项,用常数 1 取代所有加法常数

通过大O渐进表示法,我们可以推出上述 Func1 的时间复杂度了:(因为主要是++count的运行次数,所以时间复杂度也是主要计算它的运行次数)

 

示例1:

//计算Func2的时间复杂度?void Func2(int N)
{int count = 0;for (int k = 0; k < 2 * N; ++k){++count;}int M = 10;while (M--){++count;}printf("%d\n", count);
}

画图表示:


示例2:

//计算Func3的时间复杂度?void Func3(int N, int M)
{int count = 0;for (int k = 0; k < M; ++k){++count;}for (int k = 0; k < N; ++k){++count;}printf("%d\n", count);
}

画面表示:

解释:如果M>>N,则时间复杂度可以为O(M),反之N>>M,则时间复杂度可以写成O(N),如果M==N,则时间复杂度为O(M+N)


示例3:

//计算Func4的时间复杂度?void Func4(int N)
{int count = 0;for (int k = 0; k < 100; ++k){++count;}printf("%d\n", count);
}

画图表示:


示例4:

//计算strchr的时间复杂度?const char* strchr(const char* str, int character)
{const char* p_begin = str;while (*p_begin != character){if (*p_begin == '\0')return NULL;p_begin++;}return p_begin;
}

画图表示:

通过上面我们会发现,有些算法的时间复杂度存在最好、平均和最坏情况。

  • 最坏情况:任意输入规模的最大运行次数(上界)
  • 平均情况:任意输入规模的期望运行次数
  • 平均情况:任意输入规模的期望运行次数

大O的渐进表示法在实际中一般情况关注的是算法的上界,也就是最坏运行情况。

因此示例4的时间复杂度应该为:O(N)


示例5:冒泡排序

//计算BubbleSort的时间复杂度?void BubbleSort(int* a, int n)
{assert(a);for (size_t end = n; end > 0; --end){int exchange = 0;for (size_t i = 1; i < end; ++i){if (a[i - 1] > a[i]){Swap(&a[i - 1], &a[i]);exchange = 1;}}if (exchange == 0)break;}
}

画图表示:


示例6:对数的计算

//求时间复杂度void func5(int n)
{int cnt = 1;while (cnt < n){cnt *= 2;}
}

画图表示:

注:log 的底数可写可不写,如果底数为10可写成 lg


示例7:递归的计算

//计算阶乘递归Fac的时间复杂度?long long Fac(size_t N)
{if (0 == N)return 1;return Fac(N - 1) * N;
}

画图表示:


四、空间复杂度

空间复杂度也是一个数学表达式,是对一个算法在运行过程中因为算法的需要额外临时开辟的空间。

空间复杂度计算规则基本跟时间复杂度类似,也使用大O渐进表示法

注意:函数运行时所需要的(函数栈帧)栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好 了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。

空间复杂度计算示例

示例1:冒泡排序

//计算BubbleSort的空间复杂度?void BubbleSort(int* a, int n)
{assert(a);for (size_t end = n; end > 0; --end){int exchange = 0;for (size_t i = 1; i < end; ++i){if (a[i - 1] > a[i]){Swap(&a[i - 1], &a[i]);exchange = 1;}}if (exchange == 0)break;}
}

画图表示:

示例2:递归函数

//计算阶乘递归Fac的空间复杂度?long long Fac(size_t N)
{if (N == 0)return 1;return Fac(N - 1) * N;
}

画图表示:


五、常见复杂度对比

常见的复杂度有:n、logn、n*logn、n的平方、n的三次方、2的n次方、n的阶乘

解析:很明显,n的平方、n的三次方、2的n次方、n的阶乘这些复杂度都比较高。而n、logn、n*logn这些复杂度就比较低,算法的效率比较高。


总结

        以上就是本文的全部内容,感谢支持

相关文章:

数据结构之算法复杂度

目录 前言 一、复杂度的概念 二、时间复杂度 三、大O的渐进表示法 四、空间复杂度 五、常见复杂度对比 总结 前言 本文主要讲述数据结构中的算法复杂度 一、复杂度的概念 算法在编写成可执行程序后&#xff0c;运行时需要耗费时间资源和空间(内存)资源。因此衡量一个算法的好坏…...

Python用TOPSIS熵权法重构粮食系统及期刊指标权重多属性决策MCDM研究|附数据代码...

原文链接&#xff1a;https://tecdat.cn/?p37724 在当今世界&#xff0c;粮食系统的稳定性至关重要。尽管现有的全球粮食系统在生产和分配方面表现出较高的效率&#xff0c;但仍存在大量人口遭受饥饿以及诸多粮食安全隐患。与此同时&#xff0c;在学术领域&#xff0c;准确评估…...

【例题】lanqiao4403 希尔排序模板题

插入排序每次只能将数据移动一位。 已知插入排序代码为&#xff1a; def insert_sort(a):for i in range(1,len(a)):ji-1while j>0 and a[j]>a[i]:a[j1]a[j]j-1a[j1]a[i]return a希尔排序在插入排序的基础上&#xff0c;将数据移动n/2,n/4,…,1位。 for i in range(ga…...

【C/C++】速通涉及string类的经典编程题

【C/C】速通涉及string类的经典编程题 一.字符串最后一个单词的长度代码实现&#xff1a;&#xff08;含注释&#xff09; 二.验证回文串解法一&#xff1a;代码实现&#xff1a;&#xff08;含注释&#xff09; 解法二&#xff1a;&#xff08;推荐&#xff09;1. 函数isalnum…...

MySQL:库表的基本操作

库操作 查看 查看存在哪些数据库&#xff1a; show databases;查看自己当前处于哪一个数据库&#xff1a; select database(); 由于我不处于任何一个数据库中&#xff0c;此处值为NULL 查看当前有哪些用户连接到了MySQL&#xff1a; show processlist; 创建 创建一个数据库 语…...

JS领域的AI工程利器分享

JavaScript&#xff0c;这个在网页开发中广为人知的脚本语言&#xff0c;正逐渐在AI工程领域展现出其独特的魅力。对于那些希望将大语言模型&#xff08;LLM&#xff09;融入项目的开发者来说&#xff0c;以下五个JavaScript工具将是关键资源。 1. TensorFlow.js TensorFlow.…...

2024/9/20 使用QT实现扫雷游戏

有三种难度初级6x6 中级10x10 高级16x16 完成游戏 游戏失败后&#xff0c;无法再次完成游戏&#xff0c;只能重新开始一局 对Qpushbutton进行重写 mybutton.h #ifndef MYBUTTON_H #define MYBUTTON_H #include <QObject> #include <QWidget> #include <QPus…...

09.20 C++对C的扩充以及C++中的封装、SeqList

SeqList.h #ifndef SEQLIST_H #define SEQLIST_H#include <iostream> #include<memory.h> #include<stdlib.h> #include<string.h>using namespace std;//typedef int datatype; //类型重命名 using datatype int;//封装一个顺序表 class Seq…...

Git提交类型

说明&#xff1a;Git提交类型指的是代码commit时&#xff0c;写在comment前面的标志&#xff0c;表示此次commit的提交类型&#xff0c;如下&#xff1a; Git提交类型 常见的Git提交类型有&#xff1a; feat&#xff1a;新特性、新功能或优化&#xff1b; fix&#xff1a;修复…...

C++速通LeetCode简单第18题-杨辉三角(全网唯一递归法)

全网唯一递归法&#xff1a; vector<vector<int>> generate(int numRows) {vector<int> v;vector<vector<int>>vn;if (numRows 1){v.push_back(1);vn.push_back(v);v.clear();return vn;//递归记得return}if (numRows 2){v.push_back(1);vn.p…...

Redis作为单线程模型,为什么效率高、速度快呢?

前言&#xff1a; 效率高、速度快是相较于数据库来说的&#xff08;MySQL、Orcale、SQL server&#xff09; 文章目录 一、单线程模式的工作流程二、为什么快&#xff1f; 一、单线程模式的工作流程 这里我们所说的单线程是指&#xff1a;Redis只使用一个线程&#xff0c;来处…...

人工智能——猴子摘香蕉问题

一、实验目的 求解猴子摘香蕉问题&#xff0c;根据猴子不同的位置&#xff0c;求解猴子的移动范围&#xff0c;求解对应的过程&#xff0c;针对不同的目标状态进行求解。 二、实验内容 根据场景有猴子、箱子、香蕉&#xff0c;香蕉挂天花板上。定义多种谓词描述位置、状态等…...

对ViT 中Patch Embedding理解

借鉴了这个博主的ViT Patch Embedding理解-CSDN博客&#xff0c;再加了一些理解。 就通过代码来理解吧 假设输入图像的维度为HxWxC&#xff0c;分别表示高&#xff0c;宽和通道数。 PatchEmbed 的类&#xff0c;它继承了 nn.Module&#xff0c;实现了将输入的2维图像&#…...

Redis基本命令详解

1. 基本命令 命令不区分大小写&#xff0c;而key是区分大小写的 # select 数据库间的切换 数据库共计16个 127.0.0.1:6379> select 1# dbsize 返回当前数据库的 key 的数量 127.0.0.1:6379[1]> dbsize# keys * 查看数据库所有的key 127.0.0.1:6379[1]> keys *# fl…...

Java之线程篇四

目录 volatile关键字 volatile保证内存可见性 代码示例 代码示例2-&#xff08;volatile&#xff09; volatile不保证原子性 synchronized保证内存可见性 wait()和notify() wait()方法 notify() 理解notify()和notifyAll() wait和sleep的对比 volatile关键字 volati…...

计算机毕业设计之:基于微信小程序的校园流浪猫收养系统

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…...

SpringBoot:关于Redis的配置失效(版本问题)

我们使用redis时发现yaml配置中的redis相关配置不生效&#xff0c;后面发现将配置修改甚至删除所有相关redis的配置&#xff0c;springboot依然能使用redis里面默认的db0并且不报错。上网查阅了一些文章&#xff0c;也都没有解决今天分享下&#xff0c;我的处理方法, SpringBo…...

halcon 快速定义字典

定义一个名为params的字典 Params : dict{} 等价于用 create_dict (Params ) 为字典添加键值对&#xff0c;在halcon中箭只能是字符串&#xff0c;值可以是任何类型的obj或者tuple Params.remove_outer_edges : true Params.max_gap : 150 等价于用 set_dict_object (true,…...

Sublime text3怎么关闭提示更新

问题 sublime text 3有新版本后,会不停地在每次启动后弹窗提示更新版本 第一步 软件安装之前&#xff0c;切记是软件安装之前&#xff01;&#xff01;&#xff01;需要在hosts中添加以下内容(屏蔽官网联网检测)&#xff1a;hosts的位置一般在C:\Windows\System32\drivers\etc…...

生成式语言模型技术栈

生成式语言模型的最新技术栈正在快速发展&#xff0c;尤其是随着大规模预训练模型&#xff08;LLMs&#xff09;和生成式AI的应用不断扩展。以下是当今最前沿的生成式语言模型技术栈&#xff0c;涵盖从模型开发到优化、推理和部署的各个环节。 1. 基础模型开发 基础模型开发包…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准

城市路内停车管理常因行道树遮挡、高位设备盲区等问题&#xff0c;导致车牌识别率低、逃费率高&#xff0c;传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法&#xff0c;正成为破局关键。该设备安装于车位侧方0.5-0.7米高度&#xff0c;直接规避树枝遮…...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...