数据结构与算法 -- 时间复杂度
来源:互联网 发布:直线制职能制矩阵制 编辑:程序博客网 时间:2024/04/30 22:11
数据结构与算法看完了,回过头来在看时间复杂度,对它们的效率做个比较吧。
一、时间复杂度介绍
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。
四、时间复杂度和实际运行时间
- 数据结构与算法 -- 时间复杂度
- 数据结构之算法与算法时间复杂度
- 算法与数据结构 其一 算法时间复杂度
- 数据结构与算法-如何计算时间复杂度
- 常见的数据结构与算法时间复杂度
- 数据结构-算法-时间复杂度
- 数据结构与算法____时间复杂度和空间复杂度
- 数据结构与算法笔记之--时间复杂度和空间复杂度
- 数据结构与算法,时间复杂度和空间复杂度
- 数据结构与时间复杂度
- 数据结构-算法的时间复杂度
- 数据结构-算法-时间复杂度计算
- 数据结构 算法时间、空间复杂度
- 数据结构-递归算法-时间复杂度
- 数据结构-算法-时间复杂度计算
- 【数据结构】算法时间复杂度分析
- 数据结构之算法时间复杂度
- 数据结构之算法时间复杂度
- 编写手机信息页面流程
- CPU飙高调试
- Java基础知识(四)
- C++11系列-区间迭代
- 关于网页页头的“设为首页”和“联系我们”位置互换问题
- 数据结构与算法 -- 时间复杂度
- Unit 4-Lecture 1:Intro to Discrete Probability
- xml和json格式的比较
- C++11系列-常量表达式
- Ubuntu下,清屏等常用命令
- 堆栈、堆、方法区介绍
- 变革OTT产业,苏宁PPTV打造家庭互联网第一开放平台
- Android keyboardView字体样式修改
- Java基础