数据结构——算法和算法效率的度量

目录

一、引言

二、算法

1 算法的基本概念

 2 算法的复杂度

2.1 时间复杂度

2.1.1 概念

2.1.2 大O的渐进表示

3 算法的空间复杂度

3.1 概念

 3.2 实例

4 实例分析

5 结论


一、引言

大家在写代码的时候有没有发现写同样功能的代码有多种不同的写法,而不同的代码也会给我们的程序带去不同的影响,比如有的代码执行的快,有的代码执行的慢;有的代码申请的空间大,有的代码申请的空间小,那这是为什么呢?因为是算法不同呀,那为什么不同呢,接下来就由姜糖给大家讲讲算法这一特殊的名词。

二、算法

1 算法的基本概念

算法(Algorithm)是对特定问题求解步骤的一种描述,它是指令的有限序列,其中的每条指令表示一个或多个操作。此外,一个算法还具有下列五个重要特性:

  • 有穷性。一个算法必须总在执行有穷步之后结束,且每一步都可在有穷时间内完成。
  • 确定性。算法中每条指令必须有确切的含义,对于相同的输入只能得出相同的输出。
  • 可行性。算法中描述的操作都可以通过已经实现的基本运算执行有限次来实现。
  • 输入。一个算法有零个或多个输入,这些输入取自于某个特定的对象的集合。
  • 输出。一个算法有一个或多个输出,这些输出是与输入有着某种特定关系的量。

通常,设计一个“好”的算法应考虑达到以下目标:

  • 正确性。算法应能够正确地解决求解问题。
  • 可读性。算法应具有良好的可读性,以帮助人们理解。
  • 健壮性。算法能对输入的非法数据做出反应或处理,而不会产生莫名其妙的输出。
  • 高效率与低存储量需求。效率是指算法执行的时间,存储量需求是指算法执行过程中所需要的最大存储空间,这两者都与问题的规模有关。


 2 算法的复杂度

算法效率的度量是通过时间复杂度和空间复杂度来描述的。

2.1 时间复杂度

说起时间可能有的人就会说,运行时间嘛我也会,把代码放在电脑上面跑一下就知道了。那大家想过没,我拿学校机房大LOL都卡的电脑和家里豪华rog全家桶来跑一个代码,他们的运行时间会一样吗?那有的人可能会说那放在同一台电脑上跑不就行了吗?那万一网卡了呢,时间不就又不一样了。所以算法中就有一个时间复杂度的概念

2.1.1 概念

时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度

 那接下来我们来看一个程序来找出他的执行次数:

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:
    }

    printf("%d\n",count);
}

次数:

F(N)=N^{2}+2*N+10

当我们发现当N足够大时,2*N+10对函数的影响可以忽略不记,所以F(N)=N^{2} 。

所有我们计算时间复杂度的时候,我们其实并不一定有计算精确的次数,只需要一个大概就好了,所有我们这里可以用大O的渐进表示法。

2.1.2 大O的渐进表示

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

推导大O阶的方法:

  1. 用常数1取代运行时间中的所有加法常数。
  2. 在修改后的运行次数函数中,只保留高阶项。
  3. 如果最高阶项存在且不是1,且去除于这个项目相乘的常数。得到的结果就是大O阶。

所以上面例子代码的时间复杂度为:

                                                     O(N^{2})

*时间复杂度中,变量一般用N表示。

接下来再举一个让我们对大O阶渐进表示有更深一步的认识:

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);
}

 那么这个函数的时间复杂度为什么呢?

F(N)=2N+10,只保留最高项,然后去掉最高项的常数,所以最后为O(N)。

在大O渐进表示中有一些特殊的:

  • 比如有两个变量N和M,在没有特殊说明N或者M远远大于另外一个时:O(N+M);
  • O(常数)时用O(1)表示

接下来我们再来举一个例子:

const char strchr( const char* str, int character)
{
    while(*str)
    {
        if(*str==character)
            return str;

    ++str;
    }
}

这是一个在字符串中查找的函数

他的次数不固定,最好的情况为 O(1),最坏的情况是O(n),平均情况是O(n/2)。那我们该选择哪种情况呢?

这算法中我们一般选择最坏的运行情况,以保证算法的运行时间不会比它更长。

就如同我们生活中约会一样,我们到达的时间不可能比对象晚,不然后果很严重,所以我们要把最坏的时间告诉她,给我们留下充足的时间赴约。


3 算法的空间复杂度

3.1 概念

空间复杂度:也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度 。 空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。 空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法。 注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因 此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。

 3.2 实例

下面我们来看代码进行分析:

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

该函数为阶乘递归,自身的递归每进行一次都会重新创造一个变量N,如图:

所以该函数创造的变量为N+1,用大O渐进法空间复杂度为O(N)。


4 实例分析

我们现在学习了空间复杂度和时间复杂度,那接下来我们用一道题结束今天的文章:

斐波那契数列(递归方法):

#include<stdio.h>

int Fibonacci(int N)
{
	if (N < 3)
	{
		return 1;
	}
	else
		return Fibonacci(N - 1) + Fibonacci(N - 2);
}



int main()
{
	printf("%d", Fibonacci(10));
	return 0;
}

大家想想它的时间和空间复杂度为多少呢?

在分析之前我想告诉大家的是,做这类题的时候我们画图是很有利于我们理解的,如图:

根据话题我们可以轻而易举的知道函数时间复杂度的大O为O(2^{N})(绿色部分缺少为常数所以忽略不计)

而时间复杂度呢,可能有人觉得也是O(2^{N}),答案却是错误的。那这是为什么呢?

那是因为函数是按照顺序执行的,如图函数肯定是先执行1然后执行完销毁完内存后才会执行2,

 而空间内存算的是函数执行需要的空间,当部分函数执行完的时候,空间就会被销毁,后续的函数会重新利用这一部分被销毁的空间,所以我们在这里算空间复杂度的时候,又该选择执行最大的一条如图蓝色部分,则最大申请变量为N+1,用大O渐进法表示则为:O(N)。

*大家注意

时间的消逝是回不来了的

空间是一直在的,是可以重复利用的


5 结论

姜糖最近因为特殊情况正逐步向着数据结构的方向前进,如有不足请大佬们帮我指出,姜糖也会不断去更新自己博客,不断反思完善自我,与各位一起迈入大牛之列。希望大家能一键三连,谢谢大家!

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

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

相关文章

Lab_ Finding and exploiting an unused API endpoint

https://portswigger.net/web-security/learning-paths/api-testing/api-testing-identifying-and-interacting-with-api-endpoints/api-testing/lab-exploiting-unused-api-endpoint# 查看功能点&#xff1a; 在Burp的HTTP history中发现 /api路径 我们先尝试一下将API请求…

ArcGIS JSAPI 学习教程 - ArcGIS Maps SDK for JavaScript - 框选显示高亮几何对象

ArcGIS JSAPI 学习教程 - ArcGIS Maps SDK for JavaScript - 框选显示高亮对象 核心代码完整代码&#xff1a;在线示例 在研究 ArcGIS JSAPI RenderNode 高亮&#xff08;highlights&#xff09;FBO 的时候&#xff0c;实现了一下框选高亮几何对象&#xff0c;这里分享一下。 …

Python Pygments库:代码高亮的利器

更多Python学习内容&#xff1a;ipengtao.com Pygments是一个用于Python的强大语法高亮库。它支持多种编程语言和标记格式&#xff0c;能够将源代码转换为高亮格式的文本&#xff0c;使代码在阅读和展示时更加清晰易懂。Pygments广泛应用于博客、文档、代码编辑器和IDE中&#…

视频会员干货收藏

这个文章绝对价值几百块&#xff0c;可以省去你不少视频会员的钱。但还是建议大家支持正版。。。 只推荐货真价实的好东西&#xff0c;谁用谁知道。无论电影还是电视剧更新速度还是很快的&#xff0c;而且最重要的一点&#xff0c;你连注册都不用注册&#xff0c;直接看&#x…

宝兰德应用服务器软件通过保险业信息技术应用创新攻关实验室产品适配测试认证

近期&#xff0c;宝兰德中间件核心产品「应用服务器软件 V9.5.5」&#xff08;以下简称&#xff1a;应用服务器软件&#xff09;顺利通过了保险业信息技术应用创新攻关实验室产品适配测试。标志着宝兰德应用服务器软件符合信息技术产品适配要求&#xff0c;能够全面支持金融保险…

【网络基础1】

文章目录 学习目标一、网络基础11.网络的重要性2.osi7层模式3.协议和osi7层模型的关系4.数据的封装和解封装5.tcp的三次握手6.Ddos攻击讲解7.Tcp的四次挥手 二、网络基础21.文字编码2.IP地址的划分3.子网掩码4.同网段ip才能直接通信5.DNS解析6.DNS解析命令7.短域名为什么值钱8.…

项目工具|git相关

本博客暂时只作为个人资料&#xff0c;后续会进行完善&#xff0c;主要内容来自&#xff1a; 【【Git第一讲】&#xff1a;git分区与两个盒子的故事】 理解暂存区和未暂存区 git为什么要多一个暂存区&#xff1f;难道不能我把代码写完后就是未暂存区&#xff0c;然后直接提交…

mysql设置允许外部ip访问,局域网IP访问

&#xff08;支持MYSQL8版本&#xff09; 1. 登录进入mysql&#xff1b;mysql -uroot -p输入密码进入 2. 输入以下语句&#xff0c;进入mysql库&#xff0c;查看user表中root用户的访问 use mysql; select host,user from user; 3. 更新user表中root用户域属性&#xff0c…

STM32——ADC篇(ADC的使用)

一、ADC的介绍 1.1什么是ADC ADC&#xff08;Analogto-Digital Converter&#xff09;模拟数字转换器&#xff0c;是将模拟信号转换成数字信号的一种外设。比如某一个电阻两端的是一个模拟信号&#xff0c;单片机无法直接采集&#xff0c;此时需要ADC先将短租两端的电…

深度学习(三)

5.Functional API 搭建神经网络模型 5.1利用Functional API编写宽深神经网络模型进行手写数字识别 import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn.datasets import load_irisfrom sklearn.model_selection import train_test_splitfrom…

SVNCloud 与 Navicat和IDEA的连接

文章目录 SVNCloud 配置Navicat访问云端数据库与IDEA Java jdbc 的连接 SVNCloud 配置 访问网址&#xff1a;SVN注册账号&#xff0c;进入mysql区域&#xff1a; 数据库管理->创建数据库&#xff0c;输入数据库名称和密码&#xff0c;注意&#xff0c;这里的数据库名称实际…

vue 如何制作一个跟随窗口大小变化而变化的组件

vue 如何制作一个跟随窗口大小变化而变化的组件 像下图中展示的那些统计数件就是跟随窗口变化而变化的&#xff0c;而且是几乎等比缩放的。 实现原理 只简略说一下原理。 pinia 中记录一个窗口变化的高度值给要变化的组件添加一个高度值组件内部所有关于长度距离的值都通过这…

笔记 | 软件工程04:软件项目管理

1 软件项目及其特点 1.1 什么是项目 1.2 项目特点 1.3 影响项目成功的因素 1.4 什么是软件项目 针对软件这一特定产品和服务的项目努力开展“软件开发活动",&#xff08;理解&#xff1a;软件项目是一种活动&#xff09; 1.5 软件项目的特点 1.6 军用软件项目的特点 2 …

水库安全监测系统:智慧水文动态监测系统

TH-SW2水库安全监测系统&#xff0c;作为一款智慧水文动态监测系统&#xff0c;其在现代水利管理中扮演着至关重要的角色。该系统通过集成先进的数据采集、传输、处理和分析技术&#xff0c;为水库的安全运行提供了强有力的技术支撑。 水库安全监测系统是一种用于实时监测和记…

matplotlib绘制三维曲面图时遇到的问题及解决方法

在使用 Matplotlib 绘制三维曲面图时&#xff0c;可能会遇到一些常见的问题。今天我将全程详细讲解下遇到问题并且找到应对方法的全部过程&#xff0c;希望能帮助大家。 1、问题背景 在使用 matplotlib 绘制三维曲面图时&#xff0c;遇到了一个问题。代码如下&#xff1a; im…

Faiss框架使用与FaissRetriever实现

Faiss是一个由Facebook AI Research开发的库&#xff0c;用于高效相似性搜索和稠密向量聚类。它为机器学习和深度学习中的向量检索问题提供了一种高效的解决方案&#xff0c;特别是在处理大规模数据集时。Faiss支持多种索引类型&#xff0c;包括基于量化的索引、基于聚类的索引…

Ubuntu系统的k8s常见的错误和解决的问题

K8s配置的时候出现的常见问题 Q1: master节点kubectl get nodes 出现的错误 或者 解决方法&#xff1a; cat <<EOF >> /root/.bashrc export KUBECONFIG/etc/kubernetes/admin.conf EOFsource /root/.bashrc重新执行 kubectl get nodes 记得需要查看一下自己的…

倒计时 3 天!立即预约苹果 WWDC24 直播;RLAIF-V 大规模多模态偏好数据集上线,有效减少不同 MLLMs 幻觉现象

6 月 3 日-6 月 7 日&#xff0c;hyper.ai 官网更新速览&#xff1a; 优质公共数据集&#xff1a;10 个 优质教程精选&#xff1a;2 个 社区文章精选&#xff1a;3 篇 热门百科词条&#xff1a;5 条 6-7 月截稿顶会&#xff1a;5 个 访问官网&#xff1a;hyper.ai 公共数…

37. 【Java教程】序列化与反序列化

上一小节我们学习了 Java 的输入输出流&#xff0c;有了这些前置知识点&#xff0c;我们就可以学习 Java 的序列化了。本小节将介绍什么是序列化、什么是反序列化、序列化有什么作用&#xff0c;如何实现序列化与反序列化&#xff0c;Serializable 接口介绍&#xff0c;常用序列…

【JavaEE精炼宝库】多线程(4)深度理解死锁、内存可见性、volatile关键字、wait、notify

目录 一、死锁 1.1 出现死锁的常见场景&#xff1a; 1.2 产生死锁的后果&#xff1a; 1.3 如何避免死锁&#xff1a; 二、内存可见性 2.1 由内存可见性产生的经典案例&#xff1a; 2.2 volatile 关键字&#xff1a; 2.2.1 volatile 用法&#xff1a; 2.2.2 volatile 不…