数据结构-绪论

绪论

数据结构的研究内容

通常,用计算机解决一个问题的步骤:

  1. 具体问题抽象为数学模型

    实质:

    • 分析问题
    • 提取操作对象
    • 找出操作对象之间的关系
    • 用数学语言描述 => 数据结构
  2. 设计算法

  3. 编程、调试、运行

早期,计算机主要用于数值计算,其特点为:数据元素间的关系简单,计算复杂

随着计算机应用领域的拓展,计算机被越来越多的用于非数值计算

描述非数值计算问题的数学模型不是数学方程,而是诸如表、树和图之类的具有逻辑关系的数据

数据结构是一门研究非数值计算的程序设计中计算机的操作对象以及他们之间的关系和操作的学科


基本概念和术语

  1. 数据

    • 是能输入计算机且能被计算机处理的各种符号的集合
      • 信息的载体
      • 是对客观事物符号化的表示
      • 能够被计算机识别、存储和加工
    • 包括:
      • 数值型的数据:整数、实数等
      • 非数值型的数据:文字、图像、图像和声音等
  2. 数据元素

    • 是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。
    • 也简称为元素,或称为记录、结点或顶点。
    • 一个数据元素可由若干个数据项组成
  3. 数据项

    • 构成数据元素的不可分割的最小单位

    • 数据、数据元素、数据项三者之间的关系:

      数据 > 数据元素 > 数据项

  4. 数据对象

    • 性质相同的数据元素的集合,是数据的一个子集

数据结构

  • 数据结构包括以下三个方面的内容:

    1. 数据元素之间的逻辑关系,也称为逻辑结构。
    2. 数据元素及其关系在计算机内存中的表示(又称为映像),称为数据的物理结构或数据的存储结构
    3. 数据的运算和实现,即对数据元素可以施加的操作以及这些操作在相应的存储结构上的实现
  • 数据结构的两个层次

    • 逻辑结构
      • 描述数据元素之间的逻辑关系
      • 与数据的存储无关,独立于计算机
      • 是从具体问题抽象出来的数学模型
    • 物理结构(存储结构)
      • 数据元素及其关系在计算机存储器中的结构(存储方式)
      • 是数据结构在计算机中的表示
    • 逻辑结构与存储结构的关系:
      • 存储结构是逻辑关系的映像与元素本身的映像。
      • 逻辑结构是数据结构的抽象,存储结构是数据结构的实现
      • 两者综合起来建立了数据元素之间的结构关系
  • 逻辑结构的种类

    划分方法一

    1. 线性结构

      有且仅有一个开始和一个终端结点,并且所有结点都最多只有一个直接前趋和一个直接后继。

      例如:线性表、栈、队列、串

    2. 非线性结构

      一个结点可能有多个直接前趋和直接后继

      例如:树、图

    划分方式二——四类基本逻辑结构

    1. 集合结构:结构中的数据元素之间除了同属于一个集合的关系外,无任何其它关系。
    2. 线性结构:结构中的数据元素之间存在着一对一的线性关系。
    3. 树形结构:结构中的数据元素之间存在着一对多的层次关系。
    4. 图状结构网状结构:结构中的数据元素之间存在着多对多的任意关系。
  • 存储结构的种类

    四种基本的存储结构:

    • 顺序存储结构

      用一组连续的存储单元依次存储数据元素,数据元素之间的逻辑关系由元素的存储位置来表示。

      C语言中用数组来实现顺序存储结构

    • 链式存储结构

      用一组任意的存储单元存储数据元素,数据元素之间的逻辑关系用指针来表示。

      C语言中用指针来实现链式存储结构

    • 索引存储结构

      在存储结点信息的同时,还建立附加的索引表

    • 散列存储结构

      根据结点的关键字直接计算出该结点的存储地址

数据类型和抽象数据类型

一些最基本数据结构可以用数据类型来实现,如数组、字符串等;

而另一些常用的数据结构,如栈、队列、树、图等,不能直接用数据类型来表示。

数据类型的作用:

  • 约束变量或常量的取值范围
  • 约束变量或常量的操作

数据类型:数据类型是一组性质相同的值的集合以及定义于这个值集合上的一组操作的总称。

​ 数据类型=值的集合+值集合上的一组操作

抽象数据类型(ADT):是指一个数学模型以及定义在此数学模型上的一组操作

​ 由用户定义,从问题抽象出数据模型(逻辑结构)

​ 还包括定义在数据模型上的一组抽象运算(相关操作)

​ 不考虑计算机内的具体存储结构与运算的具体实现算法

抽象数据类型的形式定义

​ 抽象数据类型可用(D,S,P)三元组表示。其中:D是数据对象、S是D上的关系集、P是对D的基本操作集。

​ 一个抽象数据类型的定义格式如下:

ADT 抽象数据类型名{
	数据对象:<数据对象的定义>
	数据关系:<数据关系的定义>
	基本操作:<基本操作的定义>
} ADT 抽象数据类型名

​ 其中:数据对象、数据关系的定义用伪代码描述;

​ 基本操作的定义格式为:

​ 基本操作名(参数表)

​ 初始条件:<初始条件描述>

​ 操作结果:<操作结果描述>

基本操作定义格式说明:

参数表:赋值参数 只为操作提供输入值。

​ 引用参数 以&打头,除可提供输入值外,还将返回操作结果。

初始条件:描述操作执行之前数据结构和参数应满足的条件,若不满足,则操作失败,并返回相应出错信息。若初始条 件为空,则省略之。

操作结果:说明操作正常完成之后,数据结构的变化状况和应返回的结果。

抽象数据类型的表示与实现

抽象数据类型如何实现

抽象数据类型可以通过固有的数据类型(如整型、实型、字符型等)来表示和实现。即利用处理器中已存在的数据类型来说明新的结构,用已经实现的操作来组合新的操作。

用C语言真正实现抽象数据类型的定义

例如:抽象数据类型“复数”的实现

typedef struct{
    float realpart; /* 实部 */
    float imagpart; /* 虚部 */
}Complex	/* 定义复数抽象类型 */
    
void assign(Complex *A,float real, float imag); /* 赋值 */
void add(Complex *A,float real, float imag); /* A+B */
...

算法和算法分析

算法

  • 算法的定义

    • 对特定问题求解方法和步骤的一种描述,它是指令的有限序列。其中每个指令表示一个或多个操作。

      简而言之,算法就是解决问题的方法和步骤

  • 算法的描述

    • 自然语言:英语、中文
    • 流程图:传统流程图、NS流程图
    • 伪代码:类语言:类C语言
    • 程序代码:C语言程序、JAVA语言程序…
  • 算法与程序

    • 算法是解决问题的一种方法或一个过程,考虑如何将输入转换成输出,一个问题可以有多种算法。
    • 程序是用某种程序设计语言对算法的具体实现。
  • **算法特性:一个算法必须具备以下五个重要特性 **

    • 有穷性:一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成。
    • 确定性:算法中的每一条指令必须有确切的含义,没有二义性,在任何条件下,只有唯一的一条执行路径,即对于相同的输入只能得到相同的输出。
    • 可行性:算法是可执行的,算法描述的操作可以通过已经实现的基本操作执行有限次来实现。
    • 输入:一个算法有零个或多个输入。
    • 输出:一个算法有一个或多个输出。
  • 算法设计的要求

    • 正确性:算法满足问题要求,能正确解决问题

      算法转化为程序后要注意:

      1. 程序中不含语法错误
      2. 程序对于几组输入数据能够得出满足要求的结果;
      3. 程序对于精心选择的、典型、苛刻且带有刁难性的几组输入数据能够得出满足要求的结果;
      4. 程序对于一切合法的输入数据都能得出满足要求的结果。

      通过以第三层意义上的正确性作为衡量一个算法是否合格的标准

    • 可读性

      1. 算法主要是为了人的阅读和交流,其次才是为计算机执行,因此算法应该易于人的理解;
      2. 另一方面,晦涩难读的算法易于隐藏较多错误而难以调试。
    • 健壮性

      1. 指当输入非法数据时,算法恰当的做出反应或进行相应处理,而不是产生莫名其妙的输出结果。
      2. 处理出错的方法,不应是中断程序的执行,而应是返回一个表示错误或错误性质的值,以便在更高的抽象层次上进行处理
    • 高效性

      要求花费尽量少的时间和尽量低的存储需求

算法分析

算法分析的目的是看算法实际是否可行,并在同一问题存在多的算法时可进行性能上的比较,以便从中挑选出比较优的算法。

一个好的算法首先要具备正确性,然后是健壮性,可读性,在几个方面都满足的情况下,主要考虑算法的效率,通过算法的效率高低来评判不同算法的优劣程度。

算法效率以下两个方面来考虑:

  1. 时间效率:指的是算法所耗费的时间
  2. 空间效率:指的是算法执行过程中所耗费的存储空间

时间效率和空间效率有时候是矛盾的。

  • 算法时间效率的度量

    • 算法时间效率可以用依据该算法编制的程序在计算机上执行所消耗的时间来度量。
    • 两种度量方法
      • 事后统计
        • 将算法实现,测算其时间和空间开销。
        • 缺点:编写程序实现算法将花费较多的时间和精力;所得实验结果依赖于计算机的软硬件等环境因素,掩盖算法本身的优劣
      • 事前分析
        • 对算法所消耗资源的一种估算方法。
  • 事前分析方法:

    • 一个算法的运行时间是指一个算法在计算机上运行所耗费的时间大致可以等于计算机执行一种简单的操作(如赋值、比较、移动等)所需的时间与算法中进行的简单操作**次数乘积 **。

      算法运行时间=一个简单操作所需的时间×简单操作次数

      也即算法中每条语句的执行时间之和

      算法运行时间=Σ每条语句的执行次数×该语句执行一次所需的时间

      算法运行时间=Σ每条语句频度×该语句执行一次所需的时间

    • 算法时间复杂度的渐进表示法

      • 为了便于比较不同算法的时间效率,我们仅比较它们的数量级
      • 若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n))为算法的渐进时间复杂度(O是数量级的符号),简称时间复杂度
      • 一般情况下,不必计算所有操作的执行次数,而只考虑算法中基本操作执行的次数,它是问题规模n的某个函数,用T(n)表示。
      • 基本语句:算法中重复执行次数和算法的执行时间成正比的语句;对算法运行时间的贡献最大;执行次数最多
      • 问题规模n:
        • 排序:n为记录数
        • 矩阵:n为矩阵的阶数
        • 多项式:n为多项式的项数
        • 集合:n为元素个数
        • 树:n为树的结点个数
        • 图:n为图的顶点数或边数
  • 分析算法时间复杂度的基本方法

    定理1.1
    若 f ( n ) = a m n m + a m − 1 n m − 1 + . . . + a 1 n + a 0 是 m 次多项式,则 T ( n ) = O ( n m ) 若f(n)=a_mn^m+a_{m-1}n^{m-1}+...+a_1n+a_0是m次多项式,则T(n)=O(n^m) f(n)=amnm+am1nm1+...+a1n+a0m次多项式,则T(n)=O(nm)

    1. 找出语句频度最大的那条语句作为基本语句
    2. 计算基本语句的频度得到问题规模n的某个函数f(n)
    3. 取其数量级用符号“O”表示

    时间复杂度是由嵌套最深层语句的频度决定的

  • 算法时间复杂度

    请注意:有的情况下,算法中基本操作重复执行的次数还随问题的输入数据集不同而不同

    • **最坏时间复杂度:**指在最坏情况下,算法的时间复杂度。
    • **平均时间复杂度:**指在所有可能输入实例在等概率出现的情况下,算法的期望运行时间。
    • **最好时间复杂度:**指在最好情况下,算法的时间复杂度。

    一般总是考虑在最坏情况下的时间复杂度,以保证算法的运行时间不会比它更长。

    对于复杂的算法,可以将它分成几个容易估算的部分,然后利用大O加法法则和乘法法则,计算算法的时间复杂度:

    • 加法规则
      T ( n ) = T 1 ( n ) + T 2 ( n ) = O ( f ( n ) ) + O ( g ( n ) ) = O ( m a x ( f ( n ) , g ( n ) ) ) T(n)=T1(n)+T2(n)=O(f(n))+O(g(n))=O(max(f(n),g(n))) T(n)=T1(n)+T2(n)=O(f(n))+O(g(n))=O(max(f(n),g(n)))

    • 乘法规则
      T ( n ) = T 1 ( n ) × T 2 ( n ) = O ( f ( n ) ) × O ( g ( n ) ) = O ( f ( n ) × g ( n ) ) T(n)=T1(n)×T2(n)=O(f(n))×O(g(n))=O(f(n)×g(n)) T(n)=T1(n)×T2(n)=O(f(n))×O(g(n))=O(f(n)×g(n))

    当n取得很大时,指数时间算法和多项式时间算法在所需时间上非常悬殊

    时间复杂度T(n)按数量级递增顺序为:

    常数阶 对数阶 线性阶 线性对数阶 平方阶 立方阶 k次方阶 指数阶
    O(1) O(log_2 n) O(n) O(n log_2 n) O(n^2) O(n^3) O(n^k) O(2^n)
  • 渐进空间复杂度

    空间复杂度:算法所需存储空间的度量,记作:S(n)=O(f(n)),其中n为问题的规模(或大小)

    算法要占据的空间

    • 算法本身要占据的空间,输入/输出,指令,常数,变量等
    • 算法要使用的辅助空间

你可能感兴趣的:(数据结构,数据结构,算法,c++)