简单来说,数据结构是一门研究非数值计算的程序设计问题中计算机操作对象以及它们之间的关系和操作的学科。
【数据】是对客观事物的符号表示,在计算机科学中指代所有能输入到计算机中并被计算机程序处理的符号的总称;
【数据元素】是数据的基本单位,在程序中通常作为一个整体进行考虑及处理。数据元素可由若干个【数据项】组成,数据项是数据的不可分割的最小单位;
【数据对象】是性质相同的数据元素的集合,是数据的一个子集;
【数据结构】是相互之间存在一种或多种特定关系的数据元素的集合。在任何问题中,数据都不是孤立存在的,而是存在着某种关系。这种数据元素相互之间的关系被称为【结构】。
根据数据元素之间关系的不同特性,通常被分为四种:
1)集合:结构中的数据元素之间除了同属于一个集合的关系外没有其他的关系;
2)线性结构:结构中的数据元素之间存在一对一的关系;
3)树形结构:结构中的数据元素之间存在一对多的关系;
4)图状结构或网状结构:结构中的数据元素存在多对多的关系。
我们可以将数据结构定义为二元组的形式:Data_Structure = (D, S)
其中D代表数据元素的有限集,S代表D上关系的有限集。
结构定义中的【关系】描述的是数据元素之间的逻辑关系,因此又被称为数据的逻辑结构;
数据结构在计算机中的表示(映像)称为数据的物理结构,又称存储结构。
在计算机中表示信息的最小单位是二进制数的一位,称为位,我们可以使用若干位组合起来形成的一个位串表示一个数据元素,通常称这个位串为元素或结点。当数据元素由若干个数据项组成时,位串中对应于各个数据项的子位串称为数据域。
数据元素之间的关系在计算机中有两种不同的表示方法:顺序映像和非顺序映像,由此得到两种不同的存储结构:顺序存储结构以及链式存储结构。
顺序映像的特点是借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系;非顺序映像则是借助指示元素存储地址的指针表示数据元素之间的逻辑关系。
【数据类型】是和数据结构密切相关的一个概念,用来刻画操作对象的特性。数据类型是一个值的集合和定义在该集合上的一组操作的总称。
按照值的不同特性,高级程序语言中的数据类型可以分为两类:原子类型以及结构类型。
原子类型是指其值不可分解,例如整型、字符型、指针类型等;而结构类型的值是由若干部分按照某种结构组成的,可以进行分解。
抽象数据类型是指一个数学模型以及定义在该模型上的一组操作。抽象数据类型的定义仅取决于它的一组逻辑特性,而与其在计算机内部如何表示与实现无关。
抽象数据类型的定义由一个值域和定义在该值域上的一组操作组成,可以细分为下列三种类型:
1)原子类型:属于原子类型的变量值是不可分解的;
2)固定聚合类型:其值由确定数目的成分按某种结构组成;
3)可变聚合类型:其值的成分的数目不确定。
我们可以将抽象数据类型定义为三元组的形式:(D, S, P)
其中D代表数据对象,S代表D上的关系集,P代表对D的基本操作。
ADT 抽象数据类型名{
数据对象
数据关系
基本操作(参数表):
初始条件
操作结果
}ADT 抽象数据类型名
算法是对特定问题求解步骤的一种描述,它是指令的有限序列。其中每条指令表示一个或多个的操作。
一个算法应具备以下五种特性:
1)有穷性 一个算法必须总是对于任何合法的输入值在执行有穷步后结束且每一步需要在有穷时间内完成;
2)确定性 算法的每一条指令需要有确切的含义,读者理解时不会产生二义性。并且在任何条件下,算法只有唯一的一条执行路径,对于相同的输入只能得出相同的输出;
3)可行性 算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现的;
4)输入 算法中有零个或多个输入,这些输入取自于某个特定的对象的集合;
5)输出 算法有一个或多个输出,这些输出是同输入有着某些特定关系的量。
通常设计一个好的算法需要达成以下四点要求:
1)正确性 算法应当满足具体问题的需求,要求程序不含语法错误,对于几组出入数据能够得到满足规格说明要求的结果,程序对于精心选择的典型、苛刻带有刁难性的几组输入数据能够得出满足规格说明要求的结果,程序对于一切合法的输入数据都能产生满足规格说明要求的结果;
2)可读性 算法主要是为了人的阅读与交流,可读性好有助于人对于算法的理解;
3)健壮性 当输入数据非法时,算法也能够适当的作出反应或进行处理而不会产生莫名其妙的输出结果;
4)效率与低存储量需求 效率通常指的是算法执行的时间,存储量需求指算法执行过程中所需要的最大存储空间。
算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗的时间来度量,度量一个程序的执行时间通常有两种办法。
1)事后统计的办法 很多计算机内部都有计时功能,不同算法的程序可通过一组或若干组相同的统计数据以分辨优劣;
2)事前估算的办法 一个用高级程序语言编写的程序在计算机上运行所消耗的时间取决于下列因素:依据的算法使用何种策略;问题的规模;书写程序的语言;编译程序所产生的机器代码的质量;机器执行指令的速度。
一般情况下,算法中基本操作重复执行的次数是问题规模 n
的某个函数 f(n)
,算法的时间量度记作 T(n) = O(f(n))
,它表示随着问题规模 n
的增大,算法执行时间的增长率和 f(n)
的增长率相同,称为算法的渐进时间复杂度,简称为时间复杂度。
被称作问题的基本操作的原操作应是其重复执行次数和算法执行时间成正比的原操作,多数情况下它是最深层循环内的语句中的原操作,它的执行次数和包含它的语句频度相同。语句的频度指的是该语句重复执行的次数。
常见的时间复杂度包括常量阶 O(1)
、线性阶 O(n)
、平方阶 O(n^2)
、对数阶 O(logn)
以及指数阶 O(2^n)
等,我们应当尽量选用多项式阶 O(n^k)
的算法,而不希望使用指数阶的算法。
类似于算法的时间复杂度,将算法所需存储空间的量度称为空间复杂度,记作 S(n) = O(f(n))
。其中 n
为问题的规模或大小。一个程序除了需要存储空间来寄存本身所需要的指令、常数、变量以及输入数据之外,也需要一些对数据进行操作的工作单元和存储一些为实现计算所需信息的辅助空间。若输入数据所占空间只取决于问题本身,和算法无关,则只需要分析除输入和程序之外的额外空间,否则应当同时考虑输入本身所需空间。若额外空间相对于输入数据量来说是常数,则称此算法为原地工作。