软考——软件设计师:第四章:数据结构&算法分析与设计考点总结(完整篇)(上)

简介: 软考——软件设计师:第四章:数据结构&算法分析与设计考点总结(完整篇)(上)

文章目录:


1.数据结构的定义(了解就好)

2.数组

3.稀疏矩阵

4.线性表

4.1 顺序表与链表

4.2 顺序存储与链式存储

4.3 栈与队列 

4.4 线性表的推广——广义表 

5.树与二叉树

5.1 基本概念

5.2 二叉树的重要性质

5.3 二叉树的遍历

5.4 反向构造二叉树 

5.5 树转二叉树

5.6 二叉查找树(二叉排序树) 

5.7 最优二叉树(哈夫曼树)

5.8 线索二叉树 

5.9 平衡二叉树


1.数据结构的定义(了解就好)

数据结构是指数据元素的集合及元素间的相互作用和构造方法。元素之间的相互关系是数据的逻辑结构,数据元素及元素之间关系的存储称为物理结构(或存储结构)。

数据结构按照逻辑关系的不同分为线性结构和非线性结构两大类。线性结构主要就是线性表(顺序表、单链表)、栈、队列数组和串这些,而非线性结构主要就是树结构、图结构。

算法与数据结构密切相关,数据结构是算法设计的基础,设计合理的数据结构可使算法简单而高效。


2.数组


对于一维数组来说,a[i]的存储地址计算公式为:a + i×lena代表起始位置,i代表数组下标,len代表每个元素所占字节数。

假设数组a中每个元素占两个字节,那么对于起始位置为0、元素a[1]来说,它的存储地址为:0 + 1×2=2,因为01两个位置被数组的第一个元素a[0]占用。

对于上面这道例题,二维数组中,根据计算公式,元素a[2][3]按行优先存储的存储地址为:a + 2×5+3×2=a + 26

3.稀疏矩阵


对于上三角矩阵和下三角矩阵,大家需要搞懂的就是上面这种例题。(不建议大家死记硬背这两个公式,推荐大家采取代入数字直接验证的方式!!!)

例题中是一个下三角矩阵,我们看到A[00]存储在一维数组M[1]这个位置(注意数组M的下标从1开始),所以我们取 i=0j=0代入四个选项,BC两个选项得到的结果是0,直接排除;而AD两个选项得到的结果是1,满足题意。我们再看到A[10]存储在一维数组M[2]这个位置,所以我们再取 i=1j=0代入AD两个选项,D选项得到的结果是1A选项得到的结果是2。综上所述,通过两次取值验证,A选项正确!!!

4.线性表


一个线性表是nn≥0)个元素的有限序列,通常表示为(a1a2......an)。非空线性表的特点如下:

存在唯一的一个称作第一个的元素。

存在唯一的一个称作最后一个的元素。

除第一个元素外,序列中的每个元素均只有一个直接前驱。

除最后一个元素外,序列中的每个元素均只有一个直接后继。 


4.1 顺序表与链表

单链表的插入操作:
s->next=p->next;
p->next=s;
单链表的删除操作:
q=p->next;
p->next=q->next;
(上面两句等价于:p->next=p->next->next)

4.2 顺序存储与链式存储


对于顺序存储和链式存储,进行查找的时间复杂度显然就是On/2)。


读运算:顺序存储中,无论元素在哪个位置,直接访问数组下标即可,所以是O1);链式存储中,如果读取第一个,则为最好情况1,如果读取最后一个,则为最坏情况n,因为要依次访问这些元素的指针域,所以总的为O((n+1/2)。


插入运算:顺序存储中,假设元素依次为25619n=5),那么最好情况是在最后一个元素后面插入一个新元素,此时不需要移动任何元素,为0,最坏情况是在第一个元素前面插入一个新元素,此时需要将25619全部向后移动一个位置,为5,所以平均下来需要移动(0+5/2个元素,即为O0+5/2=On/2);链式存储中,只需要移动插入元素位置的前驱指针和后继指针就可以了,所以为O1)。


删除运算:顺序存储中,假设元素依次为25619n=5),那么最好情况是将最后一个元素删除,此时不需要移动任何元素,为0,最坏情况是将第一个元素删除,此时需要将5619全部向前移动一个位置,为4,所以平均下来需要移动(0+4/2个元素,即为O0+4/2=O((n-1/2);链式存储中,只需要移动删除元素位置的前驱指针和后继指针就可以了,所以为O1)。


4.3 栈与队列

栈和队列最重要的一点就是:栈为先进后出;队列为先进先出。(广度队列,深度栈!!!)

对于上面这个习题,元素abc依次入栈,则可能得到哪些出栈序列?

首先,我们可以利用数学中的排列组合知识,3个元素,全排列一共有3=6种情况,但是出栈真的有6种吗?实则不然!


元素a进栈,元素a出栈,元素b进栈,元素b出栈,元素c进栈,元素c出栈,此时得到出栈序列为:abc


元素a进栈,元素a出栈,元素b进栈,元素c进栈,元素c出栈,元素b出栈,此时得到出栈序列为:acb


元素a进栈,元素b进栈,元素b出栈,元素a出栈,元素c进栈,元素c出栈,此时得到出栈序列为:bac


元素a进栈,元素b进栈,元素b出栈,元素c进栈,元素c出栈,元素a出栈,此时得到出栈序列为:bca


元素a进栈,元素b进栈,元素c进栈,元素c出栈,元素b出栈,元素a出栈,此时得到出栈序列为:cba


为什么出栈序列中没有cab这种情况呢?如果元素c第一个出栈,则说明元素ab已经在栈中,而ab压在下面,如果b不出来,a是肯定出不来的,所以不存在cab这种情况。即一共有5中出栈序列。

我们再来看上面这道例题,左端可进可出,右端只能进不能出。四个元素依次入队,得不到哪种出队序列???


A选项:e1e2e3e4依次从左端入队,就得到了e4e3e2e1这样的队列,此时依次出队即可得到A选项的结果。


B选项:e1e2先从左端入队,之后e3从右端入队,最后e4从左端入队,就能得到e4e2e1e3的队列,满足B选项。


C选项:e1e2先从右端入队,之后e3e4再从左端入队,就可以得到e4e3e1e2的队列,即符合C选项。


D选项:仔细分析这个队列的入队出队规则,我们发现e1e2无论如何都是相邻的元素,所以无法得到D选项这样的队列。


4.4 线性表的推广——广义表

1:广义表LS1的长度为元素的个数(单个元素算一个元素,子表这个整体算一个元素),所以LS1中,a是一个元素,(bc)是一个元素,(de)是一个元素,即长度为3。深度为所含括号的层数,LS1中最外层有一层括号,内部的(bc)和(de)算同样的一层,所以总层数为2,即深度为2


2:要获取LS1中的字母b,则需要的操作为:先取表尾,得到((bc),(de));再取表头,得到(bc);再取表头即可得到字母b。即操作序列为:HeadHeadTailLS1)))。


5.树与二叉树


5.1 基本概念


结点的度:当前结点的孩子结点的个数。比如结点2有两个孩子结点45,所以结点2的度为2;而结点45没有孩子节点,所以度为0;结点3只有一个孩子节点6,所以度为1


树的度:树中所有结点的度最大的那个。比如上面这棵树中,结点的度最大为2,所以该树的度为2


叶子结点:度为0的结点。


内部节点:度不为0的结点,也称为分支结点或非终端结点。除根结点外,分支结点也称为内部结点。


父结点、子结点、兄弟结点:123的父结点,452的子结点,4523称为兄弟结点。


层次:根结点为第一层,之后层数依次加1


5.2 二叉树的重要性质


再补充一条性质:具有n个结点的完全二叉树的深度为:「log2n+ 1(前面的对数部分是向下取整)


5.3 二叉树的遍历

对于上面的二叉树,我们来求一下它的先序、中序、后序以及层次遍历:👇👇👇


先序遍历:采用DLR(根左右),得到的结果是:1 24578 36

中序遍历:采用LDR(左根右),得到的结果是:42785 1 36

后序遍历:采用LRD(左右根),得到的结果是:48752 63 1

层次遍历:依次获取每层的结点,得到的结果是:1 23 456 7 8。(具体的过程在此就不再详细说明了。。。)


要想唯一确定一棵二叉树,必须要有中序遍历的序列结果!!!


5.4 反向构造二叉树

上面这道例题中,给出了先序序列和中序序列,我们来反向构造出对应的二叉树:👇👇👇


首先看先序序列,采用的是根左右的方法,所以第一个结点A一定是根结点。对于后面的一堆,我们要借助于中序序列,因为中序序列采用的是左根右的方法,所以由根结点A就可以划分出左右两棵子树(左:HBEDF,右:GC)。


之后,我们带着左子树HBEDF再回到先序序列,可以看到这部分在先序序列中为BHFDE,所以左子树的根为B。而结点B在中序序列中对应的子序列为:HBEDF,所以B的左子树为H,右子树为EDFEDF在先序序列中对应:FDE,所以B的右子树的根为FF在中序序列中为:EDF,所以F只有左子树ED,带入先序序列为:DE,即根为D,对应中序序列中的ED,即D的左子树为E


A的右子树为GC,对应先序序列中的CG,即根为C,对应中序序列中的GC,即C的左子树为G


由上述分析,得到如下的二叉树:👇👇👇

5.5 树转二叉树

我们要将一棵普通的树转为二叉树,要遵循这样的原则:孩子结点左子树结点,兄弟结点右子树结点。


根结点1还作为根结点,它有三个孩子结点234,那么这三个孩子结点都应该转为新二叉树的左子树部分(因为1没有兄弟结点,所以新二叉树没有右子树部分),我们选取最左边的孩子结点2作为新二叉树的左子树结点(左子树的根),而结点34为结点2的兄弟结点,所以34应该转为2的右子树部分。43的兄弟结点,所以4应该作为3的右子树部分。而5673的孩子结点,所以对应为3的左子树部分,我们同样选取最左边的孩子结点5作为3的左子树的根,而67作为5的兄弟结点,应该转为5的右子树部分,再次选取最左边的孩子结点6作为5的右子树的根,而7作为6的兄弟,直接转为6的右子树部分即可。再来看3的右子树部分,4作为3的兄弟结点,应该转为3的右子树的根,而894的孩子结点,全部转为4的左子树部分,选取最左边的孩子结点8作为4的左子树的根,而9作为8的兄弟结点,直接转为8的右子树部分即可!!!


仔细观察中间下方的那棵树,我们每选取一个孩子结点,就将其余的孩子结点与父结点剪断(虚线),将选取的孩子结点与自己的兄弟结点相连(实线),最终实线连成的树就是我们需要转换的二叉树!!!

5.6 二叉查找树(二叉排序树)

5.7 最优二叉树(哈夫曼树)

(哈夫曼树的目标就是构造最短的带权路径长度!!!哈夫曼编码采取左01的原则!!!)


左边这棵哈夫曼树的带权路径长度为:1×1 + 2×2 + 4×3 + 8×3=41

中间这棵哈夫曼树的带权路径长度为:8×1 + 4×2 + 1×3 + 2×3=25

右边这棵哈夫曼树的构造方法为:先选取两个权值最小的结点35,得到新的结点8,之后选取比8小的结点7,与8组合,得到新的结点15。而此时比15小的结点有3个(81114),我们先选811构成新的结点19,之后将1415组合,得到新的结点29,再将结点23与此时较小的结点19组合得到42,同时也将结点2929组合得到58,最后4258组合得到哈夫曼树的根结点100


其带权路径长度为:5×5 + 3×5 + 7×4 + 14×3 + 8×3 + 11×3 + 29×2 + 23×2=271

5.8 线索二叉树

对于先序线索二叉树,它是对于二叉树的先序遍历产生的。上面这棵二叉树的先序遍历结果为:ABDEHCFGI,可以看到与结点D相连的就是结点BE,其他的结点均是如此。(中序和后续线索二叉树和先序的规则是一样的)

n个结点的二叉树采用二叉链表做存储结构,则链表中必然有n+1 个空指针域。

5.9 平衡二叉树

先看左边这棵二叉树,结点19为叶子节点,无左子树和右子树,所以平衡度为0;结点5的左子树深度为1、无右子树(深度为0),所以平衡度为1-0=1;结点8无左子树(深度为0)、右子树深度为1,所以平衡度为0-1=-1;结点7的左右子树深度均为2


所以平衡度为2-2=0;这几个结点都满足平衡二叉树的平衡因子只能为±10的条件。但是上面的结点397388的平衡度依次为345,就不满足平衡因子只能为±10的条件,所以这不是一棵平衡二叉树。


而右边这棵二叉树,参照上面的分析过程,它是一棵标准的平衡二叉树!!!

相关文章
|
2月前
|
机器学习/深度学习 算法 搜索推荐
从理论到实践,Python算法复杂度分析一站式教程,助你轻松驾驭大数据挑战!
【10月更文挑战第4天】在大数据时代,算法效率至关重要。本文从理论入手,介绍时间复杂度和空间复杂度两个核心概念,并通过冒泡排序和快速排序的Python实现详细分析其复杂度。冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1);快速排序平均时间复杂度为O(n log n),空间复杂度为O(log n)。文章还介绍了算法选择、分而治之及空间换时间等优化策略,帮助你在大数据挑战中游刃有余。
87 4
|
22天前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
34 1
|
2月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
92 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
23天前
|
存储 算法 搜索推荐
Python 中数据结构和算法的关系
数据结构是算法的载体,算法是对数据结构的操作和运用。它们共同构成了计算机程序的核心,对于提高程序的质量和性能具有至关重要的作用
|
23天前
|
数据采集 存储 算法
Python 中的数据结构和算法优化策略
Python中的数据结构和算法如何进行优化?
|
1月前
|
算法
数据结构之路由表查找算法(深度优先搜索和宽度优先搜索)
在网络通信中,路由表用于指导数据包的传输路径。本文介绍了两种常用的路由表查找算法——深度优先算法(DFS)和宽度优先算法(BFS)。DFS使用栈实现,适合路径问题;BFS使用队列,保证找到最短路径。两者均能有效查找路由信息,但适用场景不同,需根据具体需求选择。文中还提供了这两种算法的核心代码及测试结果,验证了算法的有效性。
96 23
|
1月前
|
算法
数据结构之蜜蜂算法
蜜蜂算法是一种受蜜蜂觅食行为启发的优化算法,通过模拟蜜蜂的群体智能来解决优化问题。本文介绍了蜜蜂算法的基本原理、数据结构设计、核心代码实现及算法优缺点。算法通过迭代更新蜜蜂位置,逐步优化适应度,最终找到问题的最优解。代码实现了单链表结构,用于管理蜜蜂节点,并通过适应度计算、节点移动等操作实现算法的核心功能。蜜蜂算法具有全局寻优能力强、参数设置简单等优点,但也存在对初始化参数敏感、计算复杂度高等缺点。
60 20
|
22天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
52 1
|
1月前
|
机器学习/深度学习 算法 C++
数据结构之鲸鱼算法
鲸鱼算法(Whale Optimization Algorithm,WOA)是由伊朗研究员Seyedali Mirjalili于2016年提出的一种基于群体智能的全局优化算法,灵感源自鲸鱼捕食时的群体协作行为。该算法通过模拟鲸鱼的围捕猎物和喷出气泡网的行为,结合全局搜索和局部搜索策略,有效解决了复杂问题的优化需求。其应用广泛,涵盖函数优化、机器学习、图像处理等领域。鲸鱼算法以其简单直观的特点,成为初学者友好型的优化工具,但同时也存在参数敏感、可能陷入局部最优等问题。提供的C++代码示例展示了算法的基本实现和运行过程。
49 0
|
2月前
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
41 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
下一篇
DataWorks