数据结构

数据结构,第1张

何谓数据结构

数据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。数据结构是数据存在的形式。 数据结构是信息的一种组织方式,其目的是为了提高算法的效率,它通常与一组算法的集合相对应,通过这组算法集合可以对数据结构中的数据进行某种操作。

数据结构主要研究什么?

数据结构作为一门学科主要研究数据的各种逻辑结构和存储结构,以及对数据的各种操作。因此,主要有三个方面的内容:数据的逻辑结构;数据的物理存储结构;对数据的操作(或算法)。通常,算法的

设计取决于数据的逻辑结构,算法的实现取决于数据的物理存储结构。

什么是数据结构?什么是逻辑结构和物理结构?

数据是指由有限的符号(比如,"0"和"1",具有其自己的结构、操作、和相应的语义)组成的元素的集合。结构是元素之间的关系的集合。通常来说,一个数据结构DS 可以表示为一个二元组:

DS=(D,S), //ie, data-structure=(data-part,logic-structure-part) 这里D是数据元素的集合(或者是“结点”,可能还含有“数据项”或“数据域”),S是定义在D(或其他集合)上的关系的集合,S = { R | R : D×D×},称之为元素的逻辑结构。 逻辑结构有四种基本类型:集合结构、线性结构、树状结构和网络结构。表和树是最常用的两种高效数据结构,许多高效的算法可以用这两种数据结构来设计实现。表是线性结构的(全序关系),树(偏序或层次关系)和图(局部有序(weak/local orders))是非线性结构。

数据结构的物理结构是指逻辑结构的存储镜像(image)。数据结构 DS 的物理结构 P对应于从 DS 的数据元素到存储区M(维护着逻辑结构S)的一个映射:

(PD,S) -- > M 存储器模型:一个存储器 M 是一系列固定大小的存储单元,每个单元 U 有一个唯一的地址 A(U),该地址被连续地编码。每个单元 U 有一个唯一的后继单元 U'=succ(U)。 P 的四种基本映射模型:顺序(sequential)、链接(linked)、索引(indexed)和散列(hashing)映射。

因此,我们至少可以得到4×4种可能的物理数据结构:

sequential (sets)

linked lists

indexed trees

hash graphs

(并不是所有的可能组合都合理)

数据结构DS上的操作:所有的定义在DS上的操作在改变数据元素(节点)或节点的域时必须保持DS的逻辑和物理结构。

DS上的基本操作:任何其他对DS的高级操作都可以用这些基本操作来实现。最好将DS和他的所有基本操作看作一个整体——称之为模块。我们可以进一步将该模块抽象为数据类型(其中DS的存储结构被表示为私有成员,基本操作被表示为公共方法),称之为ADT。作为ADT,堆栈和队列都是一种特殊的表,他们拥有表的操作的子集。 对于DATs的高级操作可以被设计为(不封装的)算法,利用基本操作对DS进行处理。

好的和坏的DS:如果一个DS可以通过某种“线性规则”被转化为线性的DS(例如线性表),则称它为好的DS。好的DS通常对应于好的(高效的)算法。这是由计算机的计算能力决定的,因为计算机本质上只能存取逻辑连续的内存单元,因此如何没有线性化的结构逻辑上是不可计算的。比如对一个图进行操作,要访问图的所有结点,则必须按照某种顺序来依次访问所有节点(要形成一个偏序),必须通过某种方式将图固有的非线性结构转化为线性结构才能对图进行操作。

树是好的DS——它有非常简单而高效的线性化规则,因此可以利用树设计出许多非常高效的算法。树的实现和使用都很简单,但可以解决大量特殊的复杂问题,因此树是实际编程中最重要和最有用的一种数据结构。树的结构本质上有递归的性质——每一个叶节点可以被一棵子树所替代,反之亦然。实际上,每一种递归的结构都可以被转化为(或等价于)树形结构。

从机器语言到高级语言的抽象

我们知道,算法被定义为一个运算序列。这个运算序列中的所有运算定义在一类特定的数据模型上,并以解决一类特定问题为目标。这个运算序列应该具备下列四个特征。 有限性,即序列的项数有限,且每一运算项都可在有限的时间内完成;确定性,即序列的每一项运算都有明确的定义,无二义性;可以没有输入运算项,但一定要有输出运算项;可行性,即对于任意给定的合法的输入都能得到相应的正确的输出。这些特征可以用来判别一个确定的运算序列是否称得上是一个算法。 但是,我们现在的问题不是要判别一个确定的运算序列是否称得上是一个算法,而是要对一个己经称得上是算法的运算序列,回顾我们曾经如何用程序设计语言去表达它。

算法的程序表达,归根到底是算法要素的程序表达,因为一旦算法的每一项要素都用程序清楚地表达,整个算法的程序表达也就不成问题。

作为运算序列的算法,有三个要素。 作为运算序列中各种运算的运算对象和运算结果的数据;运算序列中的各种运算;运算序列中的控制转移。这三种要素依序分别简称为数据、运算和控制。 由于算法层出不穷,变化万千,其中的运算所作用的对象数据和所得到的结果数据名目繁多,不胜枚举。最简单最基本的有布尔值数据、字符数据、整数和实数数据等;稍复杂的有向量、矩阵、记录等数据;更复杂的有集合、树和图,还有声音、图形、图像等数据。 同样由于算法层出不穷,变化万千,其中运算的种类五花八门、多姿多彩。最基本最初等的有赋值运算、算术运算、逻辑运算和关系运算等;稍复杂的有算术表达式和逻辑表达式等;更复杂的有函数值计算、向量运算、矩阵运算、集合运算,以及表、栈、队列、树和图上的运算等:此外,还可能有以上列举的运算的复合和嵌套。 关于控制转移,相对单纯。在串行计算中,它只有顺序、分支、循环、递归和无条件转移等几种。

我们来回顾一下,自从计算机问世以来,算法的上述三要素的程序表达,经历过一个怎样的过程。

最早的程序设计语言是机器语言,即具体的计算机上的一个指令集。当时,要在计算机上运行的所有算法都必须直接用机器语言来表达,计算机才能接受。算法的运算序列包括运算对象和运算结果都必须转换为指令序列。其中的每一条指令都以编码(指令码和地址码)的形式出现。与算法语言表达的算法,相差十万八千里。对于没受过程序设计专门训练的人来说,一份程序恰似一份"天书",让人看了不知所云,可读性

极差。

用机器语言表达算法的运算、数据和控制十分繁杂琐碎,因为机器语言所提供的指令太初等、原始。机器语言只接受算术运算、按位逻辑运算和数的大小比较运算等。对于稍复杂的运算,都必须一一分解,直到到达最初等的运算才能用相应的指令替代之。机器语言能直接表达的数据只有最原始的位、字节、和字三种。算法中即使是最简单的数据如布尔值、字符、整数、和实数,也必须一一地映射到位、字节和字

中,还得一一分配它们的存储单元。对于算法中有结构的数据的表达则要麻烦得多。机器语言所提供的控制转移指令也只有无条件转移、条件转移、进入子程序和从子程序返回等最基本的几种。用它们来构造循环、形成分支、调用函数和过程得事先做许多的准备,还得靠许多的技巧。 直接用机器语言表达算法有许多缺点。

大量繁杂琐碎的细节牵制着程序员,使他们不可能有更多的时间和精力去从事创造性的劳动,执行对他们来说更为重要的任务。如确保程序的正确性、高效性。程序员既要驾驭程序设计的全局又要深入每一个局部直到实现的细节,即使智力超群的程序员也常常会顾此失彼,屡出差错,因而所编出的程序可靠性差,且开发周期长。 由于用机器语言进行程序设计的思维和表达方式与人们的习惯大相径庭,只有经过

较长时间职业训练的程序员才能胜任,使得程序设计曲高和寡。因为它的书面形式全是"密"码,所以可读性差,不便于交流与合作。因为它严重地依赖于具体的计算机,所以可移植性差,重用性差。这些弊端造成当时的计算机应用未能迅速得到推广。

克服上述缺点的出路在于程序设计语言的抽象,让它尽可能地接近于算法语言。 为此,人们首先注意到的是可读性和可移植性,因为它们相对地容易通过抽象而得到改善。于是,很快就出现汇编语言。这种语言对机器语言的抽象,首先表现在将机器语言的每一条指令符号化:指令码代之以记忆符号,地址码代之以符号地址,使得其含义显现在符号上而不再隐藏在编码中,可让人望"文"生义。其次表现在这种语言摆脱了具体计算机的限制,可在不同指令集的计算机上运行,只要该计算机配上汇编语言的一个汇编程序。这无疑是机器语言朝算法语言靠拢迈出的一步。但是,它离算法语言还太远,以致程序员还不能从分解算法的数据、运算和控制到汇编才能直接表达的指令等繁杂琐碎的事务中解脱出来。 到了50年代中期,出现程序设计的高级语言如Fortran,Algol60,以及后来的PL/l, Pascal等,算法的程序表达才产生一次大的飞跃。

诚然,算法最终要表达为具体计算机上的机器语言才能在该计算机上运行,得到所需要的结果。但汇编语言的实践启发人们,表达成机器语言不必一步到位,可以分两步走或者可以筑桥过河。即先表达成一种中介语言,然后转成机器语言。汇编语言作为一种中介语言,并没有获得很大成功,原因是它离算法语

言还太远。这便指引人们去设计一种尽量接近算法语言的规范语言,即所谓的高级语言,让程序员可以用它方便地表达算法,然后借助于规范的高级语言到规范的机器语言的"翻译",最终将算法表达为机器语言。而且,由于高级语言和机器语言都具有规范性,这里的"翻译"完全可以机械化地由计算机来完成,就像汇编语言被翻译成机器语言一样,只要计算机配上一个编译程序。 上述两步,前一步由程序员去完成,后一步可以由编译程序去完成。在规定清楚它们各自该做什么之后,这两步是完全独立的。它们各自该如何做互不相干。前一步要做的只是用高级语言正确地表达给定的算法,产生一个高级语言程序;后一步要做的只是将第一步得到的高级语言程序翻译成机器语言程序。至于程序员如何用高级语言表达算法和编译程序如何将高级语言表达的算法翻译成机器语言表达的算法,显然毫不相干。

处理从算法语言最终表达成机器语言这一复杂过程的上述思想方法就是一种抽象。汇编语言和高级语言的出现都是这种抽象的范例。 与汇编语言相比,高级语言的巨大成功在于它在数据、运算和控制三方

面的表达中引入许多接近算法语言的概念和工具,大大地提高抽象地表达算法的能力。 在运算方面,高级语言如Pascal,除允许原封不动地运用算法语言的四则运算、逻辑运算、关系运算、算术表达式、逻辑表达式外,还引入强有力的函数与过程的工具,并让用户自定义。这一工具的重要性不仅在于它精简了重复的程序文本段,而且在于它反映出程序的两级抽象。

在函数与过程调用级,人们只关心它能做什么,不必关心它如何做。只是到函数与过程的定义时,人们才给出如何做的细节。用过高级语言的读者都知道,一旦函数与过程的名称、参数和功能被规定清楚,那么,在程序中调用它们便与在程序的头部说明它们完全分开。你可以修改甚至更换函数体与过程体,而不影响它们的被调用。如果把函数与过程名看成是运算名,把参数看成是运算的对象或运算的结果,那么

,函数与过程的调用和初等运算的引用没有两样。利用函数和过程以及它们的复合或嵌套可以很自然地表达算法语言中任何复杂的运算。

在数据方面,高级语言如Pascal引人了数据类型的概念,即把所有的数据加以分类。每一个数据(包括表达式)或每一个数据变量都属于其中确定的一类。称这一类数据为一个数据类型。 因此,数据类型是数据或数据变量类属的说明,它指示该数据或数据变量可能取的值的全体。对于无结构的数据,高级语言如Pascal,除提供标准的基本数据类型--布尔型、字符型、整型和实型外,还提供用户可自定义的枚举类、子界类型和指针类型。这些类型(除指针外),其使用方式都顺应人们在算法语言中使用的习惯。对于有结构的数据,高级语言如Pascal,提供了数组、记录、有限制的集合和文件等四种标准的结构数据类型。其中,数组是科学计算中的向量、矩阵的抽象;记录是商业和管理中的记录的抽象;有限制的集合是数学中足够小的集合的势集的抽象;文件是诸如磁盘等外存储数据的抽象。

人们可以利用所提供的基本数据类型(包括标准的和自定义的),按数组、记录、有限制的集合和文件的构造规则构造有结构的数据。 此外,还允许用户利用标准的结构数据类型,通过复合或嵌套构造更复杂更高层的结构数据。这使得高级语言中的数据类型呈明显的分层。 高级语言中数据类型的分层是没有穷尽的,因而用它们可以表达算法语言中任何复杂层次的数据。 在控制方面,高级语言如Pascal,提供了表达算法控制转移的六种方式。

(1)缺省的顺序控制";"。

(2)条件(分支)控制:"if表达式(为真)then S1 else S2;" 。

(3)选择(情况)控制:

"Case 表达式 of

值1: S1

值2: S2

值n: Sn

end"

(4)循环控制:

"while 表达式(为真) do S;" 或

"repeat S until 表达式(为真);" 或

"for变量名:=初值 to/downto 终值do S;"

(5)函数和过程的调用,包括递归函数和递归过程的调用。

(6)无条件转移goto。

这六种表达方式不仅覆盖了算法语言中所有控制表达的要求,而且不再像机器语言或汇编语言那样原始、那样繁琐、那样隐晦,而是如上面所看到的,与自然语言的表达相差无几。 程序设计语言从机器语言到高级语言的抽象,带来的主要好处是: 高级语言接近算法语言,易学、易掌握,一般工程技术人员只要几周时间的培训就可以胜任程序员的工作;高级语言为程序员提供了结构化程序设计的环境和工具,使得设计出来的程序可读性好,可维护性强,可靠性高;高级语言远离机器语言,与具体的计算机硬件关系不大,因而所写出来的程序可移植性好,重用率高; 由于把繁杂琐碎的事务交给了编译程序去做,所以自动化程度高,开发周期短,且程、序员得到解脱,可以集中时间和精力去从事对于他们来说更为重要的创造性劳动,以提高、程序的质量。

数据结构、数据类型和抽象数据类型

数据结构、数据类型和抽象数据类型,这三个术语在字面上既不同又相近,反映出它们在含义上既有区别又有联系。

数据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成,即一个数据由哪些成分数据构成,以什么方式构成,呈什么结构。数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,物理上的数据结构反映成分数据在计算机内的存储安排。数据结构是数据存在的形式。

数据是按照数据结构分类的,具有相同数据结构的数据属同一类。同一类数据的全体称为一个数据类型。在程序设计高级语言中,数据类型用来说明一个数据在数据分类中的归属。它是数据的一种属性。这个属性限定了该数据的变化范围。为了解题的需要,根据数据结构的种类,高级语言定义了一系列的数据类型。不同的高级语言所定义的数据类型不尽相同。Pascal语言所定义的数据类型的种类。

其中,简单数据类型对应于简单的数据结构;构造数据类型对应于复杂的数据结构;在复杂的数据结构里,允许成分数据本身具有复杂的数据结构,因而,构造数据类型允许复合嵌套;指针类型对应于数据结构中成分数据之间的关系,表面上属简单数据类型,实际上都指向复杂的成分数据即构造数据类型中的数据,因此这里没有把它划入简单数据类型,也没有划入构造数据类型,而单独划出一类。

数据结构反映数据内部的构成方式,它常常用一个结构图来描述:数据中的每一项成分数据被看作一个结点,并用方框或圆圈表示,成分数据之间的关系用相应的结点之间带箭号的连线表示。如果成分数据本身又有它自身的结构,则结构出现嵌套。这里嵌套还允许是递归的嵌套。

由于指针数据的引入,使构造各种复杂的数据结构成为可能。按数据结构中的成分数据之间的关系,数据结构有线性与非线性之分。在非线性数据结构中又有层次与网状之分。 由于数据类型是按照数据结构划分的,因此,一类数据结构对应着一种数据类型。数据类型按照该类型中的数据所呈现的结构也有线性与非线性之分,层次与网状之分。一个数据变量,在高级语言中的类型说明必须是读变量所具有的数据结构所对应的数据类型。最常用的数据结构是数组结构和记录结构。数组结构的特点是:

成分数据的个数固定,它们之间的逻辑关系由成分数据的序号(或叫数组的下标)来体现。这些成分数据按照序号的先后顺序一个挨一个地排列起来。每一个成分数据具有相同的结构(可以是简单结构,也可以是复杂结构),因而属于同一个数据类型(相应地是简单数据类型或构造数据类型)。这种同一的数据类型称为基类型。所有的成分数据被依序安排在一片连续的存储单元中。 概括起来,数组结构是一个线性的、均匀的、其成分数据可随机访问的结构。

由于这、种结构有这些良好的特性,所以最常被人们所采用。在高级语言中,与数组结构相对应的、数据类型是数组类型,即数组结构的数据变量必须说明为array [i] of T0 ,其中i是数组、结构的下标类型,而T0是数组结构的基类型。 记录结构是另一种常用的数据结构。它的特点是:与数组结构一样,成分数据的个数固定。但成分数据之间没有自然序,它们处于平等地位。每一个成分数据被称为一个域并赋予域名。不同的域有不同的域名。不同的域允许有不同的结构,因而允许属于不同的数据类型。与数组结构一样,它们可以随机访问,但访问的途径靠的是域名。在高级语言中记录结构对应的数据类型是记录类型。记录结构的数据的变量必须说明为记录类型。

抽象数据类型的含义在上一段已作了专门叙述。它可理解为数据类型的进一步抽象。即把数据类型和数据类型上的运算捆在一起,进行封装。引入抽象数据类型的目的是把数据类型的表示和数据类型上运算的实现与这些数据类型和运算在程序中的引用隔开,使它们相互独立。对于抽象数据类型的描述,除了必须描述它的数据结构外,还必须描述定义在它上面的运算(过程或函数)。抽象数据类型上定义的过程和函

数以该抽象数据类型的数据所应具有的数据结构为基础。

泛型设计和数据结构与算法

下面我想再说说关于泛型程序设计模型对于数据结构和算法方面的最新推动,泛型思想已经把数据结

构和算法方面的基本思想抽象到了一个前所未有的高度,现在有多种程序设计语言支持泛型设计,比如

ADA,C++,而且据说在JAVA的下一版本和C#中也将对泛型设计进行全面的支持。

先说说泛型设计的基本思想:泛型编程(generic programming,以下直接以GP称呼)是一种全新的程序设计思想,和OO,OB,PO这些为人所熟知的程序设计想法不同的是GP抽象度更高,基于GP设计的组件之间偶合度底,没有继承关系,所以其组件间的互交性和扩展性都非常高。我们都知道,任何算法都是作用在一种特定的数据结构上的,最简单的例子就是快速排序算法最根本的实现条件就是所排序的对象是存

贮在数组里面,因为快速排序就是因为要用到数组的随机存储特性,即可以在单位时间内交换远距离的对象,而不只是相临的两个对象,而如果用联表去存储对象,由于在联表中取得对象的时间是线性的既O[n],这样将使快速排序失去其快速的特点。也就是说,我们在设计一种算法的时候,我们总是先要考虑其应用的数据结构,比如数组查找,联表查找,树查找,图查找其核心都是查找,但因为作用的数据结构不同

将有多种不同的表现形式。数据结构和算法之间这样密切的关系一直是我们以前的认识。泛型设计的根本思想就是想把算法和其作用的数据结构分离,也就是说,我们设计算法的时候并不去考虑我们设计的算法将作用于何种数据结构之上。泛型设计的理想状态是一个查找算法将可以作用于数组,联表,树,图等各种数据结构之上,变成一个通用的,泛型的算法。这样的理想是不是很诱惑人?

泛型编程带来的是前所未有的弹性以及不会损失效率的抽象性,GP和OO不同,它不要求你通过额外的间接层来调用函数:它让你撰写完全一般化并可重复使用的算法,其效率与针对特定数据结构而设计的算法旗鼓相当。我们大家都知道数据结构在C++中可以用用户定义类型来表示,而C++中的模板技术就是以类型作为参数,那么我可以想象利用模板技术可以实现我们开始的GP思想,即一个模板函数可以对于各种传递进来的类型起作用,而这些类型就可以是我们定义的各种数据结构。

泛型算法抽离于特定类型和特定数据结构之外,使得其适应与尽可能的一般化类型,算法本身只是为了实现算法其需要表达的逻辑本质而不去被为各种数据结构的实现细节所干扰。这意味着一个泛型算法实际具有两部分。1,用来描叙算法本质逻辑的实际指令;2,正确指定其参数类型必须满足的性质的一组需求条件。到此,相信有不少人已经开始糊涂了,呵呵,不要紧。毕竟GP是一种抽象度非常高的程序设计思想,里面的核心就是抽象条件成为成为程序设计过程中的核心,从而取代了类型这在OO里面的核心地位,正是因为类型不在是我们考虑的重点,类型成为了抽象条件的外衣,所以我们称这样的程序思想为泛型思想------把类型泛化。

算法分析

.评价算法好坏的标准 求解同一计算问题可能有许多不同的算法 究竟如何来评价这些算法的好坏以便从中选出较好的算法呢?  选用的算法首先应该是 正确 的 此外 主要考虑如下三点 ① 执行算法所耗费的时间 ② 执行算法所耗费的存储空间 其中主要考虑辅助存储空间 ③ 算法应易于理解 易于编码 易于调试等等

.算法性能选择 一个占存储空间小 运行时间短 其它性能也好的算法是很难做到的 原因是上述要求有时相互抵触 要节约算法的执行时间往往要以牺牲更多的空间为代价 而为了节省空间可能要耗费更多的计算时间 因此我们只能根据具体情况有所侧重 ① 若该程序使用次数较少 则力求算法简明易懂 ② 对于反复多次使用的程序 应尽可能选用快速的算法 ③ 若待解决的问题数据量极大 机器的存储空间较小 则相应算法主要考虑如何节省空间

.算法的时间性能分析 ( )算法耗费的时间和语句频度 一个算法所耗费的时间=算法中每条语句的执行时间之和每条语句的执行时间=语句的执行次数(即频度(Frequency Count))×语句执行一次所需时间  算法转换为程序后 每条语句执行一次所需的时间取决于机器的指令性能 速度以及编译所产生的代码质量等难以确定的因素 若要独立于机器的软 硬件系统来分析算法的时间耗费 则设每条语句执行一次所需的时间均是单位时间 一个算法的时间耗费就是该算法中所有语句的频度之和

例 求两个n阶方阵的乘积 C=A×B 其算法如下:# define n // n 可根据需要定义 这里假定为 void MatrixMultiply(int A[a] int B [n][n] int C[n][n]){ //右边列为各语句的频度int i j k;( ) for(i= ; i<n;j++) n+ ( )   for (j= ;j<n;j++) { n(n+ )( )     C[i][j]= ; n ( )     for (k= ; k<n; k++) n (n+ )( )       C[i][j]=C[i][j]+A[i][k]B[k][j]; n        }     }

 该算法中所有语句的频度之和(即算法的时间耗费)为          T(n)= n + n + n+ ( )分析 语句( )的循环控制变量i要增加到n 测试到i=n成立才会终止 故它的频度是n+ 但是它的循环体却只能执行n次 语句( )作为语句( )循环体内的语句应该执行n次 但语句( )本身要执行n+ 次 所以语句( )的频度是n(n+ ) 同理可得语句( ) ( )和( )的频度分别是n n (n+ )和n算法MatrixMultiply的时间耗费T(n)是矩阵阶数n的函数

( )问题规模和算法的时间复杂度 算法求解问题的输入量称为问题的规模(Size) 一般用一个整数表示 例 . 矩阵乘积问题的规模是矩阵的阶数 例 . 一个图论问题的规模则是图中的顶点数或边数 一个算法的时间复杂度(Time Complexity 也称时间复杂性)T(n)是该算法的时间耗费 是该算法所求解问题规模n的函数 当问题的规模n趋向无穷大时 时间复杂度T(n)的数量级(阶)称为算法的渐进时间复杂度 例 . 算法MatrixMultidy的时间复杂度T(n)如( )式所示 当n趋向无穷大时 显然有   

    这表明 当n充分大时 T(n)和n 之比是一个不等于零的常数 即T(n)和n 是同阶的 或者说T(n)和n 的数量级相同 记作T(n)= (n )是算法MatrixMultiply的渐近时间复杂度 数学符号 的严格的数学定义 若T(n)和f(n)是定义在正整数集合上的两个函数 则T(n)= (f(n))表示存在正的常数C和n 使得当n≥n 时都满足 ≤T(n)≤C·f(n)

( )渐进时间复杂度评价算法时间性能 主要用算法时间复杂度的数量级(即算法的渐近时间复杂度)评价一个算法的时间性能 例 . 有两个算法A 和A 求解同一问题 时间复杂度分别是T (n)= n T (n)= n ( )当输入量n< 时 有T (n)>T (n) 后者花费的时间较少 ( )随着问题规模n的增大 两个算法的时间开销之比 n / n =n/ 亦随着增大 即当问题规模较大时 算法A 比算法A 要有效地多 它们的渐近时间复杂度 (n )和 (n )从宏观上评价了这两个算法在时间方面的质量 在算法分析时 往往对算法的时间复杂度和渐近时间复杂度不予区分 而经常是将渐近时间复杂度T(n)=O(f(n))简称为时间复杂度 其中的f(n)一般是算法中频度最大的语句频度

例 . 算法MatrixMultiply的时间复杂度一般为T(n)= (n ) f(n)=n 是该算法中语句( )的频度 下面再举例说明如何求算法的时间复杂度

例 . 交换i和j的内容     Temp=i;    i=j;    j=temp;

 以上三条单个语句的频度均为 该程序段的执行时间是一个与问题规模n无关的常数 算法的时间复杂度为常数阶 记作T(n)=O( ) 如果算法的执行时间不随着问题规模n的增加而增长 即使算法中有上千条语句 其执行时间也不过是一个较大的常数 此类算法的时间复杂度是O( )

例 . 变量计数之一 ( ) x= ;y= ;( ) for(k ;k<=n;k++)( )   x++;( ) for(i= ;i<=n;i++)( )     for(j= ;j<=n;j++)( )       y++;

 一般情况下 对步进循环语句只需考虑循环体中语句的执行次数 忽略该语句中步长加 终值判别 控制转移等成分 因此 以上程序段中频度最大的语句是( ) 其频度为f(n)=n 所以该程序段的时间复杂度为T(n)= (n ) 当有若干个循环语句时 算法的时间复杂度是由嵌套层数最多的循环语句中最内层语句的频度f(n)决定的

例 . 变量计数之二 ( ) x= ;( ) for(i= ;i<=n;i++)( )     for(j= ;j<=i;j++)( )         for(k= ;k<=j;k++)( )             x++;

 该程序段中频度最大的语句是( ) 内循环的执行次数虽然与问题规模n没有直接关系 但是却与外层循环的变量取值有关 而最外层循环的次数直接与n有关 因此可以从内层循环向外层分析语句( )的执行次数  则该程序段的时间复杂度为T(n)= (n / +低次项)= (n )

( )算法的时间复杂度不仅仅依赖于问题的规模 还与输入实例的初始状态有关 例 . 在数值A[ n ]中查找给定值K的算法大致如下     ( )i=n ;        ( )while(i>= &&(A[i]!=k))    ( )   i ;    ( )return i;

 此算法中的语句( )的频度不仅与问题规模n有关 还与输入实例中A的各元素取值及K的取值有关:①若A中没有与K相等的元素 则语句( )的频度f(n)=n ②若A的最后一个元素等于K 则语句( )的频度f(n)是常数

( )最坏时间复杂度和平均时间复杂度 最坏情况下的时间复杂度称最坏时间复杂度 一般不特别说明 讨论的时间复杂度均是最坏情况下的时间复杂度 这样做的原因是 最坏情况下的时间复杂度是算法在任何输入实例上运行时间的上界 这就保证了算法的运行时间不会比任何更长 例 . 查找算法例 · 在最坏情况下的时间复杂度为T(n)= (n) 它表示对于任何输入实例 该算法的运行时间不可能大于 (n) 平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下 算法的期望运行时间 常见的时间复杂度按数量级递增排列依次为 常数 ( ) 对数阶 (log n) 线形阶 (n) 线形对数阶 (nlog n) 平方阶 (n )立方阶 (n ) … k次方阶 (n k) 指数阶 ( n) 显然 时间复杂度为指数阶 ( n)的算法效率极低 当n值稍大时就无法应用     类似于时间复杂度的讨论 一个算法的空间复杂度(Space Complexity)S(n)定义为该算法所耗费的存储空间 它也是问题规模n的函数 渐近空间复杂度也常常简称为空间复杂度 算法的时间复杂度和空间复杂度合称为算法的复杂度

lishixinzhi/Article/program/sjjg/201311/22593

你这个是梭织布吧 经向:全棉32/1 纬向:麻21/1 然后经纬密度是:100X60

算法为:100/32=3125 60/21=2857

3125+2857=5982

然后算法:C32=3125/5982=522%

L21=2857/5982=478%

另外小提示一下:你的表示L21 这个支数有问题因为L21这么粗的纱,密度不应该是60,连最紧密的贡锻也不可能这么应该是公制如果是公制表示的粗细,那要相应换成英制才行

多因子分析(Multiple Factor Analysis)是一种统计分析方法,用于研究多个因子对于观察对象的影响。在多因子分析中,常用的算法包括主成分分析(Principal Component Analysis, PCA)和因子分析(Factor Analysis)。

1 主成分分析(PCA):主成分分析是一种降维技术,用于将多个相关变量转化为少数几个无关的主成分。它通过计算协方差矩阵或相关系数矩阵,找到最能解释原始数据变异性的线性组合。主成分分析可以帮助我们理解数据的结构、降低数据的维度,并发现隐藏在数据背后的重要信息。

2 因子分析(Factor Analysis):因子分析也是一种降维技术,用于找出多个观测变量背后的潜在因子。它假设观测变量与潜在因子之间存在线性关系,并通过计算因子载荷矩阵来确定每个观测变量与潜在因子之间的相关性。因子分析可以帮助我们理解观测变量之间的关系,发现潜在的因素,并简化数据分析过程。

除了主成分分析和因子分析,还有其他一些常用的多因子分析算法,例如聚类分析(Cluster Analysis)、判别分析(Discriminant Analysis)和结构方程模型(Structural Equation Modeling, SEM)等。这些算法可以根据不同的研究目的和数据特点选择使用。

需要注意的是,选择合适的多因子分析算法需要结合具体的研究问题、数据类型和分析目的来进行决策。在实际应用中,通常需要综合考虑多个因素,包括数据特点、算法假设、计算复杂度、解释能力等,来选择最适合的算法。

算法就是解决某一具体问题所采取的方法和步骤。

著名的计算机科学家沃思(Wirth)提出了一个著名的公式来表达程序的实质:

程序=数据结构+算法

即程序就是在数据的某些特定的表达方式和结构的基础上,对抽象算法的具体描述。

当然,在实际编写计算机程序时,要遵循程序设计方法,在运行程序时要有软件环境的支持,因此,可以将上述公式扩充为:

程序=数据结构+算法+程序设计方法+语言工具

即一个应用程序应该包括四个方面的成分:采用的描述和存储数据的数据结构,采用的解决问题的算法,采用的程序设计的方法和采用的语言工具和编程环境。

1、算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。

不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。

2、算理就是计算过程中的道理,是指计算过程中思维方式,是解决为什么这样算的问题。如计算214+35时,就是根据数的组成进行演算的:214是由2个百、1个十和4个一组成的,35是由3个十和5个一组成的,所以先把4个一与5个一相加9个一,再把1个十与3个十相加得4个十,最后把2个百、4个十和9个一合并得249,这就是算理。

扩展资料:

算法常用设计模式

1、完全遍历法和不完全遍历法:在问题的解是有限离散解空间,且可以验证正确性和最优性时,最简单的算法就是把解空间的所有元素完全遍历一遍,逐个检测元素是否是我们要的解。

这是最直接的算法,实现往往最简单。但是当解空间特别庞大时,这种算法很可能导致工程上无法承受的计算量。这时候可以利用不完全遍历方法——例如各种搜索法和规划法——来减少计算量。

2、分治法:把一个问题分割成互相独立的多个部分分别求解的思路。这种求解思路带来的好处之一是便于进行并行计算。

3、动态规划法:当问题的整体最优解就是由局部最优解组成的时候,经常采用的一种方法。

4、贪心算法:常见的近似求解思路。当问题的整体最优解不是(或无法证明是)由局部最优解组成,且对解的最优性没有要求的时候,可以采用的一种方法。

5、简并法:把一个问题通过逻辑或数学推理,简化成与之等价或者近似的、相对简单的模型,进而求解的方法。

参考资料:

算法

参考资料:

算理

1、确定配方中每种原材料的成分和含量,并计算出每种原材料所需的最小重量或体积。

2、根据需要生产的产品数量和单个产品所需的原材料数量,按比例计算出每种原材料的总需求量。

3、考虑到实际操作中可能存在的损耗和浪费,根据经验确定合适的系数,并将总需求量乘以该系数得到实际需要采购的原材料总量。

4、在采购原材料时,注意核对原材料的成分、品质和规格等信息,以确保有效地控制成本和保证产品质量。

算法的“确定性”指的是组成算法的每条指令是清晰的,无歧义的。

算法是《数据结构》这门课程中常用的一个概念。算法的定义可以简单表述为:“算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条指令表示一个或多个操作。“任何算法都具有确定性。

即“算法中的每一条指令必须有确定的含义,读者理解时不会产生二义性。并且,在任何条件下,算法只有唯一的一条执行路径,即对于相同的输入只能得出相同的输出。”

在笔者教学实践中,常有学生对算法的确定性表示怀疑。甚至有的学生提出一种反对意见:高级语言几乎都提供了随机函数,如果一个算法调用随机函数那么得到的结果事先是无法预知的,该算法也就不具有确定性。本文通过正反两个方面对这种错误观点加以分析。

算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。

如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。

形式化算法的概念部分源自尝试解决希尔伯特提出的判定问题,并在其后尝试定义有效计算性或者有效方法中成形。这些尝试包括库尔特·哥德尔、Jacques Herbrand和斯蒂芬·科尔克莱尼分别于1930年、1934年和1935年提出的递归函数。

阿隆佐邱奇于1936年提出的λ演算,1936年Emil Leon Post的Formulation 1和艾伦图灵1937年提出的图灵机。即使在当前,依然常有直觉想法难以定义为形式化算法的情况。

欢迎分享,转载请注明来源:品搜搜测评网

原文地址:https://pinsoso.cn/meirong/2041793.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-11-05
下一篇2023-11-05

随机推荐

  • 科丝美诗生产哪些大牌?

    1、植村秀,植村秀品牌起名源于其品牌创始人,当今国际世界著名化妆艺术大师植村秀先生。是全球首个风尚主题妆容的先驱,因其创作的概念前卫和用色大胆而被公认为彩妆艺术界大师级人物。2、卡姿兰,卡姿兰,时尚彩妆领导品牌,用国际美学,定义彩妆潮流,用

    2024-04-15
    761100
  • 柔嘉艾灸是上市公司吗

    不是。根据查询BOSS直聘网显示:1、柔嘉企业是一家集科研、生产、销售,投资、教育培训、营销咨询、专业会展、网络科技为一体的多元化、现代化集团公司,也是国内最具有发展潜质的健康产业公司。2、柔嘉艾灸没有向证券监督管理机构提出股票上市申请。柔

    2024-04-15
    22900
  • 有没有好的防晒乳呢?

    1、Nivea妮维雅水感防晒啫喱SPF50这个妮维雅水感防晒是目前为止我用得最多的一款防晒,找代购买80人民币左右有140g的容量,所以大量抹在胳膊上腿上也不心疼。它挤出来是半水状半乳液状的质地,不像那种厚重的防晒,很水润,极度容易推开,抹

    2024-04-15
    10400
  • 天气丹三个版本的区别

    天气丹三个版本的没有区别。虽然它们的叫法不同,但是套盒中的爽肤水和乳液在成分以及含量上都是一模一样的,所以三个版本的天气丹是不分好坏的。天气丹套盒适应的肤质比较广泛,干性肌肤使用以后能够很好的补水保湿,油性皮肤使用以后能够很好的控油祛痘,因

    2024-04-15
    17400
  • 妮维雅男士洗面奶好吗?

    每日正常的洁肤次数最好为3次,除早晚之外,中间应增加1次。此外,户外活动或长时间购物等活动之后,还应该适当增加洁肤的次数。洗面的次数究竟该多少次还要考虑肤质、年龄和季节等因素。干性、敏感性肤质和年龄偏大者,应适当减少洗面的次数,并应慎重使用

    2024-04-15
    9800
  • 伊荣肤美玻色因胶原蛋白焕颜套装怎么用

    伊荣肤美玻色因胶原蛋白焕颜套装的使用方法如下:1 涂抹水乳霜后,取适量玻色因精华液,按照肌肤纹理均匀涂抹于面部,按摩至吸收即可。2 取适量玻色因精华乳,按照肌肤纹理均匀涂抹于面部,按摩至吸收即可。3 取适量玻色因面霜,按照肌肤纹理均匀涂抹于

    2024-04-15
    8400
  • 精华露和精华液的区别是什么 如何正确使用精华

      一直以来精华类的护肤品效果是非常显著的,很多人都非常喜欢这类产品。通常来说精华类的产品里面都蕴含着非常丰富的营养成分,具有非常好的护肤效果,而精华类产品有精华露和精华液,很多人都不知道精华露和精华液的区别是什么。  精华露其实就是高度浓

    2024-04-15
    18600

发表评论

登录后才能评论
保存