数据结构和算法的基本概念, 算法复杂度,时间,空间复杂度

2023-11-12

概念

a)数据结构是研究数据之间组织结构的一门学科。
数据结构可以理解为一组数据在计算机中的存储结构或者理解为相互之间存在一种或者多种特定关系的数据集合。

b)算法是操作数据解决特定问题的求解步骤和方法。 一个问题可以有多种算法。

c)数据结构和算法的关系:数据结构服务于算法,算法也要作用于特定的数据结构之上,两者相辅相成,不能孤立。

d)算法五个特性:输入;输出;有穷性;确定性;可行性;

e)一个好的算法通常有四个设计要求:正确性;可读性;健壮性;高时间效率和低存储量需求;

大O时间复杂度表示法

公式T(n) = O(f(n)),其中:
a)n:表示问题规模的大小
b)T(n):表示算法的执行时间(T指的Time),也就是算法的时间复杂度。
c)f(n):表示代码的执行次数总和。
d)O:表示代码的执行时间T(n)与F(n)的函数关系(正比关系);

看几个例子(加法规则)

	//1+1001+1000+1 = 2003  =    2n+3次
	void calc(int n) //n=1000 问题规模
	{
		int sum = 0;    //执行1次;
		for(int i = 1; i <= n; ++i)  //执行1001次
		{
			sum = sum + i;    //执行1000次
		}
		cout << sum << endl; //执行1次
	}

这个函数用公式表示为 T ( n ) = O ( 2 n + 3 ) = O ( n ) T(n) = O(2n+3) = O(n) T(n)=O(2n+3)=O(n)

	for (int j = 1; j <= n; ++j)//执行1001次
	{
		for (int k = 1; k <= n; ++k) //1001 * 1000 = 1001000次
		{
			sum = sum + k;  //1000 * 1000次 = 1000000次
		}
	}

用公式表示为 T ( n ) = O ( n 2 ) T(n) = O( n^2) T(n)=O(n2)

(乘法规则)例子

	int testfunc(int n) //O(n)
	{
		int sum = 0;
		for (int i = 1; i <= n; ++i)
		{
			sum = sum + i;
		}
		return sum;
	}
	void cacl3(int n)  //O(n * n) = O(n^2)
	{
		int sum = 0;
		for (int i = 1; i <= n; ++i)
		{
			sum = sum + testfunc(i);
		}
	}

用公式表示为 O ( n ∗ n ) = O ( n 2 ) O(n * n) = O(n^2) O(nn)=O(n2)

算法时间复杂度计算规则

加法规则:若有 T 1 ( n ) = O ( f ( n ) ) , T 2 ( n ) = O ( g ( n ) ) T1(n) = O(f(n)), T2(n) = O(g(n)) T1(n)=O(f(n)),T2(n)=O(g(n)),则 T ( n ) = T 1 ( n ) + T 2 ( n ) = O ( m a x ( f ( n ) , g ( n ) ) ) T(n) = T1(n) + T2(n) = O(max(f(n),g(n))) T(n)=T1(n)+T2(n)=O(max(f(n),g(n)))
说明:加法规则的算法时间复杂度取决于阶数最高的代码段的复杂度

乘法规则: 若有 T 1 ( n ) = O ( f ( n ) ) , T 2 ( n ) = O ( g ( n ) ) T1(n) = O(f(n)), T2(n) = O(g(n)) T1(n)=O(f(n)),T2(n)=O(g(n)),则 T ( n ) = T 1 ( n ) ∗ T 2 ( n ) = O ( f ( n ) ) ∗ O ( g ( n ) ) = O ( f ( n ) ∗ g ( n ) ) T(n) = T1(n) * T2(n) = O(f(n)) * O(g(n)) = O(f(n) * g(n)) T(n)=T1(n)T2(n)=O(f(n))O(g(n))=O(f(n)g(n))
说明:乘法规则的算法时间复杂度取决于内外循环代码段时间复杂度的乘积.

常见算法时间复杂度

O ( 1 ) O(1) O(1):常数阶

void calc4(int n)
{
	int i = 100;
	int j = 15;
	int sum = i + j+n;
	cout << sum << endl;
}

O ( l o g 2 n ) O(log_2^n) O(log2n):对数阶

	void calc5(int n)
	{
		int i = 1;
		while (i <= n)  //2^x > n
		{
			i = i * 2; //i=i*3
		}
	}

补充:
i = i * 3的情况;
O ( l o g 3 n ) O(log_3^n) O(log3n) = = = O ( O( O( ( l o g 3 2 ) (log_3^2) (log32) × \times × ( l o g 2 n ) (log_2^n) (log2n) ) ) ) = l o g 2 n log_2^n log2n

O ( O( O( n n n × \times × l o g 2 n ) log_2^n) log2n):线性对数阶

	void calc6(int n)
	{
		int i = 1;
		for (int count = 0; count < n; ++count)
		{
			while (i <= n)
			{
				i = i * 2; //i=i*3
			}
		}
	}

O ( n 2 ) O(n^2) O(n2):平方阶

	void calc8(int n)
	{
		int sum = 0;
		for (int i = 1; i <= n; ++i)
		{
			for (int j = 1; j <= n; ++j)
			{
				sum++;
			}
		}
	}

特殊情况
O ( O( O( n 2 2 \frac{n^2}{2} 2n2 + + + n 2 \frac{n}{2} 2n ) ) ) = O ( n 2 ) O(n^2) O(n2)
结果依旧是 O ( n 2 ) O(n^2) O(n2)

	void calc81(int n)
	{
		int sum = 0;
		for (int i = 1; i <= n; ++i)
		{
			for (int j = i; j <= n; ++j) //n+(n-1)+(n-2)+....+1 -> 1+2+3+4+...+n :等差数列求和公式
			{                           // = n(n+1)/2 = n^2 / 2 + n / 2
				sum++;
			}
		}
	}

O ( m ∗ n ) O(m*n) O(mn)

void calc9(int m, int n)
{
	int sum = 0;
	for (int i = 1; i <= m; ++i)
	{
		for (int j = 1; j <= n; ++j)
		{
			sum++;
		}
	}
}

O ( m + n ) O(m+n) O(m+n)

void calc10(int m, int n)
{
	int sum1 = 0;
	for (int i = 1; i <= m; ++i)
	{
		sum1 += i;
	}

	int sum2 = 0;
	for (int j = 1; j <= n; ++j)
	{
		sum2 += j;
	}
}

最好、最坏、平均情况时间复杂度

最好情况时间复杂度,最坏情况时间复杂度,平均情况时间复杂度
最好情况: O ( 1 ) O(1) O(1)
最坏情况: O ( n ) O(n) O(n)
平均情况: O ( O( O( 1 + 2 + 3 + . . . + n n \frac{1+2+3+...+n}{n} n1+2+3+...+n ) ) ) = = = O ( O( O( n + 1 2 \frac{n+1}{2} 2n+1 ) ) ) = = = O ( n ) O(n) O(n)

	void calc11(int array[], int n, int x)  //n表示元素个数
	{
		int pos = -1;
		for (int i = 0; i < n; ++i)
		{
			if (array[i] == x)
			{
				pos = i;
				break;
			}
		}
		if (pos == -1)
			cout << "没找到值为" << x << "的元素" << endl;
		else
			cout << "找到了值为" << x << "的元素,其在数组中的位置下标为:" <<pos <<  endl;
	}

//调用
	int asz[5] = { 1,2,3,4,5 };
	calc11(asz, 5, 3);

总结

O ( 1 ) O(1) O(1):常数阶
O ( l o g n ) O(log^n) O(logn):对数阶
O ( n ) O(n) O(n):线性阶
O ( n l o g n ) O(nlog^n) O(nlogn):线性对数阶
O ( n 2 ) O(n^2) O(n2):平方阶
O ( n 3 ) O(n^3) O(n3):立方阶。由平方阶、立方阶,扩展出k次方阶用O(n^k)表示。
O ( 2 n ) O(2^n) O(2n):指数阶
O ( n ! ) O(n!) O(n!):阶乘阶

排序

O ( 1 ) < O ( l o g n ) < O ( n ) < O ( n l o g n ) < O ( n 2 ) < O ( n 3 ) < O ( 2 n ) < O ( n ! ) < O ( n n ) O(1) < O(log^n) < O(n) < O(nlog^n) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n) O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)
在这里插入图片描述

空间复杂度

运行时所需要的存储空间与问题规模之间的增长关系。

a) O ( 1 ) O(1) O(1):常数阶空间复杂度。需要固定大小内存空间的情形也叫做算法原地工作。

//无论n如何变化,在执行过程中,所需要的空间大小都是不变的
	void scalc(int n)
	{
		int i, sum = 0;
		for (i = 1; i <= n; ++i)
		{
			sum = sum + 1;
		}
		cout << sum << endl;
	}

b) O ( n ) O(n) O(n):线性阶空间复杂度。
如果每次递归调用所需要的内存空间大小固定不变,那么算法的空间复杂度一般都等于递归调用深度。

void scalc2(int n)
	{
		int* array = new int[n];
		for (int i = 1; i <= n; ++i) //4n+4
		{
			array[i] = 2 * i;
		}
		//记得释放内存
		delete[] array;
	}

//递归
void scalc21(int n)  //12*n   = O(n)
{
	int i, j;
	if (n > 1)
		scalc21(n - 1);
	cout << "n=" << n << endl;
}

//递归的另一种情况
void scalc22(int n) //递归调用n次,n+(n-1)+(n-2)+....+1。等差数列求和公式 = n(n+1) /2 = n^2/2 + n/2
{                   //O(n^2)
	int* p = new int[n];
	if (n > 1)
		scalc21(n - 1);
	cout << "n=" << n << endl;
	delete[]p;
}

注意:scalc22的空间复杂度为 O ( n 2 ) O(n^2) O(n2)
c) O ( n 2 ) O(n^2) O(n2):平方阶空间复杂度表示法

void scalc3(int n) //空间复杂度O(n^2)
	{
		//注意这里的动态二维数组的初始化代码
		int** array;
		array = new int* [n]; //4n
		for (int i = 0; i < n; ++i)
			array[i] = new int[n]; //每执行一次占用4n个字节。一共占用的是4n*n = 4n^2个字节的内存

		//注意动态二维数组的内存释放代码
		for (int i = 0; i < n; i++)
		{
			delete[] array[i];
		}
		delete[] array;
	}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构和算法的基本概念, 算法复杂度,时间,空间复杂度 的相关文章

随机推荐

  • eclipse中使用Install New software下载资源超时解决

    问题 使用eclipse中提供的Help菜单 Install New software 已填入正确的链接地址 但是在下载过程中出现错误 Some sites could not be found See the error log for
  • 宝塔面板升级踩坑:ImportError: class/PluginLoader.so: undefined symbol: PyImport_GetModule

    今天在宝塔面板升级了PHP8 但是站点的PHP版本选择仍然没有PHP8以上的版本 百度了一下说是要升级宝塔面板 于是在面板首页右上角进行了升级 结果升级后发现安全入口无法打开 于是用ssh登录服务器 执行命令 etc init d bt d
  • 推荐 20 款 IDEA 主题!

    官方对主题模块的介绍 作为一名开发人员 您需要使用大量文本资源 编辑器中的源代码 搜索结果 调试器信息 控制台输入和输出等等 颜色和字体样式用于格式化这个文本 并帮助您更好地理解它一目了然 个人感觉 每天我们大半的时间都是在跟代码打交道 时
  • Vue前端代码风格指南超级详细

    本文仅作日常项目开发中的知识补充 不必按顺序阅读 如果已经知悉 请跳过 一 命名规范 现有常用的命名规范 camelCase 小驼峰 首字母小写 PsscalCase 大驼峰 首字母大写 kebab case 短横线连接式 Snake 下划
  • VSCode好用的插件

    文章目录 前言 1 Snippet Creator easy snippet 自定义代码 2 Indent Rainbow 代码缩进 3 Chinese Simplified Language Pack 中文包 4 Path Intelli
  • react项目配置 @ 为src根目录

    前置 修改jsconfig json文件 compilerOptions jsx react experimentalDecorators true baseUrl paths src 1 原生create react app 的情况 若已
  • 16、什么是拟牛顿法(Quasi-Newton Methods)?

    拟牛顿法是求解非线性优化问题最有效的方法之一 于20世纪50年代由美国Argonne国家实验室的物理学家W C Davidon所提出来 Davidon设计的这种算法在当时看来是非线性优化领域最具创造性的发明之一 不久R Fletcher和M
  • CSharp: iTextSharp 5.13.2 create pdf

    using System using System Collections Generic using System Web using System Web UI using System Web UI WebControls using
  • 超级卡哇伊的登录框

    css margin 0 padding 0 box sizing border box a color 6a6a6a text decoration none body background color 96c6e2 box displa
  • multi-view clustering指标

    几种 multi view clustering 的指标代码 介绍见 1 3 4 6 有实现 Matching Assignment 由于聚类没有类顺序 而有些指标用到 ground truth labels 如 accuracy 等分类指
  • 操作系统识别

    1 操作系统指纹 操作系统的识别有很多方法 大多跟TCP IP协议有关 操作系统对TCP IP的实现 都是严格遵循RFC标准的 问题RFC标准仅描述了TCP IP的基本要求 并没有对所有内容形成统一的行业标准 于是各操作系统厂商在实现了TC
  • Free FTP Clients 客户端:WinSCP 的 3 种版本 (**)

    安装版 便携版 WinSCP Scripting 自动化 字符编码问题 在跨平台进行文件共享时 涉及到字符的编码问题 采用 ftp一般都可以解决乱码问题 而共享网络文件夹一般不能 ftp的一个问题是 当连接中断时 会造成文件的残缺 有些 f
  • Qt目录树实现

    1 View 根据参考资料 4 的说明 可以使用QTreeView或者QListView来显示目录树 2 Model 2 1 文件系统Model 实现一个系统文件目录树模式 可以选择使用QFileSystemModel或者QDirModel
  • java.lang.ClassCastException: cn.hutool.json.JSONObject cannot be cast toXXXX

    java lang ClassCastException cn hutool json JSONObject cannot be cast toXXXX 除了网上常见解决方案以外 也存在另一种可能导致的类型转换异常 例如 当使用JSONUt
  • Python中的条件循环

    1 if条件 1 1 语法规则 if的语法 if confident 条件判断为布尔型 doing thing true时完成的动作 else doing thing false时完成的动作 1 2 示例 if else 图 1 if示例
  • QT程序发布

    用Release版本运行 将生成的exe文件拷贝到一个空文件夹中 找到QT的cmd窗口 在cmd窗口中 用 cd 命令 进入第一步中建立的空文件夹中 运行命令windeployqt exe文件 将程序需要的库文件都导入该文件中 将整个文件夹
  • Python毕业设计基于django的企业人力资源管理系统

    文末获取资源 收藏关注不迷路 文章目录 一 项目介绍 二 主要使用技术 三 研究内容 四 核心代码 五 文章目录 一 项目介绍 在互联网信息技术时代中 企业管理更多的是使用管理系统进行智能化控制 提高单位的核心竞争力 适应快节奏的生产活动
  • 二分查找 binarySearch

    二分查找 binarySearch 基本概念 时间复杂度和空间复杂度 如何取mid Level 1 一般实现 迭代法 递归法 Level 2 First or Last Position of Target Last Position of
  • ue4 VR测量

    1 在tick函数里面构建测量需要的射线 2 在控制器书写测量函数
  • 数据结构和算法的基本概念, 算法复杂度,时间,空间复杂度

    目录 概念 大O时间复杂度表示法 看几个例子 加法规则 乘法规则 例子 算法时间复杂度计算规则 常见算法时间复杂度 O 1 O 1