排序研究前戏_计算复杂性

2024-08-22 23:32

本文主要是介绍排序研究前戏_计算复杂性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

计算复杂性理论(Computational complexity theory)是理论计算机科学和数学的一个分支,它致力于将可计算问题根据它们本身的复杂性分类,以及将这些类别联系起来。一个可计算问题被认为是一个原则上可以用计算机解决的问题,亦即这个问题可以用一系列机械的数学步骤解决,例如算法。

如果一个问题的求解需要相当多的资源(无论用什么算法),则被认为是难解的。计算复杂性理论通过引入数学计算模型来研究这些问题以及定量计算解决问题所需的资源(时间和空间),从而将资源的确定方法正式化了。其他复杂性测度同样被运用,比如通信量(应用于通信复杂性),电路中门的数量(应用于电路复杂性)以及中央处理器的数量(应用于并行计算)。计算复杂性理论的一个作用就是确定一个能或不能被计算机求解的问题的所具有的实际限制。

在理论计算机科学领域,与此相关的概念有算法分析和可计算性理论。两者之间一个关键的区别是前者致力于分析用一个确定的算法来求解一个问题所需的资源量,而后者则是在更广泛意义上研究用所有可能的算法来解决相同问题。更精确地说,它尝试将问题分成能或不能在现有的适当受限的资源条件下解决这两类。相应地,在现有资源条件下的限制正是区分计算复杂性理论和可计算性理论的一个重要指标:后者关心的是何种问题原则上可以用算法解决。


判定性问题和可计算性

我们考虑对一个算法问题,什么样的回答是我们所需要的。比如搜索问题:给定数组A,和一个数s,我们要问s在不在A中(判定性问题,decision problem)。而进一步的,s如果在A中的话,s的位置是什么(搜索型问题,search problem)。再比如完美匹配问题(perfect matching):给定一个二分图G=(V,E),我们问是不是存在边集E,使得二分图中每个结点恰好属于该边集的一条边(判定型问题)。而进一步的,E存在的话,E具体是什么(搜索型问题)。

自然的,我们会发现对于一般的算法问题A,我们都可以这样来问:首先,解是不是存在的?其次,如果解存在,这个解具体是什么?这就是A的判定型问题和A的搜索型问题(又称函数型问题)区分来源的直观解释。对判定型问题的回答只需是“是”或“否”,而对搜索型问题,需要返回解的具体形式或者“解不存在”。所以一个对A的搜索型问题的算法自然的也是对A的判定型问题的算法。反之,给定了一个A的判定型问题的算法,是否存在A的搜索型问题的算法,在可计算性理论和计算复杂性理论中有着不同的回答,这也是理解计算复杂性理论与它的前身可计算性理论不同的一个基本的观察。

在可计算性理论中,可以说明,判定型问题和搜索型问题在可计算性的意义下是等价的(见Decision problem)。而在计算复杂性中,Khuller和Vazirani在1990年代证明了在P≠NP的假设下,平面图4-着色问题的判定型问题是在P中的,而寻找其字典序第一的着色是NP难的。[1]

所以在可计算性理论中,只关注判定型问题是合理的。在计算复杂性理论中,虽然一些基本的复杂性类(如P,NP和PSPACE),以及一些基本的问题(P和NP关系问题等)是用判定型问题来定义的,但函数型问题复杂性类也被定义(如FP,FNP等),而且一些特别的函数型问题复杂性类,如TFNP,也正在逐渐受到关注。

算法分析

上面提到计算复杂性理论的研究对象是执行一项计算任务所用的资源,特别的,时间和空间是最重要的两项资源。

我们用时间作例子来讨论算法分析的一些基础知识。如果将输入的长度(设为n)作为变量,而我们关注的是算法运行时间与n的函数关系T(n)。因为一个算法在不同的计算模型上实现时T(n)可能会有常数因子的差别(参见可计算性理论),我们使用大O表达式来表示T(n),这使得我们可以忽略在不同计算模型上实现的常数因子。

以搜索这个计算任务为例。在搜索问题中,给定了一个具体的数s,和长度为n的数组A(数组中数的位置用1到n作标记),任务是当s在A中时,找到s的位置,而s不在A中时,需要报告"未找到"。这时输入的长度即为n+1。下面的过程即是一个最简单的算法:我们依次扫过A中的每个数,并与s进行比较,如果相等即返回当前的位置,如果扫遍所有的数而算法仍未停止,则返回"未找到"。

如果我们假设s在A中每个位置的机率都相同,那么算法在找到s的条件下需要1/n (1+2+...+n)=n(n+1)/2n=(n+1)/2的时间。如果s不在A中,那么需要(n+1)的时间。由大O表达式的知识我们知道算法所需的时间即为O(n)。

而如果我们进一步假设A是已排序的,那么我们有二分查找算法,使得算法的运行时间是O(logn)。可以看出执行一项计算任务,不同的算法在运行时间上是有很大差异的。


这篇关于排序研究前戏_计算复杂性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1097709

相关文章

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

Python中lambda排序的六种方法

《Python中lambda排序的六种方法》本文主要介绍了Python中使用lambda函数进行排序的六种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1.对单个变量进行排序2. 对多个变量进行排序3. 降序排列4. 单独降序1.对单个变量进行排序

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c