大家好,我是一个编程小白,下面是我看了王卓老师的bi站课程《数据结构》所整理出的一些笔记,分享给需要的小伙伴,免费,希望能够对大家有所帮助,本人只是一个踏踏实实记笔记的人,也开始尝试走上自己的博客之旅,要是能够对你有所帮助我很高兴,如果有什么不足,也请写下你们宝贵的建议,最后也非常感谢大家的观看!
观看建议:我是在语雀记的笔记,大家可以直接复制之后在语雀打开,就可以很方便的查看
第一章
1.1数据结构的研究内容
1.首先看一下电子计算机的主要用途:
早期: 主要用于数值计算
后来: 处理逐渐扩大到非数值计算领域,能处理多种复杂的具有一定结构关系的数据---非数值计算
1.2基本概念和术语
1.21 5个基本概念
1.数据(Data):所有能输入到计算机中去的(且能被计算机处理的)描述客观事物的符号;(能被计算机识别,存储,加工)
1.数值性数据: 整数,实数
2.非数值性数据(多媒体信息处理):文字,图像,图形,声音;
2.数据元素(Data Element):数据的基本单位,也称结点(Node)或记录(Record)或顶点;
3.数据项(Data Item):(构成数据元素不可分割的)有独立含义的数据最小单位,也称域(Field);
三者的关系:数据 > 数据元素 > 数据项
例:学生表 > 一个学生的信息记录 > 学号、姓名……
即:一个用来存储学生信息的链表 > 一个存储学生信息的节点(结果结构体) > 节点中的某一项信息(结构体中的一项数
据)
4.数据对象(Data Object):相同特性数据元素的集合,是数据的一个子集;
例1:整数数据对象。N = { 0, 1, 2, … } ;
例2:学生数据对象,是学生记录的集合;
数据元素与数据对象区别
1.数据元素:组成数据的基本单位,
与数据的关系:是集合的个体
2.数据对象:性质相同的数据元素的集合
与数据的关系:集合的子集
人话:数据当中包含一个一个的数据元素,然后这数据的数据元素其中有一些是性质相同的,所以这些性质相同的就组成了一个集合,叫数据对象
5.数据结构(Data Structure):是相互之间存在一种或多种特定关系的数据元素的集合;(数据元素不是孤立存在的,他们之间存在某种关系,这种关系叫结构)
数据结构是带“结构”的数据元素的集合,“结构”就是指数据元素之间存在的关系。
1.22.数据结构包括以下三个方面的内容
1️⃣数据元素之间的逻辑关系,也称为逻辑结构,
2️⃣数据元素及其关系在计算机构存中的表示(又称为映像),称为数据的物理结构或数据的存储结构。
3️⃣数据的运算和实现,即对数据元素可以施加的操作以及这些操作在相应的存储结构上的实现。
数据结构的两个层次
1.逻辑结构
描述数据元素之间的逻辑关系
与数据的存储无关,独立于计算机
是从具体问题抽象出来的数学模型
2.物理结构(存储结构)
数据元素及其关系在计算机存储器中的结构(存储方式)
是数据结构在许算机中的表示
3.逻辑结构与存储结构的关系
存储结构是逻辑关系的映象与元素本身的映象。
逻辑结构是数据结构的抽象,存储结构是数据结构的实现
两者综合起来建立了数据元素之间的结构并系,
1.23逻辑结构的种类
划分方式一:
1.线性结构:
有且仅有一个开始和一个终端结点,并且所有结点都最多只有一个直接前趋和一个后继;
例如:线性表、栈、队列、串;
2.非线性结构:
一个结点可能有多个直接前趋和直接后继;
例如:树、图;
划分方式二:
集合:数据元素间除“同属于一个集合”外,无其它关系;(数组??)
线性结构:一个对一个,如线性表、栈、队列;
树形结构:一个对多个,如树;
图形结构:多个对多个,如图;
1.24 4种基本的存储结构
1️⃣顺序存储结构
一组连续的存储单元依次存储数据元素,数据元素之间的逻辑关系由元素的存储位置来表示
C语言中用数组来实现顺序存储结构
2️⃣链式存储结构
链式存储:一组任意的存储单元来存储数据元素,数据元素之间的逻辑关系用指针来表示
存储灵活,提取不方便,存储效率差(还得存储地址)
C语言中用指针来实现链式存储结构
3️⃣索引存储结构(理解)
在存储结点信息的同时,还建立附加的索引表
4️⃣散列存储结构(理解)
1.25数据类型和抽象数据类型
1️⃣ 在使用高级程序设计语言编写程序时,必须对程序中出现的每个变量常量或表达式,明确说明它们所属的数据类型
5️⃣
"例如,C语言中:
int,char, float, double等基本数据类型
数组、结构、共用体、枚举 等构造数据类型
指针、空(void)类型
用typedef 自己定义数据类型
一些最基本数据结构可以用数据类型来实现,如数组、字符串等;
而另一些常用的数据结构,如栈、队列、树、图等,不能直接用数据类型来表示。
2️⃣高级语言中的数据类型明显地或隐含地规定了在程序执行期间变量和表达的所有可能的取值范围,以及在这些数值范围上所允许进行的操作。
例如,C语言中定义变量i为int类型,
就表示i是[-min,max]范围的%等操作整数,
在这个整数集上可以进行+ - * 、 %操作
3️⃣数据类型(Data Type)
定义:是一组性质相同的值的集合以及定义于这个值集合上的一组操作的总称。
4️⃣抽象数据类型(ADT)
eg:
定义:是指一个数学模型以及定义在此数学模型上的一组操作。
由用户定义,从问题抽象出数据模型(逻辑结构)
还包括定义在数据模型上的一组抽象运算(相关操作)
不考虑计算机内的具体存储结构与运算的具体实现算法
抽象数据类型的形式定义:
基本操作定义格式说明:
参数表: 赋值参数 只为操作提供输入值。
引用参数 以&打头,除可提供输入值外,还将返回操作结果。
初始条件:描述操作执行之前数据结构和参数应满足的条件,若不满足则操作失败,并返回相应出错信息。
若初始条件为空,则省略之。
ADT定义举例--Circle的定义
ADT定义举例--复数的定义
Complex抽象数据类型中的基本操作:
1.3小结
1.4抽象数据类型的表示与实现
抽象数据类型可以通过固有的数据类型(如整型、实型、字符型等)来表示和实现。
"即利用处理器中已存在的数据类型来说明新的结构,用已经实现的操作来组合新的操作。
注:在本门课程的学习过程中,我们使用的类C语考(介于伪码和C语言之间)作为描述工具。
其描述语法见教材P10-11。
但上机时要用具体语言实现,如或C++等
用C语言实现抽象数据类型
Void assign (complex*A,float real,float imag) {
A->realpart = real; //把real赋值给我要构造的这个这个复数的实部 /* 实部赋值 */
A->imagpart = imag; /* 虚部赋值 */
/* End of assign()*/
void add(complex_*c,Complex A, Complex B){ /*C=A+B*/
c->realpart = A.realpart +B.realpart; /*实部相加*/
c->imagpart = A.imagpart +B.imagpart; /*虚部相加*/
// A.realpart ,B.realpart,普通的变量这么取值
//complex_*c 指针形的变量得这么取值,c->imagpart
// 注:Complex是我们定义的一个结构体类型
//带*:指针变量,它是指向Complex类型的指针不带*:Complex类型的普通变量
/* End of Add()*/
抽象数据类型举例:
1.4算法与算法分析
🎯算法的定义:
🎭♟️
"对特定问题求解方法和步骤的一种描述,它是指令的有限序列。其中每个指令表示一个或多个操作。
(人话:解决问题 的方法和步骤)
🎯算法的描述
自然语言:英语、中文
流程图:传统流程图、NS流程图
伪代码:类语言/类C语言
程序代码:C语言程序、JAVA语言程序.
🎯算法与程序
算法是解决问题的一种方法或一个过程,考虑如何将输入转换成输出,一个问题可以有多种算法
程序是用某种程序设计语言对算法的具体实现。
🎯算法特性:
一个算法必须具备以下五个重要特性
有穷性:一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成。
确定性:算法中的每一条指令必须有确切的含义,没有二义性,在任何条件下,只有唯一的一条执行路径,即对于相同的输入只能得到相同的输出,
可行性: 算法是可执行的,算法描述的操作可以通过已经实现的基本操作执行有限次来实现。
输入 :一个算法有零个或多个输入。
输出:一个算法有1个或多个输出。
🎯算法设计的要求
⚽正确性(Correctness)
⚽可读性(Readability)
⚽健壮性(Robustness)
⚽高效性(Efficiency)
🎯算法效率
🎯算法时间效率的度量
1. 算法时间效率可以用依据该算法编制的程序无计算机上执行所消耗的时间来度量。
2. 两种度量方法
1️⃣事后统计
将算法实现,测算其时间和空间开销
缺点:编写程序实现算法将花费较多的时间和精力;所得实验结果依赖于计算机的软硬件等环境因素, 掩盖算法本身的优劣
2️⃣事前分析
对算法所消耗资源的一种估算方法
🎯用的最多是事前分析方法
一个算法的运行时间是指一个算法在计算机上运行所耗费的时间大致可以等于计算机执行一种简单的操作(如赋值、比较、移动等)所需的时间与算法中进行的简单操作次数乘积
算法运行时间=一个简单操作所需的时间x简单操作次数
也即算法中每条语句的执行时间之和
算法运行时间=每条语句的执行次数(又称为语句频度)x 该语句执行一次所需的时间
每条语句执行一次所需的时间,一般是随机器而异的。取决于机器的指令性能、速度以及编译的代码质量。是由机器本身软硬件环境决定的它写算法无关。
所以,我们可假设执行每条语句所需的时间均为单位时间。此时对算法的运行时间的讨论就可转化为讨论该算法中所有语句的执行次数,即频度之和了。
这就可以独立于不同机器的软硬件环境来分析算法的时间性能了
🎯例如:两个n x n矩阵相乘的算法可描述为:
for(i=1;i<=n;i++) // n+1次
//一个循环,用来循环变量控制执行次数,执行多少次,从1到n,循环变量执行n次,
//但是最后一句还要判断,条件不成立,退出循环,所以要多执行一次
for(j=1;j<=n;j+ +){ // n(n+1)次
c[i][j]=0; // n*n次
for(k=0;k<n;k++) // n*n*(n+1)次
c[i][j]=c[i][j]+a[i][k]*b[k][j]; // n*n*n次
我们把算法所耗费的时间定义为该算法中每条语句的频度之和,则上述算法的时间消耗T(n)为:
这是一个关于n的函数T(n)=2n³+ 3n²+ 2n+1
🎯算法时间复杂度的渐进表示法
🎴为了便于比较不同算法的时间效率,我们仅比较它们的数量级
例如:两个不同的算法,时间消耗分别是
T(n) =10n² F(n)=5n³
🎴若有某个辅助函数f(n),使得当n趋近于无穷大时, T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n))(比值:也就是说他们成正比,增长率相同)
称O(f(n))为算法的渐进时间复杂度(O是数量级的符号),简称时间复杂度
🎴渐进:语句频度的这个函数的数量级
🎴基本操作:只需把贡献最大的语句找出来就行
🎯算法时间复杂度定义
🎯分析算法时间复杂度的基本方法
🎯算法时间复杂度分析例题
x=0;y=0;
for(int k = 0;k < n;k++)
x++;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
y++;
🎯算法时间复杂度不同:
请注意:有的情况下,算法中基本操作重复执行的次数还随问题的输入数据集不同而不同
🎯算法时间复杂度
最坏时间复杂度:指在最坏情况下,算法的时间复杂度。
平均时间复杂度:#指在所有可能输入实例在等概率出现的情况下,算法的期望运行时间。
最好时间复杂度:指在最好情况下,算法的时间复杂度。
一般总是考虑在最坏情况下的时间复杂度,以保证算法的运行时间不会比它更长
"对于复杂的算法,可以将它分成几个容易估算的部分,然后利用大O加法法则和乘法法则,计算算法的时间复杂度
🎯算法时间效率的比较
当n取得很大时,指数时间算法和多项式时间算法在所需时间上非常悬殊
时间复杂度T(n)按数量级递增顺序为:
1.5渐进空间复杂度
空间复杂度:算法所需存储空间的度量,其中n为问题的规模(或大小)
算法要占据的空间:
算法本身要占据的空间,输入/输出,指令,常数,变量等
算法要使用的辅助空间
算法复杂度空间例题:
算法1:
跟n没有关系,跟多少个元素没有关系,只需要一个临时变量,所以说是个常数阶
像这种常数阶的,通过这个算法,就是原地工作
算法2:
跟元素个数n有关,n越多,它需要的辅助空间就越多