【问题标题】:Why are not the way parameters/arguments passed considered for the time complexity of an algorithm?为什么不考虑算法时间复杂度的参数/参数传递方式?
【发布时间】:2020-12-08 19:50:47
【问题描述】:

根据传递参数/参数的方式不同的语言是否会有不同的时间复杂度。那么为什么书籍测量时间复杂度的算法或程序中没有考虑或考虑到这一点? Mark Allen Weiss 的 CLRS 或 Data Structures and Algorithm Analysis 永远不会增加程序总运行时参数传递方式的时间复杂度?我是不是误会了什么?我知道 CLRS 是伪代码,但 Mark Allen Weiss 的算法分析显示了特定于 Java 的代码。

【问题讨论】:

  • 你能举一个例子说明时间复杂度会如何影响参数的传递方式吗?我不确定您所说的“通过方式”是什么意思。
  • Java 特定的代码没有渐近复杂度,因为例如Java 原始数据类型的大小是有限的。在推理复杂性时,我们可能会使用特定的编程语言进行说明,但我们始终会考虑抽象算法。

标签: algorithm time-complexity clrs


【解决方案1】:

如果我正确理解您的问题,您的问题如下:

一些编程语言(尤其是 C 和 C++)对按值传递(复制参数)和按指针或按引用传递(其中不复制参数)进行区分。选择如何将参数传递给函数会改变函数完成的工作量,因为如果按值传递,则需要复制参数。但是,CLRS 根本不讨论这个问题,Java 书籍也没有解决这个问题,因为它们是用 Java 编写的。这很重要,我们应该关心它吗?

您是正确的,参数传递的模式绝对会影响函数运行的时间。例如,这是一个用 C++ 编写的不太好的二分搜索实现:

/* Bad code, please don't use this. */
bool binarySearchFor(std::vector<int> values, int key) {
    std::size_t lhs = 0, rhs = values.size();

    while (lhs < rhs) {
        std::size_t mid = lhs + (rhs - lhs) / 2;
        if (values[mid] == key) return true;
        else if (values[mid] > key) lhs = mid;
        else rhs = mid + 1;
    }

    return false;
}

此函数内部的逻辑将在 O(log n) 时间内运行,其中 n 是 std::vector 中的元素数。但是,由于向量是按值传递的,因此简单地复制该向量将花费时间 Θ(n),使实际算法的运行时间相形见绌,并使整个事情在时间 Θ(n) 中运行。另一方面,更改函数以便我们通过 const 引用接受 values 会将运行时间降低到 O(log n)。

那么,为什么 CLRS - 或大多数其他算法书籍 - 不谈论这个?原因之一是按值传递并不是所有编程语言的特性(或者至少与 C++ 不同)。在 Python、JavaScript、Java、LISP 等中,技术上参数是按值传递的,但由于这些参数是引用,因此传递参数的成本总是 O(1)。因此,不在算法书籍中讨论这一点的一个原因是,这些书籍讨论的是遵循的高级概念算法,而不是支持它们的实际代码,因此没有考虑到所有编程语言中的所有细节。希望您,衣冠楚楚的读者,将他们的算法翻译成您选择的编程语言,并适当地使用可用的语言功能。

【讨论】:

    猜你喜欢
    • 2017-05-21
    • 2018-06-21
    • 1970-01-01
    • 2014-01-12
    • 1970-01-01
    • 2017-10-30
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多