赖同学


  • 首页

  • 标签

  • 分类

  • 归档

  • 站点地图

  • 留言

  • 搜索

为什么我要放弃javaScript数据结构与算法(第十二章)—— 算法复杂度

发表于 November 12, 2018|分类于 javaScript相关|阅读次数: –
字数统计: 1435|阅读时间: 8 min

花了一个星期,终于看到这本书的最后一章了。这章将要学习著名的大 O 表示法。

第十二章 算法复杂度

大 O 表示法

它用于描述算法的性能和复杂程度

分析算法时,时常遇到以下几类函数

| 符号 | 名称 | | ------------------ '| ------------ |' | O(1) | 常数的 | | O(log(n)) | 对数的 | | O((log(n)c)) | 对数多项式的 | | O(n) | 线性的 | | O(n2) | 二次的 | | O(nc) | 多项式的 | | O(cn) | 指数的 |

理解大 O 表示法

如何衡量算法的效率?通常是用资源,例如 CPU(时间)占用、内存占用、硬盘占用和网络占用。当讨论大 O 表示法时,一般考虑的是 CPU(时间)占用。

让我们试着用一些例子来理解大 O 表示法的规则

O(1)

function increment(num) {
  return ++num;
}

假设运行 increment(1)函数,执行时间等于 X。如果再用不同的参数运行一次 increment 函数,执行事件依然是 X。和参数无关,increment 函数的性能都一样。因此,我们说上述函数的复杂程度是O(1)(常数)

O(n)

function sequentialSearch(array, item) {
  for (var i = 0; i < array.length; i++) {
    if (item === array[i]) {
      return i;
    }
  }
  return -1;
}

如果将含有 10 个元素的数组([1, ..., 10])传递给该函数,例如搜索 1 这个元素,那么第一次判断时就能找到想要搜索的元素。在这里我们假设每执行一次(item === array[i])开销为 1.

现在,假如要搜索元素 11. 那么函数会执行 10 次(遍历数组中所有的值,并且找不到要搜索的元素,因此结果返回-1),那么开销就是 10。以此类推,sequentialSearch 函数执行的总开销取决了数组元素的个数(数组的大小)。可以得到 sequentialSearch 函数的时间复杂度为O(n),n 是(输入)数组的大小。

回到之前的例子,修改一下算法的实现。

function sequentialSearch(array, item) {
  var cost = 0;
  for (var i = 0; i < array.length; i++) {
    if (item === array[i]) {
      return i;
    }
  }
  console.log(
    "cost for sequentialSearch with inpy size " + array.length + "is" + cost
  );
  return -1;
}

用不同大小输入数组执行以上算法,可以看到不同的输出。

O(n2)

用冒泡排序做例子

function swap(array, index1, index2) {
  var aux = array[index1];
  array[index1] = array[index2];
  array[index2] = aux;
}

function bubbleSort(array) {
  var length = array.length,
    cost = 0;
  for (var i = 0; i < length; i++) {
    cost++;
    for (var j = 0; j < length; j++) {
      cost++;
      if (array[j] > array[j + 1]) {
        swap(array, j, j + 1);
      }
    }
  }
  console.log("cost for bubbleSort with input size" + length + "is" + cost);
}

如果用大小为 10 的数组执行上面的函数,开销是 100(102)。

时间复杂度O(n)的代码只有一层循环,而O(n2)有两层循环。如果算法有三层遍历数组的嵌套循环,它的时间复杂度很有可能是O(n3)

时间复杂度比较

下面比较了前述各个大 O 符号表示的时间复杂度

数据结构

下表是常用数据结构的时间复杂度

| 数据结构 | 一般情况 | | | 最差情况 | | | | ------------ '| ----------- | ----------- | ----------- | ----------- | ----------- | ----------- |' | | 插入 | 删除 | 搜索 | 插入 | 删除 | 搜索 | | 数组-栈-队列 | O(1) | O(1) | O(n) | O(1) | O(1) | O(n) | | 链表 | O(1) | O(1) | O(n) | O(1) | O(1) | O(n) | | 双向链表 | O(1) | O(1) | O(n) | O(1) | O(1) | O(n) | | 散列表 | O(1) | O(1) | O(1) | O(n) | O(n) | O(n) | | 二分搜索树 | O(log(n)) | O(log(n)) | O(log(n)) | O(n) | O(n) | O(n) | | AVL 树 | O(log(n)) | O(log(n)) | O(log(n)) | O(log(n)) | O(log(n)) | O(log(n)) |

图

下表是图的时间复杂度

| 节点-边的管理方式 | 存储空间 | 增加顶点 | 增加边 | 删除顶点 | 删除边 | 轮询 | | ----------------- '| ------------------ | ------------------ | ------ | ------------------ | ------ | ------ |' | 邻接表 | O(V+E) | O(1) | O(1) | O(V+E) | O(E) | O(V) | | 邻接矩阵 | O(V2) | O(V2) | O(1) | O(V2) | O(1) | O(1) |

排序算法

下表是排序算法的时间复杂度

| 算法(用于数组) | 最好情况 | 一般情况 | 最差情况 | | ---------------- '| ------------------ | ------------------ | ------------------ |' | 冒泡排序 | O(n) | O(n2) | O(n2) | | 选择排序 | O(n2) | O(n2) | O(n2) | | 插入排序 | O(n) | O(n2) | O(n2) | | 归并排序 | O(nlog(n)) | O(nlog(n)) | O(nlog(n)) | | 快速排序 | O(nlog(n)) | O(nlog(n)) | O(n2) | | 堆排序 | O(nlog(n)) | O(nlog(n)) | O(nlog(n)) | | 桶排序 | O(n+k) | O(n+k) | O(n2) | | 基数排序 | O(nk) | O(nk) | O(nk) |

搜索算法

下表是搜索算法的时间复杂度

| 算法 | 数据结构 | 最差情况 | | ------------------- '| ---------------------- | ----------- |' | 顺序搜索 | 数组 | O(n) | | 二分搜索 | 已排序的数组 | O(log(n)) | | 深度优先搜索(DPS) | 顶点数为 V,边数为 E 的图 | O(V+E) | | 广度优先搜索(BFS) | 顶点数为 V,边数为 E 的图 | O(V+E) |

NP 完全理论概述

一般来说,如果一个算法的复杂度为 O(nk),其中 k 是常数,我们就认为这个算法是最高效的,这就是多项式算法。

对于给定的问题,如果存在多项式算法,则计为 P(polynomial, 多项式)。

还有一类 NP(nondeterministic polynomial, 非确定性多项式)算法。如果一个问题可以在多项式时间内验证是否正确,则计为 NP。

如果一个问题存在多项式算法,自然可以在多项式时间内验证其解。因此,所有 P 都是 NP。然而,P = NP 是否成立,仍然不得而知。

小结

我们学习了大 O 表示法,已经如何运算它计算算法的复杂度。也粗略介绍了 NP 的一些理论。

书籍链接: 学习 JavaScript 数据结构与算法

javaScript数据结构与算法
前端必备的Nginx学习
为什么我要放弃javaScript数据结构与算法(第十一章)—— 算法模式
  • 文章目录
  • 站点概览
  1. 1.第十二章 算法复杂度
    1. 1.大 O 表示法
    2. 2.理解大 O 表示法
    3. 3.<em>O(1)</em>
    4. 4.<em>O(n)</em>
    5. 5.<em>O(n2)</em>
    6. 6.时间复杂度比较
    7. 7.NP 完全理论概述
    8. 8.小结
© 2018 — 2023赖彬鸿
1.6k
载入天数...载入时分秒...
0%