数据结构与算法 -- 时间复杂度
数据结构与算法看完了,回过头来在看时间复杂度,对它们的效率做个比较吧。
一、时间复杂度介绍
1、时间复杂度定义
参看:数据结构-算法-时间复杂度计算
在进行算法分析,语句总得执行次数 T(n) 是关于问题规模 n 的函数,进而分析 T(n) 随 n 的变化情况并确定 T(n) 数量级。算法的时间复杂度,也就是算法的时间量度,记作:T(n) = O(f(n)),它表示随问题规模 n 的增大算法执行时间的增长率和 f(n) 的增长率相同,称作算法的渐近时间复杂度,简称为时间复杂度,其中 f(n) 是问题规模 n 的某个函数。
2、求解时间复杂度具体步骤
3、时间复杂度计算方法
4、常见的时间复杂度
(2)对数级复杂度:O(logN)
(3)线性级复杂度:O(N)
(4)线性对数级复杂度:O(NlogN)
(5)平方级复杂度:O(N^2)
执行次数函数 |
阶 |
非正式术语 |
12 |
O(1) |
常数阶 |
5log2^n + 20 |
O(logn) |
对数阶 |
2n + 3 |
O(n) |
线性阶 |
2n + 3nlog2^2 + 19 |
O(nlogn) |
线性对数阶 |
3n^2 + 2n + 1 |
O(n^2) |
平方阶 |
6n^3 + 2n^2 + 3n + 4 |
O(n^3) |
立方阶 |
2^n |
O(2^n) |
指数阶 |
二、具体说明各种时间复杂度
for(i=0;i<n;i++) ----------------------------- (1)
{for(j=0;j<n;j++) ------------------------- (2){c[i][j]=0; ------------------------------ (3)for(k=0;k<n;k++) ------------------- (4){c[i][j]=c[i][j]+a[i][k]*b[k][j]; ------- (5)}}
}
(1) for(i=0;i<n;i++) 频度为: n+1
(2) for(j=0;j<n;j++) 频度为:n*(n+1)
(3) c[i][j]=0 频度为:n*n
(4) for(k=0;k<n;k++) 频度为:n*n*(n+1)
(5) c[i][j]=c[i][j]+a[i][k]*b[k][j] 频度为:n*n*n
解释:
(2)与(1)不同,当 i 在 0~(n-1) 范围内,内层循环 [即是(2)的for循环] 频度为 n ; 当 i = n 时,内层循环语句没执行。所以相当此时第(1)中 for 循环执行了n次,第二个for 循环执行了n次,加上最后j=n跳出循环的判断,即,频度共 n * (n+1);
(3)此句语句,是要利用(1)、(2)for循环语句的i ,j 对 c[i][j] 进行赋值,此时,i 得到的赋值只有从 0 到 n , j 得到的赋值也是从0到n ,都是 n次,此时(当 i 达到n-1 .\当 j 达到 n-1.)的 i++ \j++都不会执行。 故,频度共 n*n 次;
(4)同上(1),(2)的理由,单独的(4)的for 循环执行了n+1 次,综上,频度为 n*n*(n+1);
(5)同理(3),对于三个for 循环, i 得到的赋值只有从 0 到 n , j 得到的赋值也是从0到n ,k得到的赋值也是从 0 到 n ,即,频度为n*n*n。
1、常数阶(O(1))
#include <stdio.h>int main (void)
{int n = 10;printf ("n = %d\n", n);printf ("n = %d\n", n);printf ("n = %d\n", n);printf ("n = %d\n", n);printf ("n = %d\n", n);printf ("n = %d\n", n);printf ("n = %d\n", n);printf ("n = %d\n", n);return 0;
}
(2)对数阶(O(logn))
#include <stdio.h>int main (void)
{int i = 1, n = 1000; //语句1while (i < n) i = i*2; //语句2return 0;
}
(3)线性阶(O(n))
#include <stdio.h>int main (void)
{int i = 0, sum = 0, n = 10; //语句1for (i = 0; i < n; i++) //语句2sum += i; //语句3printf ("sum = %d\n", sum); //语句4 return 0;
}
输出结果:
sum = 45
(4)线性对数阶(O(nlongn))
#include <stdio.h> void quick (int arr[], int left, int right)
{ int p = (left + right) / 2; int pivot = arr[p]; int i = 0, j = 0; for(i = left, j = right; i < j;) { while (arr[i] < pivot && i < p) i++; if (i < p) { arr[p] = arr[i]; p = i;} while(arr[j] >= pivot && j > p) j--; if (j > p) { arr[p] = arr[j]; p = j; } arr[p] = pivot; if(p - left > 1) quick (arr, left, p - 1); if (right - p > 1) quick (arr, p + 1, right); }
}
int main()
{ int arr[9] = {20, 8, 25, 3, 15, 9, 30, 5, 22}; quick (arr, 0, 8); int i = 0; for(i = 0; i < 9; i++) printf ("%d ", arr[i]); printf ("\n"); return 0;
}
输出结果:
3 5 8 9 15 20 22 25 30
(5)平方阶(O(n^2))
#include <stdio.h> int main (void)
{ int i, j, n = 10; //语句1for (i = 0;i < n; i++) //语句2{for (j = 0; j < n; j++) //语句3printf ("*"); printf ("\n"); }return 0;
}
(6)立方阶(O(n^3))
#include <stdio.h> int main (void)
{ int i, j, k, n = 3; //语句1for (i = 0;i < n; i++) //语句2{for (j = 0; j < n; j++) //语句3{for (k = 0; k < n; k++) //语句4printf ("*");printf ("\n");}}return 0;
}
分析:
(7)指数阶(O(2^n))
#include <stdio.h>
int i = 1;void move (int n, char from, char to)
{ printf ("第%d步:将%d号盘子%c---->%c\n", i++, n, from, to); //语句1
} void hanoi (int n, char from, char denpend_on, char to)
{ if (n == 1) move (1, from, to); else { hanoi (n - 1, from, to, denpend_on); move (n, from, to); hanoi (n - 1, denpend_on, from, to); }
} int main (void)
{ printf ("请输入盘子的个数:\n"); int n; scanf ("%d", &n); char x = 'A', y = 'B', z = 'C'; printf ("盘子移动情况如下:\n"); hanoi (n, x, y, z);
}
三、常用数据结构和算法的时间复杂度
1、数据结构部分
数据结构中常用的操作的效率表
通用数据结构 |
查找 |
插入 |
删除 |
遍历 |
数组 |
O(N) |
O(N) |
O(N) |
— |
有序数组 |
O(logN) |
O(N) |
O(N) |
O(N) |
链表 |
O(N) |
O(1) |
O(N) |
— |
有序链表 |
O(N) |
O(N) |
O(N) |
O(N) |
二叉树 |
O(logN) |
O(logN) |
O(logN) |
O(N) |
二叉树(最坏) |
O(N) |
O(N) |
O(N) |
O(N) |
红黑树 |
O(logN) |
O(logN) |
O(logN) |
O(N) |
2-3-4树 |
O(logN) |
O(logN) |
O(logN) |
O(N) |
哈希表 |
O(1) |
O(1) |
O(1) |
— |
专用数据结构 |
||||
栈 |
— |
O(1) |
O(1) |
— |
队列 |
— |
O(1) |
O(1) |
— |
优先级队列 |
— |
O(N) |
O(1) |
— |
优先级队列(堆) |
— |
O(logN) |
O(logN) |
2、排序部分
常见的排序算法比较表
排序 |
平均情况 |
最好情况 |
最坏情况 |
稳定与否 |
空间复杂度 |
冒泡排序 |
O(N2) |
O(N) |
O(N2) |
稳定 |
1 |
选择排序 |
O(N2) |
O(N2) |
O(N2) |
不稳定 |
1 |
插入排序 |
O(N2) |
O(N) |
O(N2) |
稳定 |
1 |
希尔排序 |
O(NlogN) |
(依赖于增量序列) |
不稳定 |
1 |
|
快速排序 |
O(NlogN) |
O(NlogN) |
O(N2) |
不稳定 |
O(logN) |
归并排序 |
O(NlogN) |
O(NlogN) |
O(NlogN) |
稳定 |
O(N) |
二叉树排序 |
O(NlogN) |
O(NlogN) |
O(N2) |
稳定 |
O(N) |
堆排序 |
O(NlogN) |
O(NlogN) |
O(NlogN) |
不稳定 |
1 |
拓扑排序 |
O(N+E) |
— |
— |
— |
O(N) |
3、平均和最坏时间复杂度
还以快排为例,如果每次均等划分,如果每次都是均等的划分即T(n)=T(n/2)+T(n/2)+O(n),即每次分成两段,则分的次数为logn,每一次处理需要n次计算,那么时间复杂度就是nlogn。如果每次的划分都是完全不平衡的即T(n)=T(n-1)+O(n),那么快排的时间复杂度是n^2。但它是不稳定的,无法确保它是否均等划分,因此我们说快排的平均时间复杂度是nlogn。
四、时间复杂度和实际运行时间
数据结构与算法 -- 时间复杂度相关推荐
- python数据结构和算法 时间复杂度分析 乱序单词检测 线性数据结构 栈stack 字符匹配 表达式求值 queue队列 链表 递归 动态规划 排序和搜索 树 图
python数据结构和算法 参考 本文github 计算机科学是解决问题的研究.计算机科学使用抽象作为表示过程和数据的工具.抽象的数据类型允许程序员通过隐藏数据的细节来管理问题领域的复杂性.Pytho ...
- 数据结构和算法 —— 时间复杂度+空间复杂度
算法效率的度量方法 事后统计方法 这种方法主要是通过设计好的测试程序和数据,利用计算机计时器对不同算法编制的程序的运行时间进行比较,从而确定算法效率的高低. 但这种方法显然是有很大缺陷的: 必须依据算 ...
- 大话数据结构之算法 时间复杂度
http://www.cnblogs.com/danyingjie/archive/2011/11/17/2252466.html 时间复杂度用O()来体现,我们称之为大O记法.记做:T(n)=O(f ...
- 数据结构与算法——时间复杂度
目录 文章目录 前言 一.算法时间复杂度是什么? 二.推导大O阶的方法 二.四种典型的时间复杂度 1.常数阶--O(1) 2.线性阶--O(n) 3.对数阶--O(logn) 4.平方阶--O(n^2 ...
- 数据结构与算法——时间复杂度的粗略计算
1.什么是时间复杂度 首先我们来看一段代码: int cal(int n) {int sum = 0;int i = 1;int j = 1;for (; i <= n; ++i) {j = 1 ...
- 数据结构与算法-时间复杂度的级别-时间复杂度的算法
时间复杂度分级 时间复杂度的计算 >计算规则 >基本操作,时间复杂度为 1 >程序的流程控制 顺序,分支,循环 . 按照计算规则 最终去掉常量 用大O表示法最终结果为 O(n^2)
- 数据结构与算法-时间复杂度
时间评估程序的快慢可靠吗? >运算步骤 每台机器的执行时间各不相同 但是,基本运算数量,运算步骤,大体相同 步骤分析 >第一次 当a+b+c = 2000的时候 当求和条件变为 a+b+c ...
- 常见数据结构排序算法时间复杂度
- 数据结构与算法之解析之路
数据结构是计算机存储.组织数据的方式.数据结构是指相互之间存在一种或多种特定关系的数据元素的集合.通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率.数据结构往往同高效的检索算法和索引技术有 ...
最新文章
- 从Qcheck 1.3 不能在不同操作系统上运行问题(chro124、chro342)说开来------
- Scala模式匹配:条件守卫
- 初探Java设计模式1:创建型模式(工厂,单例等)
- Python正则表达式简单说明(菜鸟教程里面的说明)
- python窗口图形界面编程上传图片_python GUI编程(Tkinter) 创建子窗口及在窗口上用图片绘图实例...
- 安卓Java按钮编写加一减一_android studio 中点击button加1或者减1
- Scrum Meeting---Ten(2015-11-5)
- 第007讲 地图映射,线包字
- Jetson开发实战记录(二):Jetson Xavier NX版本区别以及烧录系统
- Phoenix创建Hbase二级索引
- 转载一份anjuta教程
- canal 记录 ROWDATA TRANSACTIONBEGIN
- QT3D场景的快速绘制
- SBUS转485增程方案,SBUS控制远程机器人方案
- 网络对时设备(NTP校时)如何守护安全日志
- 最简易的Cfree代码,cfree爱心代码。
- 通达信公式-接近均线
- centos8以后版本突然不能上网解决
- 【联合首发】2020年中国线上高增长消费市场白皮书-魔镜市场情报.pdf(附下载链接)
- C语言实现的超详细的冒泡排序(附有详细代码)
热门文章
- 2018-2019-1 20189210 《LInux内核原理与分析》第六周作业
- IIS 发布网站到外网
- Eclipse设置字体大小等!
- torch.cat同时连接多个tensor
- oracle11g sp 1503,Oracle11g操作ASM权限问题
- Opencv 学习笔记之——鼠标操作画出感兴趣区域
- 每天60秒读懂世界20211127
- 网页上符号显示成方框_如何在word、PPT、Excel以及PDF中添加带√的方框
- OpenGL编程指南5:学习绘制不同风格的曲线
- Qt修炼手册9_Ui名字空间及setupUi()原理解读