- 数据结构与算法初识
1.1数据结构研究的内容
如果要提高数据处理的效率,就必须研究数据本身的特性、数据之间的关系,以及如何有效地将数据组织存储在计算机内。
用计算机解决具体问题大概需要下列几个步骤:
- 从具体问题抽象出一个数学模型;
- 设计一个解决此数学模型的算法;
- 编写程序,运行并调试,直至最终解答。
寻求数学模型的实质是分析问题,从中提取操作的对象,并找出这些操作对象之间含有的关系,然后用数学的语言加以描述。
但有些问题是无法用数学方程式来表达的,这些问题称为非数值计算问题。例如:用计算机管理员工信息(模型——线性表)、球赛对阵形势(模型——树)、旅游路线(模型——图)。
1.2数据结构的定义
数据结构:一门研究非数值计算程序设计问题中计算机的操作对象以及它们之间的关系和操作等的学科。
1.2.1基本概念
(1)数据
数据(Date)是客观事物的符号表示,是所有能被输入到计算机中,且能被计算机处理的符号(数字、字符等)的集合,是计算机操作对象的总称。
其为计算机处理的信息的某种特定的符号表示形式。
数据的集合表示:数据={x|x是计算机操作的对象}
(2)数据元素
数据元素是数据的“基本单位”,也称为元素、记录等。
数据元素可分为两类:1、不可分割的“原子”型数据元素:如整形“5”等;
2、多个数据项构成的数据元素。
数据项是数据不可分割的最小标识单位。
(3)数据对象
数据对象是性质相同的数据元素的集合,是数据的一个子集。
例如:整数数据对象集合:N={0,1,2,…};
字母字符数据对象集合:C={‘A’,’B’,…’Z’}.
- 数据结构
数据结构是相互之间存在一种或多种特定关系的数据元素的集合。
数据元素集合相同,而其上的关系不同,则构成的数据结构不同。
数据结构是一个二元组DS=(D,R),D是数据元素的有限集,R是D上关系的有限集
关系的表示:序偶:有序对。例如:<班主任,班长1>
前驱:序偶中第一元素为第二元素的前驱。
后继:序偶中第二元素为第一元素的后继。
数据结构:数据的逻辑结构
数据的存储结构
数据的运算
1.3逻辑结构与存储结构
逻辑结构与存储结构的关系:
- 同一逻辑结构可以对应多种存储结构。
- 同样的运算,在不同的存储结构中,其实现过程是不同的。
研究每一种具体的数据结构的步骤:
- 理解其逻辑结构;
- 设计出对应的有利于解决问题的存储结构;
- 再次存储结构的基础上,设计出相应的一系列运算以解决问题。
1.3.1数据的逻辑结构
逻辑结构是对数据元素之间存在的逻辑关系的描述。
逻辑结构可以用一个数据元素的集合和定义在此集合上的若干关系表示。
数据的逻辑结构可看作是从具体问题抽象出来的数学模型。
常见的逻辑结构:
1.3.2数据的存储结构
数据元素及其关系在计算机内的表示。
逻辑结构可以映射为一下四种存储结构:
(1)顺序存储结构:顺序存储是把逻辑上相邻的数据元素存储在物理位置也是相邻的存储单元中,借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系。
(2)链式存储结构:链式存储借助指针来表达数据元素间的逻辑关系。不要求逻辑上相邻的数据元素在物理位置上也相邻。
(3)索引存储结构
(4)哈希(散列)存储结构
1.3.3数据的运算
数据运算是指对数据实施的操作,例如:检索、插入、删除、更新和排序等。
数据运算最终需要在对应的存储结构上用算法实现。
数据的运算分为两个层面:
- 运算定义:是基于逻辑结构的,是抽象的;
- 运算实现:是基于存储结构的,是具体的。
1.4抽象数据类型
抽象数据类型是指数据元素集合以及定义在该集合上的一组操作,简称ADT(Abstract Data Type)。“抽象”指与具体实现无关,仅考虑能做什么,而不考虑如何做。
ADT=(D,R,P)
其中D是指数据对象,R是D上的关系集,P是D的基本操作集。
数据抽象:用ADT描述程序处理的实体时,强调的是其本质的特征、其所能完成的功能以及它和外部用户的接口(即外界使用它的方法)。
数据封装:将实体的外部特性和其内部实现细节分离,并且对外部用户隐藏其内部实现细节。
抽象数据类型的实现:
面向对象——类(class),如C++、Java)
面向过程——结构体(struct),如C语言
示例:矩形ADT
1.5算法的定义与特性
1、算法的定义
程序=数据结构+算法
算法就是求解问题的一系列步骤的集合,通常把具体存储结构上的炒作实现步骤或过程称为算法。
2、算法的特性
(1)有穷性:对于任意一组合法的输入值,在执行有穷步骤之后一定能结束。
(2)确定性:每条指令必须有确切的含义,不能有二义性。
(3)可行性:算法中描述的操作都是用已经实现的基本运算组成。、
(4)输入:可以有零个或多个输入。
(5)输出:一组与“输入”有确定关系的量值。有一个或多个输出
3、算法的评价(设计准则)
(1)正确性:能正确执行预定的功能。
(2)可使用性:方便使用,用户友好性。
(3)可读性:易于理解,逻辑清晰。
(4)健壮性:具有很好的容错性。能提供异常处理,不容易出现崩溃。
(5)高效性:执行时间短(时间效率)、占用存储空间少(空间效率)。
1.6时间复杂度
1、算法的频度
一般用算法中语句被执行的次数(频度)来表示算法的时间效率
例如下面程序的频度:
int i,sum-0; (1次)
for ( i=0;i<n;i++) (n+1次)
sum=sum+I; (n次)
return sum; (1次)
T(n)=2n+3,且T(n)是n数量级的。
2、(渐进)时间复杂度
忽略次要语句的执行次数,只对重要的语句(原操作)和执行最频繁的语句进行计数,同时对计算结果只取其最高次幂,且略去系数不写。
渐进时间复杂度常简称为时间复杂度,用大O表示。
T(n)=2n+3=O(n)
其既可以简化T(n)的计算,又能比较客观地反映出当n很大时,算法的时间性能。
例如:T(n)=3n²-5n+10000=O(n²)