一文概括复杂度分析

6217760-c5d5141d75bbb777.jpg

复杂度分析法则:

  • [单段代码看频率]:看代码片段中「循环代码」的时间复杂度。

  • [多段代码看最大]:如果多个 for 循环,看「嵌套循环最多」的那段代码的时间复杂度。

  • [嵌套代码求乘积]:循环、递归代码,将内外嵌套代码求乘积去时间复杂度。

  • [多个规模求加法]:法有两个参数控制两个循环的次数,那么这时就取二者复杂度相加。

----------------------------------❤------------------------------------

时间复杂度

1、什么是复杂度?

所有代码的执行时间 T(n)与每行代码的执行次数n成正比【T(n) = O(f(n)) 】。

2、分析的三个方法

最多法则

忽略掉公式中的常量、低阶、系数,取最大循环次数就可以了,也就是循环次数最多的那行代码。

Example:

// 求n个数字之和
int xiaolu(int n) {
   int sum = 0;
   for (int i = 1; i <= n; ++i) {
     sum = sum + i;
   }
   return sum;
 }

分析:

第二行是一行代码,也就是常量级别,与 n 没有关系,可以忽略,四、五行代码是我们重点分析对象,与 n 有关,时间复杂度就是反映执行时间和 n 数据规模的关系。求 n 个数据之和需要执行 n 次。所以时间复杂度为 O(n)。

加法法则

总复杂度等于循环次数最多的那段复杂度。

Example:

int xiaolu(int n) {
    int sum = 0;
    //循环一
    for (int i = 1; i <= 100; j++) {
      sum = sum + i;
    }
    //循环二
    for (int j = 1; j <= n; j++) {
       sum = sum + i;
   }
 }

分析:
上边有两个循环,一个循环 100 次,另一个循环 n 次,我们选择循环次数最多的那一个且和「数据规模 n 」相关的循环。由上可知,我们很容易选出循环二,即和数据规模 n 有关,循环次数最多,循环次数最多的那段代码时间复杂度就代表总体的时间复杂度,为 O(n) ;

乘法法则

当我们遇到嵌套的 for 循环的时候,怎么计算时间复杂度呢?那就是内外循环的乘积。

Example:

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

分析:

外循环一次,内就循环 n 次,那么外循环 n 次,内就循环 n*n 次。所以时间复杂为 O(n²)。

空间复杂度

1、什么是空间复杂度?

表示算法的「存储空间」与「数据规模」之间的增长关系.

Example:

 int xiaolu(int n) {
    int sum = 0;
    //循环一
    for (int i = 1; i <= 100; j++) {
      sum = sum + i;
    }
    //循环二
    for (int j = 1; j <= n; j++) {
       sum = sum + i;
   }
 }

分析:

在所有代码中,我们很容易寻找到存储空间相关的代码,就是第二行,申请了一个 n 大小的存储空间,所以空间复杂度为 O(n)。

2、最常见的空间复杂度

O(1)、O(n)、O(n²)。

O(1)

常量级的时间复杂度表示方法,无论是一行代码,还是多行,只要是常量级的就用 O(1) 表示。

Example:

int i = 1;
int j = 2;
int sum = i + j;

分析:

因为这三行代码,也就是常量级别的代码不随 n 数据规模的改变而改变。(循环、递归除外)

O(logn) | O(nlogn)

「对数阶时间复杂度」,最难分析的一种时间复杂度。

Example:

 i=1;
 while (i <= n)  {
   i = i * 3;
 }

分析:

要求这段代码的时间复杂度就求这段代码执行了多少次,看下图具体分析。

6217760-532f23c9e150a7ce.jpg

补充:
不管是以 2 为底、以 3 为底,还是以 10 为底,可以把所有对数阶的时间复杂度都记为 O(logn),因为对数之间可以转换的,参照高中课本

O(m+n) | O(mn)*

参照上边讲到的加法和乘法法则。

----------------------------------❤------------------------------------

1、最好、最坏时间复杂度

所谓的最好、最坏时间复杂度分别对应代码最好的情况和最坏的情况下的执行。

Example

 //在一个 array 数组中查找一个数据 a 是否存在
for (int i = 1; i < n; i++) {
    if (array[i] == a) {
       return i;
    }
 }

分析:

1、最好情况就是数组的第一个就是我们要查找的数据,上边代码之执行一遍就可以,这种情况下的时间复杂度为最好时间复杂度,为 O(1)。

2、最坏的情况就是数组的最后一个才是我们要查找的数据,需要循环遍历 n 遍数组,也就对应最坏的时间复杂度为 O(n) 。

2、平均时间复杂度

平均时间复杂度需要借助概率论的知识去分析,也就是我们概率论中所说的加权平均值,也叫做期望值。

分析:

比如上方的例子,假设我们查找的数据在数组中的概率为 1/2;出现在数组中的概率为 n/1,根据下边的公式就可以算出出现的概率为 1/2n 。

6217760-f5832c2707175b3e.jpg

然后我们再把每种情况考虑进去,就可以计算出平均时间复杂度。

6217760-717934634ceb55fb.jpg

3、均摊时间复杂度

什么是均摊时间复杂度?

比如我们每 n 次插入数据的时间复杂度为 O(1),就会有一次插入数据的时间复杂度为 O(n),我们将这一次的时间复杂度平均到 n 次插入数据上,时间复杂度还是 O(1)。

适用场景

一般应用于某一数据结构,连续操作时间复杂度比较低,但是个别情况时间复杂度特别高,我们将特别高的这一次进行均摊到较低的操作上。

几种复杂度性能对比

各个时间复杂度的性能


6217760-21006321b67eb3f1.jpg

===========我是华丽的分割线===========


更多知识:
点击关注专题:嵌入式Linux&ARM

或浏览器打开:https://www.jianshu.com/c/42d33cadb1c1

或扫描二维码:

6217760-e6bba06e005d8fe7.jpg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Linux内核是操作系统的核心部分,它负责管理系统资源并维护系统的稳定运行。它主要由三部分组成:内存管理、进程管理和文件系统。内存管理负责管理系统的内存使用,包括分配和回收内存。进程管理负责管理系统中的进程,包括创建、撤销和调度进程。文件系统管理系统中的文件和目录。内核还提供了许多其他的功能,如网络协议栈和设备驱动程序。学习Linux内核需要有一定的编程基础和对操作系统原理的了解。 ### 回答2: Linux内核是操作系统的核心部分,主要负责管理计算机的硬件资源和提供系统调度、管理、安全与稳定性等核心功能。作为一个开源软件,Linux内核不断地得到开发者们的改进和完善,同时也成为了大量不同操作系统的基础。在本文中,我们将会讨论Linux内核的架构、进程管理、内存管理、驱动程序以及调试等一些基础概念。 架构 Linux内核的总体架构可以看做是分层结构。从最底层到最上面依次是: 硬件层(Hardware Layer):主要进行I/O操作和系统调用,以及一些I/O设备驱动。 内核层(Kernel Layer):主要负责内存和驱动管理。 进程管理层(Process Management Layer):负责进程、线程等程序的管理。 文件系统层(File System Layer):负责文件系统和存储设备的管理。 用户空间(User Space Layer):系统内重要的子系统,负责处理系统中进程的上下文切换、调度、同步与通信。 进程管理 内核使用进程对计算机的各项任务进行管理和调度。每个进程都有独立的内存空间,由内核进行分配和管理。进程的状态有“运行”、“阻塞”和“挂起”三种,它们的转换会受到各种条件和操作的影响,比如时间片、信号、资源的请求等。 内存管理 Linux内核采用虚拟内存管理的方式来管理内存。虚拟内存中,实际的物理内存被映射到虚拟地址空间中,每个进程都拥有独立的虚拟地址空间,这样就避免了进程之间的内存冲突。当进程需要访问虚拟地址空间中的某个内存页面时,内核会将其映射到物理内存中,并且决定在何时将其清空回收。 驱动程序 Linux内核中的驱动程序主要负责各种硬件设备的控制和管理。它们与内核紧密结合,可以通过内核函数或者系统调用来与硬件进行交互,完成一些特定的任务。Linux内核提供了丰富的驱动程序支持,包括网络设备、磁盘设备、USB设备、声卡、显卡等等。驱动程序的实现依赖于底层硬件的特性,因此需要不断更新和维护,以确保系统稳定性。 调试 调试是软件开发过程中的重要环节之一。Linux内核的调试主要通过打印信息、跟踪、性能度量等方式实现。内核中包括了许多内置的调试工具,如KDB (Kernel Debugger)、KGDB (Kernel GDB)、Ktrace、Sysprof等。调试时需要注意到内核会不断地占用CPU资源,给系统带来较大的压力,需谨慎使用。 通过以上的简要介绍,相信读者已经对Linux内核有了一个大致的了解。了解Linux内核的基础知识不仅可以帮助我们有效地设计、编写和调试软件,也可以进一步深入了解操作系统和计算机系统的工作原理。 ### 回答3: Linux内核是Linux操作系统最核心的部分,它提供了操作系统的基本功能和服务,例如文件管理、进程和内存管理等。本文将从六个方面来介绍Linux内核,帮助读者了解Linux内核的基本结构和功能。 一、内核基本结构:由多个模块构成,包括进程管理、内存管理、文件系统和驱动程序等。这些模块之间通过一系列的接口来进行通信和协作,从而提供基本的操作系统服务。 二、进程管理:进程是指正在运行的程序实例,进程管理模块负责创建、销毁和调度进程,以及提供进程间通信和同步等功能。 三、内存管理:内存管理模块负责分配和管理内存资源,包括虚拟内存管理、物理内存管理和缓存管理等功能。 四、文件系统:文件系统模块提供文件管理功能,可以将数据存储在硬盘上并进行读写操作,同时提供了文件访问控制和权限管理等功能。 五、驱动程序:驱动程序模块负责管理硬件设备,如网卡、显卡和打印机等,可以与硬件设备进行通信和控制。 六、系统调用:系统调用是Linux内核对外提供的API,可以通过系统调用接口来访问内核提供的功能。例如,用户可以通过系统调用来创建进程、读写文件或打开设备等。 总之,Linux内核是操作系统的基础,它为上层应用和服务提供了基本的支持和保障。了解和理解Linux内核的结构和功能,可以帮助开发者更好地掌握Linux操作系统和编写高质量的软件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leon_George

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值