目录
- 前言
- 一、从问题到程序
- 二、数据结构的研究内容
- 三、理解数据结构
- 3.1 数据
- 3.2 结构
- 3.2.1 逻辑结构的分类
- 3.2.2 存储结构的分类
- 3.3 数据结构
- 四、数据类型和抽象数据类型
- 4.1 抽象数据类型的定义格式
- 4.2 抽象数据类型的实现
- 总结
前言
本篇文章先介绍数据结构的研究内容,然后再介绍如何去理解数据结构,着重介绍表示数据结构关系的逻辑结构和存储结构(物理结构)。
一、从问题到程序
用计算机实现问题求解,实质上就是在计算机中建立一个解决问题的模型。
为一个问题建立一个正确的求解程序,一般经历以下四个阶段:
- 分析阶段
该阶段的任务是,首先是理解用户的需求是什么;然后设计者对用户的需求进行深入分析,使用规范说明语言,给出问题的需求模型。
又或者是通过分析问题,提取操作对象并找出操作对象之间的关系,然后用数学语言描述操作对象之间的关系,最后给出问题的数学模型。 - 设计阶段
该阶段的任务是,设计者建立求解问题的实现模型,重点是数据结构的设计和算法的设计。
一般而言,设计过程需要从粗到细,经过多次精化才能完成。 - 编码阶段
该阶段的任务是,编码人员选择适当的程序设计语言把设计阶段的结果编写成可执行程序。 - 调试和维护阶段
该阶段的任务是,测试人员使用足够的例子调试编写的程序,发现和排除程序代码中的错误;
最后,在计算机上执行程序,获得问题的解。
程序投入使用后,需要解决在使用过程中发现的隐含错误和根据使用中提出的要求进行必要的维护和完善。
使用计算机为实际问题构建求解程序的流程图如图1.1所示。
数据结构的设计处于设计阶段,那数据结构的研究内容是什么呢?
二、数据结构的研究内容
数据结构是一门主要研究非数值计算,然后用计算机表示数据元素以及数据元素之间的关系,最后用计算机实现对数据元素的各种操作的学科。
描述非数值计算问题的数学模型不是数学方程,而是诸如表、树、图等具有逻辑关系的结构。
例子1,学生信息管理系统的一个学生信息表
数据元素:一个学生的信息
数据元素之间的关系:线性结构(逻辑结构)
操作:对一个学生的信息进行查询、修改、增加、删除等操作
例子2,文件系统的目录结构
数据元素:目录
数据元素之间的关系:树形结构(逻辑结构)
操作:对一个目录进行删除、修改、查看、新增等操作
例子3,地图导航
数据元素:地点和边
数据元素之间的关系:图结构(逻辑结构)
操作:寻求两点之间最短路径、寻求两点之间的最短耗时等
以上这些问题,都是无法使用数学公式或数学方程描述的问题,是一些非数值计算的程序设计问题。
数据结构与算法的研究内容如下:
在了解数据结构的研究内容后,请问什么是数据结构?
三、理解数据结构
为了更好的理解数据结构,可以先将其拆分为两部分:数据和结构,最后再进行总体理解。
3.1 数据
- 数据
概念:能够输入计算机且能够被计算机处理的各种符号的集合
例如,在一个学生信息管理系统中,学生信息表就是数据。 - 数据元素
概念:是数据的基本单位,在计算机程序中通常被作为一个整体进行考虑和处理
数据元素简称为元素,也可以称为记录或结点
例如,在一个学生信息管理系统中,学生信息表的一个学生信息就是一个数据元素。 - 数据项
概念:构成数据元素的不可分割的最小单位
例如,在一个学生信息管理系统中,学生信息表的学号字段就是一个数据项。 - 数据对象
概念:是性质相同的数据元素的集合,是数据的一个子集
例如,在一个学生信息管理系统中,学生信息表的同一个专业的学生信息就是一个数据对象。
数据元素与数据对象的关系:
从集合的角度看,把数据当成一个集合
数据元素是数据的一个元素
数据对象是数据的一个子集
3.2 结构
结构可以分为逻辑结构和存储结构(物理结构)
- 逻辑结构:它定义了数学模型中的元素和元素之间的相互关系。
描述数据元素之间的逻辑关系
与数据的存储无关,独立与计算机
是从具体问题抽象出来的数学模型 - 存储结构:它给出了数学模型的具体表示方式,包括元素的表示,元素与元素之间的关系表示。存储结构也可以理解为数据元素、数据元素之间的关系在计算机内存中的表示。
数据元素及其关系在计算机存储器中的结构
是数据结构在计算机中的表示
逻辑结构与存储结构的关系:
逻辑结构是数据结构的抽象
存储结构是数据结构的实现
两者综合起来建立了数据元素之间的结构关系。
3.2.1 逻辑结构的分类
-
集合结构
概念:结构中的数据元素之间除了同属于一个集合的关系外,无任何其他关系
-
线性结构
概念:结构中的数据元素之间存在着一对一的关系
-
树形结构(非线性结构)
概念:结构中的数据元素之间存在着一对多的层次关系
-
图结构(非线性结构)
概念:结构中的数据元素之间存在着多对多的任意关系
各种逻辑结构之间具有以下包含关系:
集合结构 ⊆ 线性结构 ⊆ 树形结构 ⊆ 图结构
3.2.2 存储结构的分类
- 顺序存储结构
用一组连续的存储单元依次存储数据元素,数据元素之间的逻辑关系由元素的存储位置表示 - 链接存储结构
用一组任意的存储单元存储数据元素,数据元素之间的逻辑关系用指针(或引用)表示 - 散列存储结构
又称为关键码-地址转换法
选择适当的散列(杂凑)函数,根据关键码的值将数据元素映射到给定的存储空间(散列表)中 - 索引存储结构
存储结点信息的同时,建立附加的索引表。索引是由索引项组成的结构,每个索引项包含一个结点的关键码和该结点的存储位置
3.3 数据结构
数据结构包含以下三个内容:
1. 数据元素
2. 数据元素之间的关系(包含逻辑结构关系和存储结构关系)
3. 数据元素的运算和操作,即对数据元素可以施加的操作以及这些操作在相应的存储结构上的实现
四、数据类型和抽象数据类型
-
类型(Type)
是一组值(或对象)的集合
例如,布尔作为一种类型是由真(true)和假(false)两个值组成的集合 -
数据类型(Data Type)
是一组性质相同的值的集合以及定义在这个值集合上的一组操作的总称
数据类型=值的集合+值集合上的一组操作 -
抽象数据类型(Abstract Data Type,ADT)
是指一个数学模型以及定义在此数学模型上的一组操作
其抽象掉了数据类型中值的具体表示方式
其抽象掉了数据类型中定义的各种操作的实现算法
抽象数据类型中元素间内在的相互依赖关系称为逻辑结构
不考虑在计算机内的具体存储结构和运算的具体实现算法
4.1 抽象数据类型的定义格式
抽象数据类型可用(D,S,P)三元组表示
D表示数据对象
S是D上的关系集
P是D上的基本操作集
一个抽象数据类型的定义格式如下:
ADT 抽象数据类型名{
数据对象:<数据对象的定义>
数据关系:<数据关系的定义>
基本操作:<基本操作的定义>
}ADT 抽象数据类型名
数据对象和数据关系的定义用伪代码描述
基本操作的定义格式:
基本操作名(参数表)
初始条件:<初始条件描述>
操作结果:<操作结果描述>
基本操作定义格式说明:
参数表说明:
赋值参数只为操作提供输入值
引用参数以&开头,除可为操作提供输入值外,还可作为操作结果返回
初始条件说明:
描述操作执行之前操作对象和参数应满足的条件。若不满足,则操作失败,返回对应出错信息
若初始条件为空,则省略
操作结果说明:
说明操作正常完成之后,操作对象的变化状况和应返回的结果
例如,定义圆的抽象数据类型
ADT Circle{
数据对象:D={r,x,y|r,x,y均为实数}
数据关系:S={<r,x,y>|r是半径,<x,y>是圆心}
基本操作
Circle(&C,r,x,y)
操作结果:构造一个圆
double Area(C)
初始条件:圆C存在
操作结果:计算圆C的面积
double Circumference(C)
初始条件:圆C存在
操作结果:计算圆C的周长
...
}ADT Circle
4.2 抽象数据类型的实现
在4.1小节中,定义了圆的抽象数据类型,现在利用c语言实现
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include<assert.h>
//定义数据类型:圆
struct Circle {
float radius; //圆半径
float x; //圆心x轴坐标
float y; //圆心y轴坐标
};
//类型重命名
typedef struct Circle Circle;
//宏定义PI
#define PI 3.141592
//构造一个圆
Circle* newCircle(float r, float x, float y) {
Circle* circle = (Circle*)malloc(sizeof(Circle));
if (NULL == circle)
{
printf("%s", strerror(errno));
return NULL;
}
printf("circle is build successfully!\n");
circle->radius = r;
circle->x = x;
circle->y = y;
return circle;
}
//计算圆的面积
double area(Circle* circle)
{
assert(circle);
return (circle->radius) * (circle->radius) * PI;
}
//计算圆的周长
double circumference(Circle* circle)
{
assert(circle);
return (circle->radius) * PI * 2;
}
//销毁一个圆
void destroyCircle(Circle* circle)
{
free(circle);
circle = NULL;
printf("circle is destoryed!\n");
}
//测试
int main()
{
Circle* circle = newCircle(3.0,2.0,3.0);
printf("area = %.6lf\n", area(circle));
printf("circumference = %0.6lf\n", circumference(circle));
destroyCircle(circle);
return 0;
}
总结
数据结构是抽象数据类型的物理实现。
数据结构主要应解决的两个问题:一个是选择存储结构,另一个是实现抽象数据类型中的各种操作。