1.1 数据结构研究内容
计算机解决问题的步骤:
- 分析具体问题
- 抽象出数据模型
- 设计算法
- 编程、调试
- 结果
抽象的实质:分析问题,从中提取操作对象,找出操作对象之间含有的关系,并用数学语言加以描述
问题可分为两类,一类是数值计算类问题
如:总额为一元的硬币,求1,2,5分硬币各几枚?
另一类是非数值计算类问题
如:“学生”表格
数据结构就是一门研究非数值计算的程序设计问题中计算机所处理对象以及对象之间的关系和操作的学科
算法+数据结构=程序(Pascal之父——Nicklaus Wirth)
1.2 基本概念与术语
数据Data :能输入到计算机中,被计算机程序识别和处理的一切事物的符号化表示。
- 数值性数据:整型数﹑实数
- 非数值性数据:学生信息﹑比赛项目
数据元素Data Element:亦称元素,是构成数据的基本单位
- 数据→集合
- 元素→集合中的一个实例
数据项Data Item:数据元素可细分成由若干数据项(字段)组成,数据项是具有独立含义的最小标识单位
- 学生:学号,姓名,性别,年龄…
数据结构Data Stucture:是相互之间存在一种或多种特定关系的数据元素的集合,由某一数据对象及该对象中所有数据成员之间的关系组成。记为:Data_Structure = {D, R}。其中,D(Data)是某一数据对象,R(Relationship)是该对象中所有数据成员之间的关系的有限集合
逻辑结构Logic Structure:数据之间的逻辑关系-称为数据的逻辑结构,即数据在真实世界中体现出来的关系
研究表明:元素之间必是下列四种逻辑关系之一
- 集合Set
- 线性Liner
- 数Tree
- 图Grahp/网Net
物理结构Physical Structure :数据元素及关系在计算机世界(即内存)中的表示,包括:数据元素的存储﹑元素间关系的表达
2种物理结构:
- 顺序结构:Sequential Structure,也称顺序存储
- 链式结构:Linked Structure,也称链式存储
数据的运算——对数据可施加的操作(运算的实现与物理结构有关)
物理结构Physical Structure:
-
顺序结构Sequential Structure
用一段连续的内存单元依次存放元素
逻辑上相邻的元素所占的内存单元也相邻
以物理位置(即所占内存)的相邻来表示元素在逻辑上的相邻
内存的结构:以顺序结构表示向量[1,2,3] -
链式结构(Linked Structure)
元素所占内存单元可以是任意的
为还原彼此间的逻辑关系,每个元素除自身信息外,还需存放与之具有关系的那个元素的存储位置(即链、指针)
内存的结构:以链式结构表示向量[1,2,3]
逻辑结构 VS 物理结构
数据类型:在高级语言中,是具有相同性质的一组数据值的集合,以及定义于这个值集合上的一组操作的总称
- 原子类型:不可再分,如整型、实型、字符、布尔、指针…
- 结构类型:由原子(或结构)类型组合而成,如字符串、数组、学生、图像…
抽象数据类型Abstract DataTypes:
由用户定义,用以表示应用问题的数据模型及定义在该模型上的一组操作抽象数据类型的定义仅取决于它的逻辑特性,而与其在计算机内部的表示和实现无关
ADT实现示例(C语言):复数
//定义复数类型
typedef struct {
//实部
float real;
//虚部
float image;
}Complex;//类型别名
//初始化操作的实现
void init(Complex* c, float a, float b) {
c->real = a;
c->image = b;
}
1.3算法与性能评价
定义:对特定问题求解步骤的一种描述
特性:
- 有穷性:在有穷步﹑有限合理时间内完成
- 确定性:每步定义是确切﹑无歧义的,不像自然语言
- 可行性:每一条运算应足够基本(所描述的操作可以通过已实现的基本操作实现),例如:被零除的计算动作不能被有效执行
- 输入:有0个或多个输入
- 输出:有一个或多个输出(处理结果)
算法的设计要求(性能标准)
- 正确性:满足具体问题要求
- 可读性:人易读懂(相对)
- 健壮性:对非法数据也能做出反应和处理
- 效率与存储量要求:执行时间﹑空间耗费
- 可修改/可扩展性:如果问题Р的一个算法是A,为了解答一个与Р类似的问题,希望对A稍做改动就可正确运行,如算法A满足这一点,则说A的可修改性好(工程角度)
算法时间复杂度的定义:
在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定了T(n)的数量集。算法的时间复杂度,也就是算法时间量度,记作:T(n) = O(f(n))。它表示问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数
算法空间复杂度的定义:
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))。比如直接插入排序的时间复杂度是O(n2),空间复杂度是O(1) 。而一般的递归算法就要有O(n)的空间复杂度了,因为每次递归都要存储返回信息。一个算法的优劣主要从算法的执行时间和所需要占用的存储空间两个方面衡量。
相对于时间复杂度,为什么不太关注空间复杂度?
- 大多数算法的空间复杂度要么是O(1)——与问题规模无关,要么是O(n)——可优化余地不大(如递归)
- 同一问题的不同算法的时间复杂度往往差异很大,如冒泡排序为O(n2),而归并排序为O(nlogn)
- 大多数情况下,目前的内存容量远超问题规模
- 编译器、运行环境的自动优化,OS的虚拟内存等
- 金钱可以买来更多内存条,但买不来时间
时间复杂度VS空间复杂度
- 有时难以两全,如冒泡排序和归并排序
- 如同代码可读性与可扩展性之间的矛盾
- 牺牲空间换时间,牺牲时间换空间