数据结构之算法复杂度

目录

前言

一、复杂度的概念

二、时间复杂度

三、大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这些复杂度就比较低,算法的效率比较高。


总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

python源代码编译exe 防止反编译的问题

1&#xff09;使用pyinstaller 打包为exe, 记住是版本是5.*&#xff0c;我用的是5.13.2 &#xff0c;不能是6.* 这是第一步。 pyinstaller -F -i d:\whs.ico packer.py -w 2&#xff09;使用pyarmor 再次加密,我使用的版本是8.3.11&#xff0c;不是7.*&#xff0c;这是第二步…

摩托车骑行行为检测系统源码分享

摩托车骑行行为检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comput…

Cursor Rules 让 Cursor AI 代码生成更智能、更高效,效率再次飞升!

最近,AI 代码生成工具越来越火,比如 Cursor AI 编辑器。很多开发者已经开始使用它来自动生成代码,以提高工作效率。不过你有没有发现,有时候 AI 自动生成的代码并不总是符合最佳实践?比如变量命名不够规范、代码风格不统一,或者生成的代码逻辑不够清晰。这些问题有时让人…

c# 线程等待变量的值符合条件

在C#中&#xff0c;如果你想让一个线程等待直到某个变量的值满足特定条件&#xff0c;你可以使用ManualResetEvent或者AutoResetEvent来实现线程间的同步。以下是使用AutoResetEvent实现的一个简单例子&#xff1a; 在这个例子中&#xff0c;同时实现了如何让static函数访问非…

闲鱼ip地址在哪就是人在哪吗

在数字化时代&#xff0c;IP地址作为网络设备的唯一标识&#xff0c;常被用于追踪用户的地理位置。然而&#xff0c;对于闲鱼这样的二手交易平台&#xff0c;用户的IP地址是否真实反映了其所在地&#xff0c;却是一个值得深入探讨的问题。本文将围绕这一话题展开&#xff0c;带…

单卡3090 选用lora微调ChatGLM3-6B

环境配置 Python 3.10.12 transformers 4.36.2 torch 2.0.1 下载demo代码 在官方网址https://github.com/THUDM/ChatGLM3/blob/main/finetune_demo 下载demo代码cd 进入文件夹 pip install -r requirements.txt 安装一些包 基本知识 SFT 全量微调: 4张显卡平均分配&#…

昂科烧录器支持ST意法半导体的电可擦除可编程存储器M95128-DFDW

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中ST意法半导体的电可擦除可编程存储器M95128-DFDW已经被昂科的通用烧录平台AP8000所支持。 M95128-DFDW是电可擦除可编程存储器&#xff08;EEPROM&#xff09;通过SPI总线进行…

springcloud微服务实战<1>

单机结构 我只需要一台服务器完成我项目的部署&#xff08;单体应用&#xff09;&#xff0c;开发部署简单 他就会有单点问题&#xff0c; 因为此时只有一台机器&#xff0c;一旦这个机器挂了&#xff0c;我用户就没有办法使用应用的服务了 这个就是单点问题针对我们的项目进…

Qt/C++ 多线程同步机制详解及应用

在多线程编程中&#xff0c;线程之间共享资源可能会导致数据竞争和不一致的问题。因此&#xff0c;采用同步机制确保线程安全至关重要。在Qt/C中&#xff0c;常见的同步机制有&#xff1a;互斥锁&#xff08;QMutex、std::mutex&#xff09;、信号量&#xff08;QSemaphore&…

多模态大模型MiniCPM-V技术学习

目前性价比最高的多模态模型 Minicpm-V-2.6参数8B&#xff0c;int4版本推理显存仅7GB&#xff0c;并且在幻觉数据集上效果好于其他模型&#xff0c;测试下来效果非常好&#xff0c;官方演示里面还给出了手机上端侧运行的图片和视频推理示例 p.s.Qwen2-VL和Minicpm-V-2.6头对头…

【操作系统】02.深入理解操作系统

一、操作系统的定位 任何计算机系统都包含一个基本的程序集合&#xff0c;称为操作系统(OS)。笼统的理解&#xff0c;操作系统包括操作系统内核和其他程序。 由上述的宏观图其实我们就知道&#xff1a;操作系统是一款进行软硬件资源管理的软件。 二、设计操作系统的目的 操…

众数信科AI智能体政务服务解决方案——寻知智能笔录系统

政务服务解决方案 寻知智能笔录方案 融合民警口供录入与笔录生成需求 2分钟内生成笔录并提醒错漏 助办案人员二次询问 提升笔录质量和效率 寻知智能笔录系统 众数信科AI智能体 产品亮点 分析、理解行业知识和校验规则 AI实时提醒用户文书需注意部分 全文校验格式、内…

C一语言—动态内存管理

目录 一、为什么要有动态内存管理 二、malloc和free &#xff08;2.1&#xff09;malloc &#xff08;2.2&#xff09;free 三、calloc和realloc &#xff08;3.1&#xff09;calloc &#xff08;3.2&#xff09;realloc 四、常见的动态内存的错误&#xff08;举例均为错…

springboot每次都需要重设密码?明明在springboot的配置中设置了密码

第一步&#xff1a;查看当前的密码是什么&#xff1f; 打开redis-cli.exe&#xff0c;输入config get requirepass&#xff0c;查看当前的密码是什么&#xff1f; 接着&#xff0c;修改redis的配置文件&#xff0c;找到redis的安装目录&#xff0c;找到相关的conf文件&#x…

Amazon Bedrock 模型微调实践(二):数据准备篇

本博客内容翻译自作者于 2024 年 9 月在亚马逊云科技开发者社区发表的同名博客&#xff1a; “Mastering Amazon Bedrock Custom Models Fine-tuning (Part 2): Data Preparation for Fine-tuning” 亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、…

Unity3D入门(一) : 第一个Unity3D项目,实现矩形自动旋转,并导出到Android运行

1. Unity3D介绍 Unity3D是虚拟现实行业中&#xff0c;使用率较高的一款软件。 它有着强大的功能&#xff0c;是让玩家轻松创建三维视频游戏、建筑可视化、实时三维动画等互动内容的多平台、综合型 虚拟现实开发工具。是一个全面整合的专业引擎。 2. Unity安装 官网 : Unity…

1042 Shuffling Machine,1050 String Subtractio

1042 Shuffling Machine 普通模拟即可&#xff0c;注意每一次交换牌的时候需要更新start数组&#xff08;当前卡牌的顺序&#xff09;&#xff0c;并且清空ans数组&#xff08;交换后的卡牌顺序&#xff09; #include<bits/stdc.h> using namespace std; const int N 5…

hal 正点原子 exti外部中断

1.这个是 f4/f7/h7 用于配置外部中断的寄存器 需要先使能时钟 2.这个是f1用于配置外部中断的配置器&#xff0c;也是需要先配置时钟&#xff0c;但是区别在于除了f1 &#xff0c;别的系列都用的SYSCFG 3.这个是外部中断线io和怎么exti对应的 4.这两张图 都是exti和io的对应关系…

QFramework v1.0 使用指南 更新篇:20240919. 新增 BindableDictionary

虽然笔者目前还不知道 BindableDictionary 能用在什么使用场景下&#xff0c;但是还是应童鞋的要求实现了 BindableDictionary。 基本使用如下: using System.Linq; using UnityEngine;namespace QFramework.Example {public class BindableDictionaryExample : MonoBehaviou…

【设计模式】UML类图

目录 前言 一、类图概述 二、类图的作用 三、类图表示法 四、类之间关系的表示方法 1. 关联关系 1.1 单向关联 1.2 双向关联 1.3 自关联 2. 聚合关系 3. 组合关系 4. 依赖关系 5. 继承关系 6. 实现关系 总结 前言 统一建模语言&#xff08; Unified Modeling La…