第1章 绪论
@(教材_数据结构【C】)[2023-11-4pm, C语言]
1.1 什么是数据结构
计算机解决一个具体问题,一般的大致步骤如下:
- 从一个具体问题,
抽象
出一个适当的数学模型;设计
一个解此数学模型的算法;编制
程序,进行测试、调整,直至得到最终解答。
寻求数学模型的实质是分析问题,从中提取操作的对象,并找出这些操作对象之间含有的关系,然后用数学的语言加以描述。 有些模型可以用数学方程描述。然而,更多的非数值计算问题,无法用数学方程加以描述。 这就是数据结构研究的对象。有线性、“树”型、“图”型等。
简单说:数据结构是一门研究非数值计算
的程序设计问题中,计算机的操作对象,以及它们之间的关系等的学科。
从抽象数据类型
的观点来讨论数据结构
,已成为一种新的趋势。
1.2 基本概念和术语
- 数据(
data
): 是对客观事物的符号表示(计算机程序加工的原料
)。 - 数据元素(
data elecment
): 数据的基本单位。一个数据元素可由若干个 数据项(data item
)组成,数据项是数据不可分割的最小单位。 - 数据对象(
data objiect
):是性质相同的数据元素的集合,是数据的一个子集。 - 数据结构(
data structure
):是相互之间存在一种或多种特定关系的数据元素的集合。这种数据元素相互之间的关系称为结构(structure
)。4类基本结构:
(1)集合:结构中的数据元素之间除了“同属于一个集合”的关系外,别无其他关系;
(2)线性结构:结构中的数据元素之间存在一个对一个的关系;
(3)树形结构:结构中的数据元素之间存在着一个对多个的关系;
(4)图状结构或网状结构:结构中的数据元素之间存在多个对多个的关系。
数据结构的形式定义为:数据结构是一个二元组
Data_Structure = (D,S)
其中:D是数据元素的有限集,S是D上关系的有限集。
逻辑结构:描述的是数据元素之间的逻辑关系。
物理结构(又称存储结构):数据结构在计算机中的表示(又称映像)。
数据元素之间的关系在计算机中有两种不同的表示方法:顺序映像和非顺序映像,得出两种不同的存储结构:顺序存储结构和链式存储结构。
数据类型(data type):是一个值的集合
和定义在这个值集上的一组操作
的总称。
按值的不同属性,数据类型分为原子类型
和结构类型
。数据结构可以看成是“一组具有相同结构的值”。
抽象数据类型(Abstract Data Type,简称ADT):是指一个数学模型以及定义在该模型上的一组操作。仅取决于它的一组逻辑特性,与计算机内部无关。
抽象的意义在于数据类型的数学抽象特性。
近代程序设计方法学中指出:一个软件系统的框架应建立在数据之上,而不是建立在操作之上(后者是传统的软件设计方法所为)。
所定义的数据抽象层次越高,含有该抽象数据类型的软件模块的复用程度就越高。
一个含抽象数据类型
的软件模块通常应包括定义
、表示
和实现
3个部分。
抽象数据类型值可细分3种类型:
- 原子类型
- 固定聚合类型
- 可变聚合类型
后两种统称为结构类型
抽象数据类型可用三元组表示: (D, S, P)
D 是数据对象;
S 是D上的关系集;
P 是对D的基本操作集。
抽象数据类型定义格式:
ADT 抽象数据类型名{
数据对象:<数据对象的定义>
数据关系:<数据关系的定义>
基本操作:<基本操作的定义>
}ADT 抽象数据类型名
例1-6 抽象数据类型三元组的定义:
ADT Triplet{
数据对象:D = {e1, e2, e3|e1, e2, e3∈ElemSet(定义了关系运算的某个集合)}
数据关系:R1 = {<e1, e2> , <e2, e3>}
基本操作:
InitTriplet(&T, v1, v2, v3)
操作结果:构造了三元组T,元素e1, e2, e3分别被赋以参数v1, v2和v3的值。
DestroyTriplet(&T)
操作结果:三元组T被销毁。
Get(T, i,&e)
初始条件:三元组T已存在,1≦i≦3。
操作结果:用e返回T的第i元值。
Put(&T, i,e)
初始条件: 三元组T已存在,1≦i≦3。
操作结果:改变T的第i元的值为e。
IsAscending(T)
初始条件: 三元组T已存在。
操作结果:如果T的3个元素按升序排列,则返回1,否则返回0.
IsDescending(T)
初始条件: 三元组T已存在。
操作结果:如果T的3个元素按降序排列,则返回1,否则返回0.
Max(T, &e)
初始条件: 三元组T已存在。
操作结果:用e返回T的3个元素中的最大值。
Min(T, &e)
初始条件: 三元组T已存在。
操作结果:用e返回T的3个元素中的最小值。
}ADT Triplet
多形数据类型:是指其值的成分不确定的数据类型。从抽象数据类型的角度看,具有相同的数学抽象特性,故称之为多形数据类型
。
1.3 抽象数据类型的表示与实现
本书采用伪码和类C语言作为描述工具。
1) 预定义常量和类型:
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
// Status 是函数的类型,其值是函数结果状态代码
typedef int Status;
2) 数据结构的表示(存储结构)用类型定义(typedef
)描述。数据元素类型约定为ElemType
,有用户在使用该数据类型时自行定义。
3) 基本操作的算法都用以下形式的函数描述:
函数类型 函数名(函数参数表){
//算法说明
语句序列
} // 函数名
注:一般地,
- a、b、c、d、e等用作数据元素名;
- i、j、k、l、m、n等用作整形变量名;
- p、q、r等用作指针变量名。
- 函数返回值为函数结果状态代码时,函数定义为
Status
类型。 - 形参表中,"&"打头的参数即为引用参数。
4) 赋值语句
5) 选择语句
6)循环语句
7)结束语句
8)输入和输出语句
9)注释
10)基本函数有:
- 求最大值:max(表达式1,…,表达式n)
- 求最小值:min(表达式1,…,表达式n)
- 求绝对值:abs(表达式)
- 求不足整数值:floor(表达式)
- 求进位整数值:cell(表达式)
- 判定文件结束:eof(文件变量)或 eof
- 判定行结束: eoln(文件变量)或eoln
11)逻辑运算约定
例1-7 抽象数据类型Triplet
的表示和实现。
// --采用动态分配的顺序存储结构----
typedef ElemType * Triplet; // 由InitTriplet分配3个元素存储空间
// --基本操作的函数原型说明-----
Status InitTriplet(Triplet &T, ElemType v1, ElemType v2, ElemType v3);
// 操作结果:构造了三元组T,元素e1,e2和e3分别被赋以参数v1,v2和v3的值。
Status DestroyTriplet(Triplet &T);
// 操作结果:三元组T被销毁。
Status Get(Triplet T, int i, ElemType &e);
// 初始条件:三元组T已存在, 1≤i≤3。
// 操作结果:用e返回T的第i个值。
Status Put(Triplet &T, int i, ElemType e);
// 初始条件:三元组T已存在, 1≤i≤3。
// 操作结果:改变T的第i元的值为e。
Status IsAscending(Triplet T);
// 初始条件:三元组T已存在。
// 操作结果:如果T的3个元素按升序排列,则返回1,否则返回0。
Status IsDescending(Triplet T);
// 初始条件:三元组T已存在。
// 操作结果:如果T的3个元素按降序排列,则返回1,否则返回0。
Status Max(Triplet T, ElemType &e);
// 初始条件:三元组T已存在。
// 操作结果:用e返回T的3个元素中的最大值。
Status Min(Triplet T, ElemType &e);
// 初始条件:三元组T已存在。
// 操作结果:用e返回T的3个元素中的最小值。
//-- 基本操作的实现 -----
Status InitTriplet(Triplet &T, ElemType v1, ElemType v2, ElemType v3) {
// 构造三元组T,依次置T的3个元素的初值为v1,v2和v3。
T = (ElemType *)malloc(3 * sizeof(ElemType)); // 分配3个元素的存储空间
if (!T) exit(OVERFLOW); // 分配存储空间失败
T[0] = v1; T[1] = v2; T[2] = v3;
return OK;
} // InitTriplet
Status DestroyTriplet(Triplet &T){
// 销毁三元组T。
free(T); T = NULL;
return OK;
} // DestroyTriplet
Status Get(Triplet T, int i, ElemType &e){
// 1≤i≤3, 用e返回T的第i元的值。
if (i<1 || i>3) return ERROR;
e = T[i-1];
return OK;
} // Get
Status Put(Triplet &T, int i, ElemType e){
\\ 1≤i≤3, 置T的第i元的值为e。
if (i<1 || i>3) return ERROR;
T[i-1] = e;
return OK;
} // Put
Status IsAscending(Triplet T){
\\ 如果T的3个元素按升序排列,则返回1,否则返回0。
return (T[0] <= T[1]) && (T[1] <= T[2]);
} // IsAscending
Status IsDescending(Triplet T){
// 如果T的3个元素按降序排列,则返回1,否则返回0。
return (T[0] >= T[1]) && (T[1] >= T[2]);
} // IsDescending
Status Max(Triplet T, ElemType &e){
\\ 用e返回指向T的最大元素的值。
e = (T[0] >= T[1]) ? ((T[0] >= T[2]) ? T[0] : T[2]) : ((T[1] >= T[2] ? T[1] : T[2]));
return OK;
} // Max
Status Min(Triplet T, ElemType &e){
\\ 用e返回指向T的最小元素的值。
e = (T[0] <= T[1]) ? ((T[0] <= T[2]) ? T[0] : T[2]) : ((T[1] <= T[2] ? T[1] : T[2]));
return OK;
} // Min
1.4 算法和算法分析
1.4.1 算法
算法(algorithm
)是对特定问题求解步骤的一个描述,它是指令的有限序列,其中每一条指令表示一个或多个操作;此外,算法还具有下列5个重要特性:
- 有穷性
- 确定性
- 可行性
- 输入
- 输出
1.4.2 算法设计的要求
- 正确性
大体分4个层次:
a. 程序不含语法错误;
b. 程序对几组输入数据
能够得出想要的结果;
c. 程序对精心选择的典型、苛刻而带有刁难性
的几组输入数据能够出要求的结果;
d. 程序对一切合法
的输入数据能产生要求的结果。
注:一般达到c条即可
。 - 可读性
- 健壮性
- 效率与低存储量需求
1.4.3 算法效率的度量
时间复杂度
1.4.4 算法的存储空间需求
空间复杂度