计算机科学

为学生,研究人员和计算机科学从业者提供的问答

11
为什么实践中quicksort比其他排序算法更好?
在标准的算法当然我们被教导快速排序是平均和ø (Ñ 2)在最坏的情况下。同时,还研究了其他排序算法,它们在最坏的情况下为O (n log n )(例如mergesort和heapsort),在最坏的情况下甚至是线性时间(例如bubbleort),但还有一些额外的内存需求。Ø (ñ 日志n )O(nlog⁡n)O(n \log n)Ø (ñ2)O(n2)O(n^2)Ø (ñ 日志n )O(nlog⁡n)O(n \log n) 快速浏览一下更多的运行时间后,自然可以说quicksort 应该不如其他高效。 另外,考虑到学生在基础编程课程中学习到,递归通常并不太好,因为它会占用过多的内存,等等。因此(尽管这不是一个真正的论点),但这样的想法是快速排序可能不是真的很好,因为它是一种递归算法。 那么,为什么在实践中快速排序优于其他排序算法?它与真实数据的结构有关吗?它与计算机中内存的工作方式有关吗?我知道有些记忆要比其他记忆快,但是我不知道这是否是这种违反直觉的表现的真正原因(与理论估计相比)。 更新1:一个规范的答案是说,平均情况的所涉及的常数小于其他O (n log n )算法所涉及的常数。但是,我还没有看到用正确的计算代替仅凭直觉的想法的适当理由。Ø (ñ 日志n )O(nlog⁡n)O(n\log n)Ø (ñ 日志n )O(nlog⁡n)O(n\log n) 无论如何,正如某些答案所暗示的那样,似乎真正的区别发生在内存级别,在这种级别上,实现利用了计算机的内部结构,例如使用高速缓存比RAM快。讨论已经是有趣的,但我还是喜欢看关于内存管理更详细,因为它似乎是在回答有什么关系。 更新2:有几个网页提供了排序算法的比较,其中有些比其他网页更出色(最著名的是sorting-algorithms.com)。除了提供不错的视觉辅助外,这种方法也无法回答我的问题。


29
为什么写下数学证明比编写计算机代码更能抵御故障?
我注意到,我发现写下数学证明而不犯任何错误要比写下没有错误的计算机程序容易得多。 似乎这不仅仅是我的经验。大多数人在编程时总是会犯软件错误,而且他们让编译器始终告诉他们错误是什么。我从未听说过有人一口气编写大型计算机程序,但一无所错,并且完全相信它不会出错。(实际上,几乎没有任何程序是没有错误的,甚至包括许多高度调试的程序)。 然而,人们可以写整篇论文或数学证明书,而无需任何编译器向他们反馈自己犯错的反馈,有时甚至无法从他人那里得到反馈。 让我清楚一点。这并不是说人们不会在数学证明中犯错误,但是对于即使是有经验的数学家来说,错误通常也不是问题,并且可以在没有诸如编译器指向您的编译器的“外部oracle”帮助下解决。错误。 实际上,如果不是这种情况,那么在我看来数学几乎是不可能的。 因此,这引发了我一个问题:编写无故障的数学证明和编写无故障的计算机代码有什么不同,从而使前者比后者更易于处理? 可以说,事实是人们拥有编译器的“外部预言”,使他们指出自己的错误,这使程序员变得懒惰,从而阻止他们执行严格编写代码所必需的工作。这种观点意味着,如果他们没有编译器,他们将能够像数学家一样完美无缺。 您可能会发现这很有说服力,但是基于我的编程经验和写下数学证明,在我看来,这并不是真正的解释。两项工作似乎在根本上有所不同。 我最初的想法是,可能会有区别,对于数学家来说,正确的证明仅要求每个逻辑步骤都是正确的。如果每个步骤都正确,则整个证明都是正确的。另一方面,要使程序无缺陷,不仅每一行代码都必须正确,而且它与程序中每行其他代码的关系也必须正常工作。 换句话说,如果步骤中证明是正确的,那么在制作工序中的错误不会弄乱一步如初。但是,如果正确记录了一行代码,则在行犯错误将影响行的工作,因此,每当编写行,都必须考虑其与所有其他行的关系。我们可以使用封装以及所有类似的东西来限制这种情况,但是不能完全删除它。XXXÿYYX Y X XXXXXXXÿYYXXXXXX 这意味着检查数学证明中的错误的过程在证明步骤的数量上基本上是线性的,但是检查计算机代码中的错误的过程在代码行数上基本上是指数的。 你怎么看? 注意:该问题有大量答案,可探讨各种事实和观点。在回答之前,请阅读所有内容并仅在有新添加内容时回答。多余的答案或不支持事实的观点的答案可能会被删除。


3
算法分析的魔力背后是否有一个系统?
关于如何分析算法的运行时间存在很多问题(例如,参见运行时分析和算法分析)。许多都是类似的,例如那些要求对嵌套循环或分而治之算法进行成本分析的方法,但是大多数答案似乎都是量身定制的。 另一方面,另一个通用问题的答案通过一些示例解释了更大的图景(尤其是关于渐近分析),但没有说明如何弄脏您的手。 有没有一种结构化的,通用的方法来分析算法的成本?成本可能是运行时间(时间复杂度),也可能是某种其他成本度量,例如执行的比较次数,空间复杂度或其他。 这应该成为一个参考问题,可以用来指导初学者。因此其范围比平常大。请小心给出一般的,有说服力的答案,至少由一个示例说明了这一点,但仍然涵盖了许多情况。谢谢!

12
为什么停运问题如此重要?
我不明白为什么经常使用“ 暂停问题”来消除确定程序是否暂停的可能性。维基百科[article] [1]正确地解释了具有有限内存的确定性机器将停止或重复先前的状态。您可以使用算法来检测链表是否循环以实现具有O(1)空间复杂度的停止功能。 在我看来,“停顿问题”证明无非就是所谓的“悖论”,它是自欺欺人的自相矛盾(至少是周期性的),与说谎者的悖论一样。它得出的唯一结论是,停止功能容易受到此类格式错误的问题的影响。 因此,除矛盾的程序外,停止功能是可以确定的。那么,为什么我们认为它是相反的证据呢? 4年后:当我写这篇文章时,我只是看了这段视频。程序员得到了一些程序,必须确定哪些程序终止,然后视频继续解释为什么这是不可能的。我很沮丧,因为我知道给定一些任意程序,主角可能会证明它们是否终止。普遍性的概念以某种方式丢失了。说“无法证明某些程序终止”与“不能证明程序终止”之间是有区别的。正式证明了许多算法可以做到这一点。根据我在网上找到的每一个参考文献,未能做出这种区分是我如何找到该问题的标题。因此,我非常感谢您的回答 将停止功能重新定义为三元而不是布尔值。

3
如何确定
我们进行了以下练习。 让 F(n )= { 100ñ 以π 的十进制表示形式出现 其他f(n)={10n occurs in the decimal representation of π0else\qquad \displaystyle f(n) = \begin{cases} 1 & 0^n \text{ occurs in the decimal representation of } \pi \\ 0 & \text{else}\end{cases} 证明是可计算的。Fff 这怎么可能?据我所知,我们不知道是否包含数字的每个序列(或哪个序列),并且算法当然不能确定某个序列没有发生。因此我认为f是不可计算的,因为根本的问题只能是半确定的。ππ\piFff

12
为什么会有那么多编程语言?
我精通C / C ++,并且可以绕过各种脚本语言(awk / sed / perl)。我开始更多地使用python,因为它结合了C ++的一些漂亮方面和awk / sed / perl的脚本功能。 但是为什么会有这么多不同的编程语言呢?我猜所有这些语言都可以做同样的事情,那么为什么不只坚持一种语言并将其用于计算机编程呢?特别是,作为我的计算机程序员,我是否应该知道某种功能语言? 相关阅读: 为什么新的编程语言成功-或失败? 还需要用编程语言进行研究吗?

14
为什么我可以看一下图并立即找到与另一点最接近的点,但是我花了O(n)时间来编程?
让我澄清一下: 给定一个散点图,该散点图具有给定数量的点n,如果我想在思维上找到最接近点的任何点,我可以立即忽略图中的大多数点,将选择范围缩小到附近的一些小而恒定的点。 但是,在编程中,给定一组点n,以便找到与任何一个点最接近的点,它需要检查每隔一点,即时间。O(n )O(n){\cal O}(n) 我猜测图形的视觉效果可能相当于我无法理解的某些数据结构;因为通过编程,通过将点转换为更结构化的方法(例如四叉树),可以在时间中找到中与个点最接近的点,或者将时间。Ñ ķ ⋅ 日志(Ñ )ø(登录Ñ )ķkkñnnk · 对数(n )k⋅log⁡(n)k\cdot\log(n)O(对数n )O(log⁡n){\cal O}(\log n) 但是,仍然没有已知的摊分算法(我可以找到)用于数据重组后的测点。O(1 )O(1){\cal O}(1) 那么,为什么仅凭视觉检查就可以做到这一点?


4
如何将有限自动机转换为正则表达式?
使用标准算法(例如汤普森算法),可以很容易地将正则表达式转换为接受相同语言的(最小)NFA 。但是,另一个方向似乎更乏味,有时结果表达式是混乱的。 有什么算法可以将NFA转换为等效的正则表达式?时间复杂度或结果大小是否有优势? 这应该是一个参考问题。请包括您的方法的一般说明以及不重要​​的示例。


13
如何愚弄“尝试一些测试用例”启发式算法:看起来正确但实际上不正确的算法
为了尝试测试某个问题的算法是否正确,通常的出发点是尝试在多个简单的测试案例上手动运行该算法-在一些示例问题实例(包括一些简单的“拐角案例”)上进行尝试”。这是一种很好的启发式方法:这是一种快速清除算法中许多错误尝试并了解为什么该算法无效的好方法。 但是,在学习算法时,有些学生很想停在这里:如果他们的算法在一些示例上都能正常工作,包括他们认为可以尝试的所有极端情况,那么他们得出的结论是算法必须正确。总是有一个学生问:“如果我可以在几个测试用例上尝试一下,为什么我需要证明我的算法正确?” 那么,如何欺骗“尝试一堆测试用例”启发式方法?我正在寻找一些很好的例子来表明这种启发式方法是不够的。换句话说,我正在寻找一个或多个算法的示例,这些示例从表面上看可能是正确的,并且在任何人都可能想出的所有小输入上输出正确答案,但是该算法实际上在哪里不起作用。也许该算法恰好在所有小输入上都能正常工作,仅对大输入失败,或者仅对具有异常模式的输入失败。 具体来说,我在寻找: 一种算法。该缺陷必须在算法级别上。我不是在寻找实现错误。(例如,该示例至少应与语言无关,并且该缺陷应与算法问题有关,而不是与软件工程或实现问题有关。) 有人可能会提出的一种算法。伪代码应该看起来至少看起来是正确的(例如,混淆或明显可疑的代码不是一个好例子)。如果这是某些学生在尝试解决作业或考试问题时真正想到的一种算法,则可加分。 通过概率较高的合理手动测试策略的算法。手动尝试一些小型测试用例的人应该不太可能发现该缺陷。例如,“手动模拟十二个小型测试用例的QuickCheck”应该不太可能揭示该算法不正确。 优选地,确定性算法。我已经看到许多学生认为“手动尝试一些测试用例”是检查确定性算法是否正确的合理方法,但是我怀疑大多数学生不会认为尝试几个测试用例是验证概率的好方法算法。对于概率算法,通常没有办法判断任何特定输出是否正确。而且您手头不足以对输出分布进行任何有用的统计检验。因此,我宁愿专注于确定性算法,因为它们更清楚地了解了学生的误解。 我想教导证明算法正确的重要性,并且希望使用一些这样的示例来帮助激发正确性的证明。我希望那些相对简单并且可以被大学生使用的例子;需要重型机械或大量数学/算法背景的示例不太有用。另外,我也不想使用“非自然”的算法;虽然构造一些怪异的人工算法来欺骗启发式方法可能很容易,但是如果看起来很不自然,或者构造了明显的后门只是为了欺骗这种启发式方法,那么它可能不会使学生信服。有什么好的例子吗?


5
如何不解决P = NP?
有很多尝试证明或,并且自然地,许多人考虑这个问题,并提出了证明这两个方向的想法。P ≠ N PP = N PP=NP\mathsf{P} = \mathsf{NP} P ≠ N PP≠NP\mathsf{P} \neq \mathsf{NP} 我知道,有些方法已被证明行不通,而且可能还有更多失败的历史。似乎也存在许多无法克服的证明障碍。 我们要避免调查死胡同,那是什么?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.