根据MOOC上课程总结,文章目录为:
一、引论
- 数据结构的基本概念
- 数据的逻辑结构和存储结构
- 算法及其时间复杂度
- 时间复杂度及应用
二、线性表
- 线性表的概念及顺序存储
- 单链表的概念及其基本操作
- 建立单链表
- 循环链表
- 双向链表
- 一元多项式的表示和运算
三、栈和队列
- 栈的概念及其基本操作
- 栈的概念及其基本操作—双端栈
- 栈的应用—递归及汉诺塔问题
- 栈的应用—迷宫实验
- 队列的概念及基本操作
- 队列的概念及应用—链队列
- 表达式的求值问题
- 递归与分治算法
四、串
- 串的基本操作
- 串的简单模式匹配
- 串的KMP模式匹配算法
- 模式串的next值计算思
- 模式串的next值计算实现
- 模式串的nextval值
五、多维数组和广义表
- 数组的定义与顺序存储
- 矩阵的压缩存储
- 三元组矩阵的快速转置
- 广义表
六、树
- 二叉树的性质
- 二叉树的顺序存储
- 二叉树的遍历
- 统计叶子结点
- 计算二叉树的高度
- 二叉树的恢复建立
- 二叉树的非递归遍历
- 线索二叉树
- 线索二叉树的遍历
- 树和森林
- 树与森林的遍历
- 哈夫曼树
- 哈夫曼编译码
- 哈夫曼编码算法
- 解空间树及其相关算法
七、图
- 图的基本概念
- 图的存储
- 图的深度优先遍历
- 图的广度优先遍历
- 图的最小生成树-Prim算法思想
- 图的最小生成树-Prim算法实现
- 图的最小生成树-Kruskal算法
- 图的拓扑排序思想
- 图的拓扑排序实现
- 图的关键路径思想
- 图的关键路径实现
- 图的单源最短路径-Dijkstra思想
- 图的单源最短路径-Dijkstra实现
- 贪心算法
八、查找
- 顺序查找
- 折半查找
- 二叉排序树的基本概念与查找
- 二叉排序树的插入与生成
- 二叉排序树的删除
- 哈希表基本概念
- 哈希函数
- 哈希处理冲突
九、排序
- 排序基本概念
- 直接插入排序
- 希尔排序
- 冒泡排序
- 快速排序
- 选择排序
- 树形排序
- 堆排序
- 归并排序
- 基数排序
正文
一、引论
(一)数据结构的基本概念
niklaus wirth计算机科学家说过:
算法+数据结构=程序。
algorithm+data structures=programs
程序设计:为计算及处理问题编制的一组指令集和。
算法:处理问题的策略。
若有一个实际的问题需要用程序设计实现,那么第一步就要先做数据抽象,抽象出它的数学模型。然后对数据进行组织,如何组织、存储、计算就是数据结构要研究的范畴。
对于数值型数据如结构静力分析计算(线性代数方程组)、全球天气预报(环流模式方程/球面坐标)比较好处理,但是对于很多非数值型的计算,程序设计要解决两个关键问题:
①表示:对象及其关系在计算机中的表示。只有对象及其相互关系已存储在计算机中,才能被进一步处理。
②操作:对对象进行处理,访问。
A、数据结构的分类
1、线性结构
例子1:超市商品管理。对商品的各种信息如何加以组织和存储。
数据对象:商品。如W1是方便面,W2是洗发水,W3是鸡精。。。这是一个表结构。
关系:线性。W1后面是W2,W2后面是W3。。。
![262a21b082f67fad54483efd3044fd97.png](https://img-blog.csdnimg.cn/img_convert/262a21b082f67fad54483efd3044fd97.png)
2、树型结构
例子2:计算机对弈。象棋 五子棋 三子棋等。
操作对象:格局(棋盘状态)
元素间的关系:树(有比赛规则决定)
![ce0fc36ed6e84203917847306240b51c.png](https://img-blog.csdnimg.cn/img_convert/ce0fc36ed6e84203917847306240b51c.png)
西北大学郝克刚博导编程的感悟:
![18eac47880bb7620deabca3c4983b067.png](https://img-blog.csdnimg.cn/img_convert/18eac47880bb7620deabca3c4983b067.png)
3、图结构
例子3:元素间的关系为图。
![5e7face5799c95fd7e8b7a8857cbac04.png](https://img-blog.csdnimg.cn/img_convert/5e7face5799c95fd7e8b7a8857cbac04.png)
![70b11508a64a6155ae23d149c1d5e62f.png](https://img-blog.csdnimg.cn/img_convert/70b11508a64a6155ae23d149c1d5e62f.png)
![fc1cf7a0ae6ed87375f196a56a62ff05.png](https://img-blog.csdnimg.cn/img_convert/fc1cf7a0ae6ed87375f196a56a62ff05.png)
![577c88c9be8caa58842bdb18b17b1ddf.png](https://img-blog.csdnimg.cn/img_convert/577c88c9be8caa58842bdb18b17b1ddf.png)
B、基本概念
数据data:描述客观事物的数值、字符以及能输入机器且能被处理的各种符号集合。包括整型、实型、布尔型、图像、字符、声音等一切可以输入到计算机中的符号集合。 数据元素data element: 组成数据的基本单位,是数据集合的个体,在计算机中通常作为一个整体进行考虑和处理。一个数据元素可以由一个或多个数据项data item组成,数据项是有独立含义的最小单位。 数据对象data object: 性质相同的数据元素的集合,是数据的一个子集。如整数集合:N={0,正负1,……},无限集。字符集合 数据结构data structure:相互之间存在一种或多种特定关系的数据元素的集合,是 带有结构关系的数据元素的集合,他指的是数据元素之间的相互关系,即数据的组织形式。如树结构、图结构。 数据类型data type: 一组性质相同的值集合以及定义在这个值集合上的一组操作的总称。如在高级语言中,整型类型的取值范围为-32768到+32767,运算符集合为加减乘除取模。数据类型可以分为原子类型和结构类型。 原子类型:其值不可分解。如C语言中的标准类型(整型、实型、字符型)。 结构类型:其值是由若干成分按某种结构组成的,因此是可以分解的,并且它的成分可以是非结构的,也可以是结构的。
数据抽象与抽象数据类型。 抽象数据类型abstract data type: 基于一类逻辑关系的数据类型以及定义在这个类型之上的一组操作。抽象数据类型确定了一个模型,但将模型的实现细节隐藏起来,它定义了一组运算,但将运算的实现过程隐藏起来。如整型就可以认为是一个抽象数据类型,取值范围,运算过程和细节我们都不用管。
如线性表的抽象数据类型的描述:
![c9802bd6b99689f5fb7c40921d5474f8.png](https://img-blog.csdnimg.cn/img_convert/c9802bd6b99689f5fb7c40921d5474f8.png)
抽象数据类型实现的三种方法:①传统的面向过程的程序设计、②“包”、“模型”的设计方法如Ada语言;③面向对象的程序设计OOP。
ADT有两个重要特征:①数据抽象:用ADT描述程序处理的实体时,强调的是其本质的特征、其所能完成的功能以及他和外部用户的接口(即外部使用它的方法)。②数据封装:将实体的外部特性和其内部实现细节分离,并且对外部用户隐藏其内部实现细节。
(二)数据的逻辑结构和存储结构
1、逻辑结构
逻辑结构:数据元素之间的逻辑关系描述。形式化描述为:Data_Structure=(D,R)。其中D是数据元素的有限集,R是D上关系的有限集。逻辑结构有四类基本的结构:集合结构、线性结构、树型结构、图状结构。 集合结构:结构中的数据元素之间除了 同属于一个集合的关系外,无任何其他关系。 线性结构:结构中的数据元素之间存在着 一对一的线性关系。如一元表。 树型结构:结构中的数据元素之间存在着 一对多的层次。如文件夹存储、对弈、五子棋等。 图状结构或网状结构:结构中的数据元素之间 多对多的任意关系。如城市旅游、交通问题。
2、存储结构
存储结构:逻辑结构在计算机中的存储映像,是逻辑结构在计算机中的表现,包括数据元素的表示和关系的表示。
数据元素的表示:用若干个二进制“位串”表示。
数据元素之间关系的表示:有两种方法,顺序映像(顺序存储结构)和非顺序映像(非顺序存储结构)。
![b5b89d45b48f840c1b77d278ec7e7f69.png](https://img-blog.csdnimg.cn/img_convert/b5b89d45b48f840c1b77d278ec7e7f69.png)
![7c4d64030f7867b7e510415981526da0.png](https://img-blog.csdnimg.cn/img_convert/7c4d64030f7867b7e510415981526da0.png)
运算集合:在计算机中进行运算操作的集合。
线性表一般为增删改查。
最终我们就得出了数据结构的定义:
按某种 逻辑关系组织起来的一批数据,按一定的 映像方式把它存放在计算机 存储中,并在这些数据上定义了一个 运算的集合。
![4de947e8467de2eb6453755fe4c71756.png](https://img-blog.csdnimg.cn/img_convert/4de947e8467de2eb6453755fe4c71756.png)
(三)算法及其时间复杂度
算法Algorithm:是规则的有限集合,是为解决特定问题而规定的一系列操作。
1、算法的特性有5个:
- 有限性:有限步骤内正常结束,不能形成无穷循环。
- 确定性:算法中的每一个步骤必须有确定含义。
- 无二义性:算法中不能拥有二义性。
- 输入或输出:至少有一个或多个输入和输出。
- 可行性:原则上能精确进行,操作可通过已实现基本运算执行有限次而完成。
2、对算法的要求:
- 正确性:
![f15923e03312e8dc05abbc99ef188226.png](https://img-blog.csdnimg.cn/img_convert/f15923e03312e8dc05abbc99ef188226.png)
- 可读性:一个程序的命名一般应按照它的含义,函数的整个结构都要非常的清晰。
- 健壮性:抗病毒和抗干扰能力。
- 高效率和低存储量的要求:一般我们需要一个程序的销量是比较高的,占用的存储空间是比较少的。
3、算法、语言、程序的关系:
算法:描述了数据对象的元素之间的关系(包括数据逻辑关系,存储关系描述)
描述算法的工具:算法可用自然语言、框图或高级程序设计语言(如C语言、Java、Python)进行描述。
程序是算法在计算机中的实现。
4、算法性能分析
评价算法的标准:评价一个算法的好坏就是看它的时间和空间,因为空间现在的内存都很大,考虑的比较少,我们主要考虑算法的时间复杂度怎样进行衡量。
性能性价:对问题规模N与该算法在运行时所占的空间S与所耗费的时间T给出一个数量关系的评价。
问题规模N——对不同的问题其含义不同,对矩阵是阶数;对多项式运算是多项式项数;对图是顶点个数;对集合运算是集合中元素个数。
衡量算法效率的方法一般有两种:
- ①事后统计法,缺点必须执行程序,其他因素会掩盖算法本质。
- ②事前估算法。
和算法执行时间相关的因素有:
- 算法选用的策略,如冒泡排序
- 问题的规模
- 编写程序的语言
- 编译程序产生的机器代码的质量
- 计算机执行指令的速度
算法执行时间:大致上等于其所有语句执行时间的总和,对于语句的执行时间是指该条语句的执行次数和执行一次所需时间的乘积。
一般针对算法中基本操作语句(源操作)的执行次数做出估计,从中得到算法执行时间的信息。
语句频度:该语句在一个算法中重复执行的次数。
![40a0a018885688e0b49fce11879f9612.png](https://img-blog.csdnimg.cn/img_convert/40a0a018885688e0b49fce11879f9612.png)
算法的时间复杂度:即是算法的时间量度记做:T(n)=O(f(n))
如:
- x=x+1;时间复杂度为0(1),称为常量阶;
- for (i=1;i<=n;i++) x=x+1;时间复杂度为O(n),称为线性阶;
- for(i=1;i<=n;i++)
- for(j=1;j<=n;j++) x=x+1;时间复杂度为O(n的平方),称为平方阶
一般常用的时间复杂度频率计数有7个:
![a611c2b8509810a8307366c2392bf02f.png](https://img-blog.csdnimg.cn/img_convert/a611c2b8509810a8307366c2392bf02f.png)
常用的时间复杂度频率表:
![a931dac1fe8ce1fd7c1f19a94a820466.png](https://img-blog.csdnimg.cn/img_convert/a931dac1fe8ce1fd7c1f19a94a820466.png)
算法的空间复杂度:作为算法所需存储空间的量度,记做:S(n)=O(f(n))。算法的存储量包括输入数据所占空间,程序本身所占空间,辅助变量所占空间。
问题:编写程序实现用亿元人民币换成一分、两分、五分的硬币共50枚。分析:假设一分、两分、五分的硬币各为x、y、在、枚。则有:x+y+z=50;x+2y+5z=100
那么编程方法1:三重循环
![88014f28f9755c7c6f33ae548d1cde36.png](https://img-blog.csdnimg.cn/img_convert/88014f28f9755c7c6f33ae548d1cde36.png)
方法2:两重循环
![62584e3ecc083df399ddf279300e3102.png](https://img-blog.csdnimg.cn/img_convert/62584e3ecc083df399ddf279300e3102.png)
方法3:改进的两重循环
![7c8677ff886ec5d8158b686e40ed28bf.png](https://img-blog.csdnimg.cn/img_convert/7c8677ff886ec5d8158b686e40ed28bf.png)
方法4:单重循环
![bec7202c2c82520e85a786715c112b44.png](https://img-blog.csdnimg.cn/img_convert/bec7202c2c82520e85a786715c112b44.png)
算法的设计是至关重要的。无论多么简单的编程,都要考虑优化,怎么简单。
![4cf1b963c8db7043edc20db673ea9142.png](https://img-blog.csdnimg.cn/img_convert/4cf1b963c8db7043edc20db673ea9142.png)
二、线性表
(一)线性表的概念及顺序存储
线性表(linear list):由n(n>=0)个类型相同的数据元素组成的有限序列。数据元素之间是一对一的关系,即每个数据元素最多有一个直接前驱和一个直接后继。
![7d652e289b2cb20f97ac4ec7679aea09.png](https://img-blog.csdnimg.cn/img_convert/7d652e289b2cb20f97ac4ec7679aea09.png)
特点:
- 同一性:线性表由同类数据元素组成,每一个数据必须属于同一数据对象。
- 有穷性:线性表由有限个数据元素组成,表长度就是表中数据元素的个数。
- 有序性:线性表中相邻数据元素之间存在着序偶关系。
线性表的顺序存储:用一组地址连续的存储单元依次存储线性表中的各个元素,使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中。
采用顺序存储结构的线性表通常称为 顺序表。假设线性表中每个元素占k个单元,第一个元素的地址为loc(a1),则第i个元素的地址为:loc(ai)=loc(a1)+(i-1)k
![7f5bae3ba3baa5ffb252e09cd0299dda.png](https://img-blog.csdnimg.cn/img_convert/7f5bae3ba3baa5ffb252e09cd0299dda.png)
基本运算:查找、插入、删除操作
如c语言中查找操作,按序号查找getdata(L,i)即查找线性表L中第i个数据元素,其结果为L.elem[i]。按内容查找Locate(L,x),即查找线性表L中与给定值x相等的数据元素,其结果是,若在表L中找到与x相等的元素,则返回该元素在表中的序号,若找不到就返回一个空序号如-1。
顺序表插入、删除算法时间复杂度分析:
![a3273ba336a92b4948613ab7ebc9ece3.png](https://img-blog.csdnimg.cn/img_convert/a3273ba336a92b4948613ab7ebc9ece3.png)
![e14552aed12991bba062d5a15dbd229b.png](https://img-blog.csdnimg.cn/img_convert/e14552aed12991bba062d5a15dbd229b.png)
线性表的顺序存储
优点:①用数组存储数据元素,操作方法简单,容易实现。②无须为表示结点间的逻辑关系而增加额外的存储开销。③存储密度高。④顺序表可按元素位序随机存取结点。
缺点:①插入或删除运算不方便,除表尾的位置外,在表的其他位置上进行插入或删除操作都必须移动大量的结点,其效率较低。②由于顺序表要求占用连续的存储空间,存储分配只能预先进行静态分配。因此当表长变化较大时,难以确定合适的存储规模。
(二)单链表的概念及其基本操作
链表:采用链式存储结构的线性表。从实现角度来说,可分为静态链表和动态链表。从链接方式来说,可分为单链表、双向链表和循环链表。 单链表:链表中的每个结点只有一个指针域。单链表包括两个域:数据域——用来存储结点的数据值;指针域——用来存储数据元素的直接后继的地址。
![34b8e1db2d2f7e8ec33f1628b5534bcb.png](https://img-blog.csdnimg.cn/img_convert/34b8e1db2d2f7e8ec33f1628b5534bcb.png)
单链表的插入操作
![c9b98782905039e0fb2b4927df6ebb12.png](https://img-blog.csdnimg.cn/img_convert/c9b98782905039e0fb2b4927df6ebb12.png)
单链表删除
![811699829d0b80b39dad46cd511b175d.png](https://img-blog.csdnimg.cn/img_convert/811699829d0b80b39dad46cd511b175d.png)
![19319dcb5e3d5158c029915da2f1c272.png](https://img-blog.csdnimg.cn/img_convert/19319dcb5e3d5158c029915da2f1c272.png)
(三)建立单链表
(四)循环链表
(五)双向链表
(六)一元多项式的表示和运算
三、栈和队列
(一)栈的概念及其基本操作
- 栈的概念及其基本操作—双端栈
- 栈的应用—递归及汉诺塔问题
- 栈的应用—迷宫实验
- 队列的概念及基本操作
- 队列的概念及应用—链队列
- 表达式的求值问题
- 递归与分治算法
四、串
- 串的基本操作
- 串的简单模式匹配
- 串的KMP模式匹配算法
- 模式串的next值计算思
- 模式串的next值计算实现
- 模式串的nextval值
五、多维数组和广义表
- 数组的定义与顺序存储
- 矩阵的压缩存储
- 三元组矩阵的快速转置
- 广义表
六、树
- 二叉树的性质
- 二叉树的顺序存储
- 二叉树的遍历
- 统计叶子结点
- 计算二叉树的高度
- 二叉树的恢复建立
- 二叉树的非递归遍历
- 线索二叉树
- 线索二叉树的遍历
- 树和森林
- 树与森林的遍历
- 哈夫曼树
- 哈夫曼编译码
- 哈夫曼编码算法
- 解空间树及其相关算法
七、图
- 图的基本概念
- 图的存储
- 图的深度优先遍历
- 图的广度优先遍历
- 图的最小生成树-Prim算法思想
- 图的最小生成树-Prim算法实现
- 图的最小生成树-Kruskal算法
- 图的拓扑排序思想
- 图的拓扑排序实现
- 图的关键路径思想
- 图的关键路径实现
- 图的单源最短路径-Dijkstra思想
- 图的单源最短路径-Dijkstra实现
- 贪心算法
八、查找
- 顺序查找
- 折半查找
- 二叉排序树的基本概念与查找
- 二叉排序树的插入与生成
- 二叉排序树的删除
- 哈希表基本概念
- 哈希函数
- 哈希处理冲突
九、排序
- 排序基本概念
- 直接插入排序
- 希尔排序
- 冒泡排序
- 快速排序
- 选择排序
- 树形排序
- 堆排序
- 归并排序
- 基数排序