【摘抄】
数据的逻辑结构、数据的存储结构和数据的运算
一、数据的逻辑结构
数据的逻辑结构反映了人们对数据的含义解释。一个逻辑结构可以用一组数据结点和一个关系集合R来表示:
(K,R)
其中,K是由有限个结点组成的集合,R是一组定义在集合K上的二元关系。在此需要重点掌握的内容包括结点的类型、结构的分类、结点和结构等几部分。
结点的类型可以是基本数据类型,也可以是复合数据类型。常见的程序设计语言中使用了5种基本的数据类型:整数类型、实数类型、布尔类型、字符类型、指针类型,它们的共同特点是在程序访问数据时,把基本数据类型看成一个整体,而不会把基本类型的一个组成部分看作独立含义的数据。
根据关系集R中关系r的分类,结点的结构一般可分为线性结构、树形结构和图结构。这种结构分类揭示了枯燥数据之间的相互关系,给出了关系本身的一般性质,对于理解数据结构以及正确设计算法都是很重要的。
线性结构在程序设计中应用最为广泛。它是一种满足全序性和单索性等约束条件的有向关系。全序性是指,线性结构的全部结点两两皆可以比较前后;单索性是指,每一个结点x 都可以存在唯一的一个直接后继结点y。 树形结构,也称树结构,是一种层次结构,其关系r 称为层次关系或“父子关系”。树形结构的最高层次的结点称为根结点(root),只有它没有父结点。树形结构存在着很多变种,如二叉树、堆结构等,它们都有各自独特的应用。图结构也称网络结构,其关系r 没有任何约束。
二、数据的存储结构
数据的存储结构是建立一种由逻辑结构到存储空间的映射:对于逻辑结构(K,r), 其中r Î R,对它的结点集合K建立一个从K 到存储器M 的单元的映射:K->M,其中每个结点j ÎK都对应一个惟一的连续存储区域c Î M。
常用的基本存储映射方法有顺序方法、链接方法、索引方法和散列方法。
顺序存储把一组结点存放在按地址相邻的存储单元里,结点间的逻辑关系用存储单元的自然顺序关系来表达的,即,用一块存储区域存储线性数据结构。顺序存储法为使用整数编码访问数据结点提供了便利。因为,顺序存储方法的存储空间除了存储有用数据外,没有用于存储其他附加的信息,所以顺序存储结构一般也被称为紧凑存储结构。
链接法是在结点的存储结构中附加指针字段来存储结点间的逻辑关系。链接法中数据结点包括两部分:数据字段存放结点本身的数据,指针字段存放指向其后继结点的指针。链接方法适用于那些需要经常进行增删结点的复杂数据结构。
索引法是顺序存储的一种推广,用于大小不等的数据结点的顺序存储。通过建造一个由整数域Z映射到存储地址域的函数,把整数索引值映射到结点的存储地址,从而形成一个存储一串指针的索引表,每个指针指向存储区域的一个数据结点。
作为索引法的一种延伸和扩展,散列法利用散列函数进行索引值的计算,然后通过索引表求出结点的指针地址。
算法的一般性质
算法的一般性质包括:
(1) 通用性 对于那些符合输入类型的任意输入数据,都能根据算法进行问题求解,包保证计算结构的正确性。
(2) 有效性 组成算法的每一条指令都必须是能够被人或机器确切执行的。
(3) 确定性 算法每执行一步之后,对于它的下一步,应该有明确的指示。即,保证每一步之后都有关于下一步动作的指令,不能缺乏下一步指令或仅仅含有模糊不清的指令。
(4) 有穷性 算法的执行必须在有限步内结束。
二、常见的算法类型
在实际应用中,算法的表现形式千变万化,但许多算法的设计思想具有相似之处。归纳起来,常用的算法大致可分为以下几类:
(1) 穷举法 基本思想是在一个可能存在可行状态(可行解)的状态全集中依次遍历所有的元素,并判断是否为可行状态。
(2) 贪心法 基本思想是试图通过局部最优解得到全局最优解。
(3) 分治法 基本思想是把一个规模较大的问题划分成相似的小问题,各个求解,再得整个问题的解。
(4) 回溯法 基本思想是一步一步向前试探,等有多种选择时任意选择一种,只要可行就继续向前,一旦失败时就后退回来选择其它可能性。
(5) 动态规划法 基本思想是把大问题分解为若干小问题,通过求解子问题来得到原问题的解。由于这些子问题相互包含,为了复用已计算的结果,常把计算的中间结果全部保存起来,自底向上多路经地求解计算原问题的解。
(6) 分枝界限法 基本思想是在表示问题空间的树上进行系统搜索时采用广度优先策略,同时利用最优解属性的上下界来控制搜索的分枝。
一个算法优劣的重要依据:渐进分析实现该算法的程序在计算机中执行时所需占用的机器资源的多少。另外介绍两个重要指标:算法的空间代价(或称空间复杂性)和算法的时间代价(或称时间复杂性)。渐进分析的结果是得到一个大 O 渐进表达式。
一、空间代价和时间代价
算法空间代价(或称空间复杂性)一般定义为求解问题的算法所需占用的存储空间大小。当问题的规模以某种单位由 1 增至 n 时,求解该问题的算法所需占用的空间也以某单位由f(1) 增至 f(n), 则称函数 f(n) 为该算法的空间代价。
算法的时间代价(或称时间复杂性) )一般定义为求解问题的算法所需耗费的时间大小。当问题的规模以某种单位由 1 增至 n 时,求解该问题的算法所需占用的时间也以某单位由g(1) 增至 g(n), 则称函数 g(n) 为该算法的时间代价。
二、算法的渐进分析
以算法的时间代价为例,算法的渐进分析就是估计当求解问题的规模 n 逐步增大时,时间开销 T(n) 的增长趋势。为简化时间和空间复杂性的度量,可以只关注于复杂性的量级,而忽略量级的系数。而从数量级大小来考虑,当 n 增大到一定值以后,T(n) 计算公式中影响最大的就是 n 的幂次最高的项,其他的常数项和低幂次项都是可以忽略的。
渐进分析的结果是得到一个大 O 渐进表达式, 简写为
其中,T(n) 是算法运行所消耗的时间或存储空间的总量,O 是数学分析常用的符号“大O”,f(n) 是自变量为 n 的某个具体的函数表达式,n 反映求解问题的规模。也即,如果存在正的常数 c 和 ,当问题的规模后,某算法的时间(空间)代价,则说该算法的时间(空间)代价为。
根据大 O 表示法的定义,有下列常用的计算规则:
(1) 加法规则 设有两个程序段S1 和S2,其时间代价分别为和,将两个程序段连接在一起得到(S1 :S2),则总的时间代价为
(2) 乘法规则 假设有 和,如果一个程序的时间代价为,但其时间单位并不是最基本的,而是以某个子程序的执行代价为单位时间()来考虑的,那么这个程序的实际时间代价为
来源:http://www.jpk.pku.edu.cn/pkujpk/course/sjjg/chapter1/c01_jj.html