算法的基本概念

文章介绍了数据结构的两大类——线性结构(如数组、队列、链表和栈)和非线性结构(如散列表、多维数组、树结构和图结构),并重点讨论了算法的时间复杂度分析,包括大O表示法的概念,以及常見的时间复杂度级别如O(1)、O(logn)、O(n)、O(nlogn)和O(n²)。同时,文章也触及了空间复杂度,指出空间复杂度是对算法运行过程中临时占用存储空间大小的度量,并给出了O(1)和O(n)的空间复杂度示例。
摘要由CSDN通过智能技术生成

1、基本概念和术语

数据结构主要包括:线性结构非线性结构

线性结构

线性结构有两种不同的存储结构:

  • 顺序存储结构

    顺序存储的 线性表 称为 顺序表,顺序表中的存储元素 都是连续

  • 链式存储结构

    链式存储的 线性表 称为 链表,链表中的存储元素 不⼀定是连续 的,元素节点中存放 数据元素 以及 相邻元素的地址信息

线性结构常⻅的有:

  • 数组 队列 链表 栈

非线性结构

它的元素之间⾄少不是 1 对 1 的关系了

⾮线性结构包括:

  • 散列表
  • 多维数组
  • 树结构
  • 图结构

在非线性结构中,树结构和图结构⽤的最多的
在这里插入图片描述

2、复杂度分析

2.1、时间复杂度分析

2.1.1、什么是⼤O表示法

【⼤O表示法】算法的的渐进时间复杂度: T(n) = O(f(n))

⼤O表示法:算法的时间复杂度通常⽤⼤O符号表述,定义为Tn = O(f(n))。称函数T(n)以f(n)为界或者称T(n)受限于f(n)。 如果⼀个问题的规模是n,解这⼀问题的某⼀算法所需要的时间为T(n)。T(n)称为这⼀算法的“时间复杂度”。当输⼊量n逐渐加⼤时,时间复杂度的极限情形称为算法的“渐近时间复杂度”。

2.1.2、⼤O表示算法的时间举例

案例1:

O(1+3N) = O(N)

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

案例2:

O(n²)

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

案例3:

O(n+n²) = O(n²)

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

2.1.3、常⻅的⼤O表示法

O(1)

O(1) 只是常量级时间复杂度的⼀种表示⽅法,并不是指只执⾏了⼀⾏代码。⽐如这段代码,即便有3⾏,它的时间复杂度也是O(1),⽽不是O(3)。

int i =8;
int j = 10;
int m = i+j;

总结:只要代码的执⾏时间不随 n 的增⼤⽽增⻓,这样代码的时间复杂度都记作O(1)。或者说,⼀般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万⾏的代码,其时间复杂度也是Ο(1)。

O(logn)

O(logn)也叫做对数时间复杂度,对数阶时间复杂度⾮常常⻅,同时也是最难分析的⼀种时间复杂度。通过下⾯的代码来分析对数时间复杂度。

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

根据我们前⾯讲的复杂度分析⽅法,第三⾏代码是循环执⾏次数最多的。所以,我们只要能计算出这⾏代码被执⾏了多少次,就能知道整段代码的时间复杂度。从代码中可以看出,由于变量i每次在乘以2之后都会更加逼近n,也就是说,在有x次后,cnt将会⼤于n从⽽跳出循环,所以(2^x= n), 也就是(x = log2n),循环结束。所以这个代码循环的复杂度为O(logn)

O(n)

O(n)也叫做线性时间,通常指⼀次for循环所话费的时间⽐如这段代码。⼀个for循环,他的时间复杂度是O(n),⽽不是O(4)

for(int i = 0;i<4;i++){
}

O(n*logn)

O(nlogn)也叫做线性对数阶,就是n乘以logn,当数据增⼤256倍时,耗时增⼤256 8=2048倍。这个复杂度⾼于线性低于平⽅。

通过下⾯的代码来分析线性对数阶时间复杂度。

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

通过代码中可以看出,当i=1时,循环n次,当i=2时,需要执⾏n/2次,当i=n时,需要执⾏n/n次, 每次的时间复杂度为O(1),则总共的时间复杂度为n(1 +1/2+1/3+1/4 + 1/5+ 1/6+1/7+1/8 +…1/n),那么通过筛选到总结 时间复杂度时等于nln(n+1)+rn,所以是O(n*logn)。

O(n^2)

O (n^2)也叫做线性平⽅阶,就代表数据量增⼤n倍时,耗时增⼤n的平⽅倍,这是⽐线性更⾼的时间复杂度。

通过下⾯的代码来分析线性对数阶时间复杂度

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

由O(n)的代码分析可以得知,⼀个for循环是O(n),那么两个for循环就是O(n)*O(n),所以整合下来就是O (n^2)。

以下便是常⻅的时间复杂度量级:
在这里插入图片描述
常数阶O(1) | 对数阶O(logN) | 线性阶O(n) | 线性对数阶O(nlogN) | 平⽅阶O(n²) | ⽴⽅阶O(n³) | K次⽅阶O(n^k) | 指数阶(2^n) | 阶乘O(n!)

2.2 、空间复杂度分析

空间复杂度是对⼀个算法在运⾏过程中临时占⽤存储空间⼤⼩的量度,所谓的临时占⽤存储空间指的就是代码中**「辅助变量所占⽤的空间」,它包括为参数表中「形参变量」分配的存储空间和为在函数体中定义的「局部变量」**分配的存储空间两个部分。我们⽤ S(n)=O(f(n))来定义,其中n为问题的规模(或⼤⼩)。通常来说,只要算法不涉及到动态分配的空间,以及递归、栈所需的空间,空间复杂度通常为0(1)。⼀个⼀维数组 a[n] ,空间复杂度O(n),⼆维数组为O(n^2)。

下⾯看两个常⻅的空间复杂度示例:空间复杂度O(1)和O(n)。

空间复杂度 O(1)

空间复杂度为O(1)的情况的示例代码与时间复杂度为O(1)的实例代码⼀致:

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

上述代码中临时空间并不会随着n的变化⽽变化,因此空间复杂度为O(1)。总结⼀下就是:如果算法执⾏所需要的临时空间不随着某个变量n的⼤⼩⽽变化,此算法空间复杂度为⼀个常量,可表示为 O(1),即 S(n) = O(1)。

空间复杂度 O(n)

int j = 0;
int[] m = new int[n];
for (int i = 1; i <= n; ++i) {
 j = i;
 j++;
}

上述代码中,只有创建int数组分配空间时与n的⼤⼩有关,⽽for循环内没有再分配新的空间,因此,对应的空间复杂度为S(n) = O(n)。

⼩结: 【时间空间复杂度】= 时间和空间增⻓的趋势

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值