目录
前言
下学期专业有这门课,听说这门课很抽象也很重要,所以先大致过一遍有个了解。课程跟着b站的数据结构与算法基础(青岛大学-王卓)走的。
1.数据结构基本概念
1.1 研究内容
数据结构是一门研究非数值计算的程序设计中计算机的操作对象以及他们之间的关系和操作的学科。主要研究非数值计算中数据的逻辑结构、存储结构以及数据之间的关系,以便对数据进行运算和操作。数学模型不是方程而是表、树、图。
主要内容:
对具体问题的处理步骤:
1.具体问题抽象为数学模型
(实质:提取操作对象 找出之间关系 用数学语言描述 即数据结构)
2.算法
3.编译
1.2 基本概念和术语
概念小结:
1.2.1 数据诸类
数据:数值型、非数值型(图、表)
数据元素:数据基本单位。又称记录、结点(人机对弈问题的格局)、顶点(导航问题)。与数据的关系:集合的个体
数据项:构成数据元素的不可分割的最小单位。
数据对象: 性质相同的数据元素的集合,是数据的子集。与数据的关系:集合的子集
1.2.2 数据结构
数据结构:数据元素之间的关系
内容包括:
数据结构的两个层次:
逻辑结构种类:(逻辑关系)
划分方式一:
对于线性结构只有一个直接前驱和后继,但树结构:
- 前驱节点最多只有1个,可以有0个(根节点)、1个(非根节点/父节点)
- 后继节点可以有0个(叶子结点)、1个或多个(非叶子节点)
对于图结构:
- 前驱节点个数可以是0个或多个
- 后继节点个数也可以是0个或多个
- 其数目根据图的连通状态而变化,没有固定
划分方式二:
存储结构(四种基本的):数据结构在计算机中的表示
顺序存储结构:
链接存储结构:存储每一个元素本身的同时还存储了下一个元素的地址
指针是直接包含变量内存地址的数据类型,可以将其视为内存地址的别名
索引存储结构:索引表(联系人按首字母分)
散列存储结构:根据结点的关键字直接计算该节点的储存方式。
1.2.3 数据类型和抽象数据类型
数据类型隐性规定了数据的取值范围、该进行什么操作。
数据类型:
抽象数据类型:有固定的定义格式
基本操作部分的格式定义:(下文所说的操作完成皆指基本操作部分)
参数表:
- 赋值参数:只为操作提供输入值
- 引用参数:&开头,除可提供输入值外,还返回操作结果
初始条件:
- 描述操作执行前数据结构和参数应满足的条件
- 不满足则操作失败,返回相应出错信息
- 初始条件为空则省略
操作结果:
- 说明操作正常完成后,数据结构的变化状况和应返回的结果
(a=3,如果你只是把a传进进行加减运算的函数,那么a的值不会改变,但是如果你传的是&a,那a的值就会改变。
学过面向对象的直接忽略&C看成构造函数即可)
下面这些都只是定义,后续用代码具体实现:
1.3 抽象数据类型的表示与实现
代码实现复数加减:
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
void minus(Complex * A, float real, float imag);
void assign(Complex * A, float real, float imag){
A->realpart = real;
A->imagpart = imag;
}
//->前面只能加对象的指针,"."前面只能加对象名,他们后面都是加变量
void add(Complex * C, Complex A, Complex B){//返回
C->realpart = A.realpart + B.realpart; //实部相加
C->imagpart = A.realpart + B.imagpart; //虚部相加
}
#include <stdio.h>
int main()
{
Complex z1,z2,z3,z4,z;
// 函数调用加&
assign(&z1,8.0,6.0);
assign(&z2,4.0,3.0);
add(&z3,z1,z2);
printf("%f", z3.imagpart);
}
1.4 算法和算法分析
算法:对特定问题求解方法和步骤的描述,是指令的有限序列。其中每个指令表示一个或多个操作。
算法的描述:
- 自然语言:中英文
- 流程图:传统流程图(高中那种)、NS流程图
- 伪代码:类语言:类C语言
- 程序代码:C、Java
算法特性:必须具备的五个特性
- 有穷性
- 确定性:每条指令在任何条件下只有唯一的执行路径
- 可行性:算法可执行
- 输入:一个算法有零个或多个输入
- 输出:一个算法有一个或多个输出
算法设计要求:
- 正确性、可读性、健壮性、高效性(要求花费尽量少的时间和尽量低的存储要求)
算法分析:主要通过算法效率高低评判不同算法优劣
- 时间效率:算法所耗费的时间
- 空间效率:算法执行过程中所消耗的储存空间
- 二者有时候是矛盾的
算法时间效率的度量:可依据算法编制的程序在计算机上所消耗的时间来度量。
- 事后统计:将算法先实现,测算时间和空间开销。 缺点:编写程序耗时耗精力;结果也依赖于软硬件等环境因素,掩盖算法本身的优劣。
- 事前分析:对算法的估算(常用此方法)
因每条语句执行时间与算法本身无关,只依赖于软硬件,故直接假设执行每条语句所需时间均为单位时间,所以算法运行时间即为该算法所有语句频度之和。
每一次缩进比上一次减少一次运行次数,同一循环下嵌套循环其次数加一。第一个运行n+1次才判断不满足条件。为方便比较,仅比较数量级(抓大头)。下面引入算法的渐进时间复杂度。即常数C是T/f的极限。
根据算法时间复杂度定义要考虑:如何找到基本语句(如下)和问题规模:
基于上判断算法时间复杂度步骤:
算法中基本语句的执行次数还随问题的输入不同而变化,所以要考虑最坏时间复杂度、平均时间复杂度、最好时间复杂度:
复杂算法可按加法和乘法规则进行分解计算:
算法时间效率的比较:
空间复杂度:算法所需存储空间的度量
t是一个常数变量所以一次只能存储一个值,不管循环多少次都只能存储1个值,所以是1阶,b数组随着for循环的递增存储了n个值,所以是n阶。故算法一的空间复杂度低。