数据结构与算法复杂度介绍

news2024/11/16 23:58:18

目录

一、基本概念

二、时间复杂度

【2.1】时间复杂度概念

【2.2】大O的渐进表示法

【2.3】举例时间复杂度计算

三、空间复杂度


一、基本概念

数据结构:相互之间存在一种或者多种特定关系的数据元素的集合。在逻辑上可以分为线性结构,散列结构、树形结构,图形结构等等。

算法:求解具体问题的步骤描述,代码上表现出来是解决特定问题的一组有限的指令序列。

算法复杂度:时间和空间复杂度,衡量算法效率,算法在执行过程中,随着数据规模n的增长,算法执行所花费的时间和空间的增长速度。

常见的时间复杂度

表达式大O表示法方程
5201314O(1)常数阶
3n+4O(n)线性阶
3n^2+4n+5O(n^2)平方阶
3log(2)n+4O(logn)对数阶
2n+3nlog(2)n+14O(nlogn)nLogn阶
n^3+2n^2+4n+6O(n^3)立方阶
2^nO(2^n)指数阶

常见算法的时间复杂度关系:O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(2^n) < O(n!) < O(n^n)

【复杂度指标对比】

【创建的数据结构算法的复杂度】

大O计法应用示例
O(1)数组随机访问、哈希表
O(logn)二分搜索、二叉堆调整、AVL、红黑树查找
O(n)线性搜索
O(nlogn)堆排序、快速排序、归并排序
O(n^2)冒泡排序、选择排序、插入排序
O(2^n)子集树
O(n!)排列树

二、时间复杂度

【2.1】时间复杂度概念

        时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?

        是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。

        即:找到某条基本语句与问题规模N之间的数学表达式,就是算出了该算法的时间复杂度。

// 请计算一下Func1中++count语句总共执行了多少次?
void Func1(int N)
{
	int count = 0;
	for (int i = 0; i < N; ++i) // 循环次数为N^2
	{
		for (int j = 0; j < N; ++j)
		{
			++count;
		}
	}

	for (int i = 0; i < 2 * N; i++) // 循环次数为2 * N
	{
		++count;
	}

	int M = 10;
	while (M--) // 循环次数为10
	{
		++count;
	}

	printf("%d\n", count);
}
// Func1 执行的基本操作次数 :F(N) = (N^2) + (2 * N) + 10
// 比如:N = 10		F(N) = 130
// 比如:N = 100		F(N) = 10210
// 比如:N = 1000	F(N) = 1002010
// 上面N越大后面两项对整个表达式的影响是越来越小的
// 实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法。
// 最终以大概的次数:上面代码的时间复杂度是N^2

【2.2】大O的渐进表示法

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

【推导大O阶方法】

  • 用常数1取代运行时间中的所有加法常数,O1并不代表是1次,而是代表是常数次。

  • 在修改后的运行次数函数中,只保留最高阶项

  • 如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

【使用大O的渐进表示法以后,在推到一下Func1的时间复杂度为】

// Func1 执行的基本操作次数 :F(N) = (N^2) + (2 * N) + 10
// 比如:N = 10		F(N) = 130
// 比如:N = 100		F(N) = 10210
// 比如:N = 1000		F(N) = 1002010
// 结果:去掉(2*N)去掉(10) -> 时间复杂度是N^2

        通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数,另外有些算法的时间复杂度存在最好、平均和最坏情况:

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

  • 平均情况:任意输入规模的期望运行次数。

  • 最好情况:任意输入规模的最小运行次数(下界)。

  • 例如:在一个长度为N数组中搜索一个数据x。

  • 最好情况:1次找到。

  • 最坏情况:N次找到。

  • 平均情况:N/2次找到。

在实际中一般情况关注的是算法的最坏运行情况!

【2.3】举例时间复杂度计算

【实例】

// 计算Func2的时间复杂度?
void Func2(int N)
{
	int count = 0;
	for (int k = 0; k < 2 * N; ++k)// 循环次数:2 * N
	{
		++count;
	}

	int M = 10;
	while (M--) // // 循环次数:10
	{
		++count;
	}
	printf("%d\n", count);
}
// 正常为:(2 * N) + 10 
// 在此:10 影响不大, 2为固定值影响不大,影响时间复杂度的是N
// 以大O表示法:O(N)

【实例】

// 计算Func3的时间复杂度?
void Func3(int N, int M)
{
	int count = 0;
	for (int k = 0; k < M; ++k) // 循环次数为:M次
	{
		++count;
	}
	for (int k = 0; k < N; ++k) // 循环次数为:N次
	{
		++count;
	}
	printf("%d\n", count);
}
// 正常为:M + N
// 在此:M 和 N 的准确值都是不知道的,所以都算在时间复杂度成员里
// 以大O表示法:O(M + N)

【实例】

// 计算Func4的时间复杂度?
void Func4(int N)
{
	int count = 0;
	for (int k = 0; k < 100; ++k) // 循环次数为:100次
	{
		++count;
	}
	printf("%d\n", count);
}
// 正常为:100次
// 在此:N 没有参与任何东西
// 以大O表示法:O(1)

【实例】

// 计算strchr的时间复杂度?
const char * strchr(const char * str, int character); // O(N)

【实例】

// 计算BubbleSort的时间复杂度?
void BubbleSort(int* a, int n)
{
	assert(a);
	for (size_t end = n; end > 0; --end) // 循环次数为:等差数列
	{									 // N-1 N-2 N-3 N-4.... -> 1+2+3+N-1 = N(N-1)/2
		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;
	}
}
// 正常为:
// 在此:实例5基本操作执行最好N次,最坏执行了(N*(N+1)/2次,通过推导大O阶方法+时间复杂度一般看最坏,时间复杂度为 O(N ^ 2)
// 以大O表示法:O(N^2)这是最坏的情况加
// 最好的情况下是O(N)

【实例】

// 计算BinarySearch的时间复杂度?
int BinarySearch(int* a, int n, int x) // O(N * Log(2)n)
{
	assert(a);

	int begin = 0;
	int end = n - 1;
	while (begin <= end)
	{
		int mid = begin + ((end - begin) >> 1);
		if (a[mid] < x)
			begin = mid + 1;
		else if (a[mid] > x)
			end = mid - 1;
		else
			return mid;
	}
	return -1;
}

【实例】

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

【实例】

// 计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N) // O(2^N) -> 斐波那契数相当于是一个很垃圾的算法
{
	if (N < 3)
		return 1;
	return Fib(N - 1) + Fib(N - 2);
} 

// 优化
long long Fac(size_t N) 
{
	if (N < 3)
		return 1;

	long long f1 = 1, f2 = 1, f3;
	for (size_t i = 3; i <= N; i++)
	{
		f3 = f1 + f2;
		// 迭代
		f1 = f2;
		f2 = f3;
	}

	return f3;
}

三、空间复杂度

空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度

        空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法

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

【实例】

// 计算BubbleSort的空间复杂度?
void BubbleSort(int* a, int n) // 常数个额外空间,所以空间复杂度为 O(1)
{
	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;
	}
}

【实例】

// 计算Fibonacci的空间复杂度?
// 返回斐波那契数列的前n项
long long* Fibonacci(size_t n) // 动态开辟了N个空间,空间复杂度为 O(N)
{
	if (n == 0)
	{
		return NULL;
	}
		
	long long * fibArray = (long long *)malloc((n + 1) * sizeof(long long));

	fibArray[0] = 0;
	fibArray[1] = 1;
	for (int i = 2; i <= n; ++i)
	{
		fibArray[i] = fibArray[i - 1] + fibArray[i - 2];
	}
	return fibArray;
}

【实例】

// 计算阶乘递归Fac的空间复杂度?
long long Fac(size_t N) // 递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间。空间复杂度为O(N)
{
	if (N == 0)
		return 1;
	return Fac(N - 1) * N;
}

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

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

相关文章

关于 ignore

当使用 insert into xxx 时&#xff0c;可能出现因数据类型错误插入失败的情况&#xff0c;如图所示&#xff1a; 当出现这种情况时&#xff0c;可以通过 ignore 来“强制”插入&#xff0c;提示插入成功 但是这种操作会带来隐患如图&#xff1a; 时间有问题&#xff0c;但是时…

SMU200A/罗德与施瓦茨SMU200A信号发生器

181/2461/8938产品概述 R&S SMU200A信号发生器旨在满足现代通信系统研发及其生产中遇到的所有要求。R&S SMU200A矢量信号发生器不仅将多达两个独立的信号发生器组合在一个只有四个高度单位的机柜中&#xff0c;还提供无与伦比的RF和基带特性。 Rohde & Schwarz S…

如何让Android平台像网络摄像机一样实现GB28181前端设备接入?

技术背景 好多开发者在做国标对接的时候&#xff0c;首先想到的是IPC&#xff08;网络摄像头&#xff09;&#xff0c;通过参数化配置&#xff0c;接入到国标平台&#xff0c;实现媒体数据的按需查看等操作。 像执法记录仪等智能终端&#xff0c;跑在Android平台&#xff0c;…

mysql主从同步步骤(一主一从)

1、主库添加binlog配置&#xff0c;并设置server-id server-id124 # 设置日志格式,日志路径(注意路经需要mysql用户有权限写&#xff0c;默认地址放在datadir的目录下) binlog_formatmixed log-binmysql-bin# 设置binlog清理时间(秒), binlog每个日志文件大小 binlog_expire_l…

线上问诊:数仓开发(三)

系列文章目录 线上问诊&#xff1a;业务数据采集 线上问诊&#xff1a;数仓数据同步 线上问诊&#xff1a;数仓开发(一) 线上问诊&#xff1a;数仓开发(二) 线上问诊&#xff1a;数仓开发(三) 文章目录 系列文章目录前言一、ADS1.交易主题1.交易综合统计2.各医院交易统计3.各性…

行业追踪,2023-09-04

自动复盘 2023-09-04 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

实时操作系统Freertos开坑学习笔记:(四):临界段保护、列表与列表项

前言 废话不多说&#xff0c;直接看主要要探究的问题&#xff1a; 一、临界段代码保护 1.什么是临界段&#xff1f; 图里面说&#xff0c;临界区的代码是不能被打断的&#xff0c;它运行时不能被中断打断&#xff0c;也不能由于非阻塞任务延时而切换到其他任务去。 比如说…

【Java转Go】Go中使用WebSocket实现聊天室(私聊+群聊)

目录 前言功能效果&#xff08;一人分饰多角.jpg&#x1f60e;&#xff09;用户上线、群聊私聊和留言下线 实现思路代码服务端 chat.go 完整代码客户端 html 完整代码 最后 前言 之前在Java中&#xff0c;用 springbootwebsocket 实现了一个聊天室&#xff1a;springbootwebso…

用BAPI创建销售订单条件价格有多个

说明&#xff1a; 在用BAPI_SALESORDER_CREATEFROMDAT2创建销售订单的时候&#xff0c;业务配置的是Z001自动出来的&#xff0c;我在BAPI条件那块赋值更改标识也是U&#xff0c;但是创建出来的单据还是有两条件类型。 解决方法&#xff1a; LOGIC_SWITCH-PRICING G .即可

AP9193 升压恒流驱动芯片 美容护肤仪 美容灯 锂电池升压驱动IC

AP9193 是一款高效率、高精度的升 压型大功率 LED 灯恒流驱动控制芯片。 应用领域 LED 灯杯 电池供电的 LED 灯串 平板显示 LED 背光 恒流充电器控制 大功率 LED 照明 AP9193 内置高精度误差放大器&#xff0c;固 定关断时间控制电路&#xff0c;恒流驱动电路等&#xff…

签到系统怎么设计

背景 相信签到系统大家都有接触过&#xff0c;更多的是使用。但是有思考过这种系统是怎么设计的吗&#xff1f;比方说我统计一下每个月中每天的签到情况&#xff0c;怎么设计呢&#xff1f;今天一篇文章告诉你。 首先&#xff0c;我们熟悉的思维是&#xff1a;我设计一个数据…

电商平台-业务中台-SPU,SKU,SN概念简介

什么是SPU &#xff08;Standard Product Unit)? SPU标准属性是商品基本属性&#xff0c;基本属性中最核心两个属性是品牌和型号&#xff0c;电商平台一般采用 品牌和型号 来确定SPU&#xff08;Standard Product Unit&#xff09;标准化管理单元&#xff0c; 例如:小米 10 就…

Vue3 el-tooltip 根据内容控制宽度大小换行和并且内容太短不显示

el-tooltip 根据长度自适应换行以及显隐 环境 vue: "3.2.37" element-ui: "2.1.8"要求 tooltip 根据内容自动换行如果内容超出显示省略号显示&#xff0c;不超出不显示 tooltip 代码 组件 // ContentTip 组件 <template><el-tooltipv-bind&qu…

excel中的引用与查找函数篇1

1、COLUMN(reference)&#xff1a;返回与列号对应的数字 2、ROW(reference)&#xff1a;返回与行号对应的数字 参数reference表示引用/参考单元格&#xff0c;输入后引用单元格后colimn()和row()会返回这个单元格对应的列号和行号。若参数reference没有引用单元格&#xff0c;…

SOME/IP TTL 在各种Entry 中各是什么意思?有什么限制?

1 服务发现 SOME/IP SD 服务发现主要用于 定位服务实例检测服务实例状态是否在运行发布/订阅行为管理SOME/IP SD 也是 SOME/IP 消息,遵循 SOME/IP 消息格式,有固定的 Message ID、Request ID 以及 Message Type 等。并对 SOME/IP Payload 进行了详细的定义。 SOME/IP SD …

2023-9-4 快速幂求逆元

题目链接&#xff1a;快速幂求逆元 #include <iostream> #include <algorithm>using namespace std;typedef long long LL;LL qmi(int a, int k, int p) {LL res 1;while(k){if(k & 1) res (LL) res * a % p;k >> 1;a (LL) a * a % p;}return res; }i…

能力和结果之间的关系

大家好,这里是大话硬件。 今天这篇文章想和大家分享前段时间的一点工作体会,关于个人能力和工作结果之间的关系。 其实这些感悟是在上周三晚上下班,走在回家的路上,脑海中突然出现这样的体会,回到家里立马写了下来。因为是即时的灵感,完全是因为工作状态触发,立刻写下…

手写RPC框架--4.服务注册

RPC框架-Gitee代码(麻烦点个Starred, 支持一下吧) RPC框架-GitHub代码(麻烦点个Starred, 支持一下吧) 服务注册 服务注册a.添加服务节点和主机节点b.抽象注册中心c.本地服务列表 服务注册 a.添加服务节点和主机节点 主要完成服务注册和发现的功能&#xff0c;其具体流程如下&…

智能配电室运维云平台

智能配电室运维云平台依托电易云-智慧电力物联网&#xff0c;是通过物联网技术实现配电设备智能化管理和运维的云服务系统。该平台可以实时监测配电设备的运行状态、能耗情况、故障报警等信息&#xff0c;并通过云计算、大数据等技术进行分析和处理&#xff0c;提供精准的数据支…

数据结构前言

一、什么是数据结构&#xff1f; 数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。 上面是百度百科的定义&#xff0c;通俗的来讲数据结构就是数据元素集合与数据元素集合或者数据元素与数据元素之间的组成形式。 举个…