“数据类型+算法=程序”
一、数据结构的基本概念
1:数据类型与数据结构
1)数据:
数据是计算机程序的处理对象,包括描述客观事物数量特征的数值数据和描述名称特征的字符数据等,它是以多种形式呈现的信息,可以是任何能输入计算机并等待其加工处理的符号集合的总称。
数据的基本单位是数据元素(data element),它是表示一个事物的一组数据,通常在逻辑上作为一个整体进行考量和处理,有时也称为数据结点。而数据元素可能分成若干成分,构成数据元素的某个成分的数据称为该数据元素的数据项(data item),也成为数据域(data field),数据项是数据元素的基本单位。
2)数据类型
在用高级程序语言编写程序中,必须对程序中出现的每个变量、常量、表达式,明确说明它们的数据类型,它就如同一个模板,定义了属于该种类型的数据对象的性质、取值范围、对该类数据对象所能进行的操作等。
3)抽象数据类型:
数据类型和算法中使用的数据类型不仅仅局限于程序设计语言中的数据类型,更多的是指某种抽象数据类型(Abstract data type,ADT)。抽象数据类型是指一个概念意义上的数据类型和这个类型上的逻辑操作集合,我们讨论的线性表,栈,队列,串,数组和矩阵,树,二叉树,图等都是典型的数据结构。
抽象数据类型具有数据抽象和数据封装两个重要特征。数据抽象特征表现在用抽象数据类型描述程序处理的数据实体时,强调的是数据的本质特征、其所能完成的功能以及它和外部的接口(外界使用它的方法)。数据封装特征表现在抽象类型数据将数据实体的外部特征和内部实现细节分离,并对外部用户隐藏其内部实现细节。
4)数据结构:
数据结构是指数据元素之间存在某种关系的数据集合,它可以看成是关于数据集合的数据类型。
它关注三个方面内容:数据元素的特性、数据元素之间的关系、数据元素组成的数据集合所允许进行的操作
2:数据的逻辑类型
数据的逻辑结构侧重于数据集合的抽象特性,它描述数据集合中数据元素之间的逻辑,常见的数据结构可以分为三种基本类型:线性结构、树结构、图结构。
1)线性结构
一组具有某种共性的数据元素按照某种逻辑上的顺序关系组成一个数据集合,特征是,第一个数据没有前驱,最后一个元素没有后继,其他每个元素只有一个前驱和后继
数组是最基本的具有线性结构的数据集合,其他的比如,线性表,栈,队列等
A→B→C
2)树结构
一组具有某种共性的数据元素按照某种逻辑上的层次关系组成的一个数据集合,特征是,有一个根结点(root),没有前驱元素,其他每个数据元素都只有一个前驱,可能有0-若干个后继
A
↙ ↘
B C
↙ ↘ ↙ ↘
D E F G
3)图结构
一组具有某种共性的数据元素按照某种逻辑上的网状关系组成的一个数据集合,特征是,每个数据元素可能有零到若干前驱和后继
A → D
↑ ↓ ↘ ↓↑
B ← C
3:数据的存储类型
数据集合在计算机中的存储方式称为数据的存储结构,也成为物理结构
常见的数据存储结构分为顺序存储结构和链式存储结构
1)顺序存储结构
顺序存储结构是将数据集合中的数据元素存储在一块地址连续的内存空间中,并且逻辑上相近的元素在物理上也相邻
2)链式存储结构
链式存储结构使用称为链结点(link node)的扩展类型存储各个数据类型,链节点由数据元素域和指向其他结点的指针域构成,链式存储结构使用指针将相互关联的结点链接起来,数据域存储数据,指针域指向相关节点,指针域保存指向相关节点的链信息,因此又称为链域
用这两种存储结构的不同组合可以产生复杂的存储结构
3)存储密度
一个数据结构所需的存储空间不仅用来存放数据本身,也可能存放其他信息
存储密度=数据本身的所占存储量/整个结构所占的存储总量
如果数据结构所有的存储空间都用来存储数据元素,这种存储结构称为紧凑结构,存储密度为1。
顺序存储中所有分配的存储空间都被数据元素自身占用,存储密度为1
链式存储结构中,每个结点至少包含数据域和指针域,因而链式存储结构是非紧凑结构,但是附加的信息会带来操作上的便利
4:数据的操作
数据的操作是定义在数据的逻辑结构上的,在不同的逻辑结构中插入和删除元素的操作是不同的
例如树结构和图结构和线性结构在进行操作时的实现方式不同
在某个逻辑结构上定义的操作的具体实现和数据的存储结构相关
例如对于一个线性数据集合,选择顺序和链式存储结构进行插入和删除操作都有不同的实现方式
二、算法与算法分析
1:算法
1)算法定义
简单来说,算法(algorithm)是指一系列的计算步骤,特定的算法描述对特定问题的求解过程,它定义了解决该问题的一个确定的、有限长的操作序列。
算法过程具有5个重要特征:
确定性:对于每种情况下所应当执行的操作,在算法中都有确切的规定,算法的执行者或阅读者都能明确其含义,并且在任何条件下都只有一条执行路径
可行性:算法中的所有操作都必须是足够基本的,都可以通过已经实现的基本操作运算有限次得以实现
有穷性:对于任意一组合法输入值,算法必须在执行有穷步骤后结束,算法中的每个步骤都能在有限时间完成
有输入:算法有零个或多个输入数据,它们构成算法的加工对象
有输出:有一个或多个输出,它们是算法进行加工后的结构
2)计算模型
计算模型是指算法实现技术的模型,它具有两方面的基本特征
采用通用的单处理器:同一时间执行一条指令,并且执行的指令是确定的,计算机程序以指令一条接一条地执行地方式实现算法
随机存储器(random access machine,RAM),处理器可以随机访问存储器
3)算法的描述方式
算法过程可用文字、流程图、高级程序设计语言来实现,无论哪种描述性是,都要体现出算法是由语义明确的操作步骤组成的有限操作序列,它精确的描述了怎样将给定的输入信息加工处理,逐步得到要求的输出信息,算法的执行者或阅读者都能明白其含义
4)算法和数据结构的关系
不同的逻辑结构需采用不同算法
同样的逻辑结构因为存储结构的不同而采用不同的算法,比如用顺序存储结构实现的线性表称为顺序表,用链式存储结构实现的线性表称为链表,例如它们在排序算法中,顺序表可以采用冒泡排序、折半插入排序等算法,而链表则采用直接插入排序、简单选择排序等。
同样的逻辑结构和存储结构,因为要解决问题的要求不同而采用不同的算法
/*
线性表的顺序查找(sequential search )算法
大规模线性表的分块查找(blocking search)算法
*/
2:算法设计的要求
1)正确性
不含语法错误、对于输入的简单的或复杂数据能够得出满足要求的结果、程序对于一切合法的输入数据都能够得出满足要求的结果
2)可读性
被描述算法中的类名、对象名、方法名等命名要简明
有足够多的注释
3)健壮性
当输入非法数据时,算法要做适当的处理,不应中断程序执行,而应该返回一个表示错误或错误性质的值
4)高效性
算法在执行时一般要求额外的内存空间,内存要求低的算法称为高空间效率算法,一般首先考虑算法的时间效率。
3:算法效率分析
1)算法的时间复杂度
算法重复执行原操作的次数是该算法所处理的数据个数n的某种函数f(n),其渐进特性称作该算法的时间复杂度(time complexity),记作T(n)=O(f(n)),它表示随着问题规模的增大,算法执行时间的增长率和函数f(n)的增长率相同,通常用算法的时间复杂度来表示算法的时间效率。
O(1)表示算法执行时间是一个常数,不依赖于n,O(n)表示算法执行时间与n成正比,线性关系,O(n²)表示平方阶,其他的比如立方阶,指数阶等。若两个算法的执行时间分别为O(1)和O(n),当n充分大时,显然O(1)的执行时间更少,同样O(n²)和O(lgn)相比,当n充分大时,则O(lgn)对应的算法速度要快得多
①时间复杂度为O(1)的简单语句
S=10;
该语句的执行时间是一个常量,时间复杂度为O(1)
②时间复杂度为O(n)的单重循环
int n=100,sum =10;
for(int i =0,i<n;i++)
sum+=a[i];
该for语句循环体内语句的执行时间是常量,共循环执行n次,所以时间复杂度为O(n)
③时间复杂度为O(n²)的二重循环
int n=100;
for(int i=0;i<n;i++)
for(int j=0,j<n,j++)
console.Write(j*j);
外层循环执行n次,每执行一次外层循环,内层循环执行n次,所以二重循环中的循环体语句被执行了n*n次,时间复杂度为O(n²)
2)算法的空间复杂度
算法的执行除了需要存储空间来寄存本身所用指令、变量和输入数据外,也需要一些对数据进行操作的工作单元和存储一些为实现算法所需的辅助空间。
算法的空间复杂度(space complexity)主要着眼于算法所需辅助内存空间与待处理的数据量之间的关系,也用O(f(n))来表示。
例如分析某个排序算法的空间复杂度,就是要确定该算法执行中所需附加的内存空间与待排序数据序列的长度之间的关系