软件设计师笔记:数据结构与算法基础


在这里插入图片描述

一、数组与矩阵

1.1 数组

主要了解存储地址计算,以及二维数组的按行存储和按列存储的区别。
在这里插入图片描述

某个数组变量的存储地址,一定是按照数组首元素的地址为偏移来计算的,根据每个元素占的存储空间,求的某元素的存储地址。

二维数组看成一个表,存储地址取决于数组是按行存储还是按列存储。

1.2 稀疏矩阵

在这里插入图片描述
考试建议使用代入法求解。
在这里插入图片描述
代入A[0][0]和A[1][1]即可求解。

二、线性表

2.1 数据结构的定义

数据结构就是计算机存储以及组织数据的方式,研究的意义在于选择不同的数据结构,带来的运行效率差异非常之大,即使同一结构下,稍作调整,效率也可以有很大改变。

按逻辑结构分类可分为线性结构和非线性结构,非线性结构包括树和图。树和图区别在于树没有环路,可图可能存在环路。实际上图可以包含树,树也可以包含线性结构。

2.2 线性表

在这里插入图片描述

线性表是线性结构的基本表现,有两种存储方式:顺序表和链表。

在这里插入图片描述
顺序表就是开辟了连续的空间,如数组。

链表每一个存储单元包含存数据的地方和指针的地方,原因是他的空间不一定是连续的,每一个离散的空间用指针连接起来。链表分为单链表、循环链表、双向链表。

单链表:只有一套指针,头指针指向下一个元素,以此类推。指针是单向的。定义一个元素需要从头节点一个一个找下去。

循环链表:把尾元素指向头节点,好处是当前指针如果已经到达了尾元素,可以直接顺次往下找而不用重新定位头节点的位置。

双向链表:可以双向查询的,有两套指针,一套指针向前链接,另一套指针向后链接。

链表的基本操作:
在这里插入图片描述
尤其要注意操作步骤!!!

单链表删除结点,相当于将指向待删除结点的结点的指针指向待删除节点所指向的结点。即p.next = q.next

插入结点即s.next = p.next; p.next = s

有头结点的链表好处是头结点不存信息,可以令所有的操作方式变成一致的,如果头结点存了信息,那么对头结点的操作应该是特殊的。

2.3 顺序存储与链式存储

在这里插入图片描述
链式存储中结点还存了指针,导致链式存储的存储密度小于顺序存储。

顺序存储要事先确定存储信息需要的空间,开辟连续的空间。链式存储的空间可以动态分配,容量分配更优。

查找运算用顺序表比较方便,在内容没有顺序的情况下两者的时间复杂度相同,如果存储顺序表的内容本身是有序的,要涉及二分查找法的话,则顺序存储更优。

读运算即读取信息,顺序表更优。顺序表可以直接读取某个元素,链表要定位到头结点,再一个一个遍历到所查找的元素。

插入运算,链表更优,只需要局部调整,而顺序表需要把插入位置后的所有元素后移才能插入。

同理删除操作也是链式存储更优。

2.4 队列与栈

在这里插入图片描述
循环队列有两个指针,头指针不动,尾指针指向下一个要存入数据的结点。由于指针还会指会头结点,队空和队满都是两个指针指向头结点,则无法判断是队空还是队满。一般采取在最后一个位置空出来不放元素,再用如图的判断条件来判断队满。

依次入栈尝试写出所有可能的出栈序列问题,个人的经验是,将元素按次序标号1,2,3等等,元素所有排列组合中,只要满足以下条件就是可能的出栈序列:在排列中如果出现标号从小到大排列的序列,当该序列中存在一个元素使得其标号大于前面所有元素的标号,那么该出栈序列是成立的,例如3241(出现了2比4小但是2在4前面的情况,但是2和4组成的序列中4比前面的3大,所以该组合是成立的。)例如125463(125序列前无元素,默认前面标号为0,所以符合条件,后面还有46序列,但是6比前面的5大,也符合条件,所以这也是成立的)

练习:
在这里插入图片描述
可以按照输出把输出序列写在队列中,看能不能输入成这样的队列顺序

三、广义表

在这里插入图片描述
广义表的元素可以是广义表,所以说是递归形式定义的。广义表中包含的广义表叫子表。长度为元素数,深度是嵌套次数加1。

例一答案:长度为3,深度为2

表头为第一个元素,表尾是除了第一个元素以外的所有元素组成的新的广义表。

例二答案为head(head(tail(LS1)))

四、树与二叉树

4.1 树

在这里插入图片描述
结点的度:结点拥有的孩子结点数。

树的度:所有结点中最高的度数

叶子结点:没有孩子结点的结点(度为0的结点)为叶子结点

分支结点:度数不为0的结点

内部节点:除了根结点和叶子结点以外的结点

父结点子结点是相对的概念

兄弟结点:具有同一个父结点的结点互称兄弟结点

4.2 二叉树

在这里插入图片描述
满二叉树:每个结点要么有两个子结点,要么本身是叶子结点

完全二叉树:除去最下层以后二叉树为满二叉树,且最下层是由左到右顺序排列,即缺的结点是在最下层右侧的结点。

其余二叉树均是非完全二叉树。

二叉树重要特性如图。注意特性4中i/2是向下取整。

4.3 二叉树的遍历

在这里插入图片描述

层次遍历:每层从左到右遍历
12345678

前中后序遍历的前中后指的是根结点在什么时候被遍历的。

前序遍历:先访问根结点,再访问左子树结点,最后访问右子树结点。
12457836

中序遍历:先访问左子树结点,再访问根结点,再访问右子树结点。
42785136

后序遍历:先访问左子树结点,再访问右子树结点,再访问根结点。
48752631

4.4 反向构造二叉树

在这里插入图片描述
有前序和中序,或中序和后序可以推出二叉树,如果仅仅有前序和后序不可推出。

前序序列得到A是根结点,带入中序序列中知道A的左结点中序序列为HBEDF,右结点序列为GC。

前序序列得到B是左子树根结点,带入中序序列中知道B的左结点中序序列为H,右结点为EDF。

前序序列中查找EDF的顺序,可知F在ED的前面,所以F是根结点,带入中序序列,知道左结点中序序列为ED。

进一步分析:D是根结点,E是D的左子结点。以此类推。

结果:
在这里插入图片描述

4.5 树转二叉树

在这里插入图片描述
结点的孩子结点都将成为它的左子树结点,其兄弟结点将成为它的右子树结点。

简易求法:每个结点只保留最左边的线,其他线全部去掉,然后把所有兄弟结点连起来,把这些线向下稍稍旋转即可得到。

4.6 查找二叉树

在这里插入图片描述
查找二叉树是一类比较特殊的二叉树。特性:根结点的左子树结点都比根结点的值小,右子树的值都比根结点的值大。这种二叉树称为查找二叉树,也叫排序二叉树。

意义:能够极大提高查询的速度和效率。

插入和删除规则如图。其中删除规则第三条以89为例,要删除89,则中序遍历89的左子树,查找值最大的结点,为56,则将56的值覆盖原来的值为89的结点,即89被删除,新的值为56,其次按照第二条规则把56删除,其左结点51和48直接相连。

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


最优二叉树又称哈夫曼树,是一种工具,用来哈夫曼编码。哈夫曼编码是一种压缩编码方式,能让原始信息编码长度更短一些,从而节省存储空间和传输带宽,属于无损压缩的方式。

带权路径长度,其中权是某个叶子结点的某个字符出现的频度。带权路径长度为路径长度乘以这个叶子结点的权。

例如图中左边第一棵树,叶子结点2的带权路径长度为22=4,叶子结点4为43=12,叶子结点8为83=24,叶子结点1为11=1。树的带权路径长度为所有叶子节点的带权路径长度之和,也称树的代价。

哈夫曼树的理念是令树的带权路径长度最小,即树的代价最小。

构造哈夫曼树方法:以图中例题为例

在整个数列当中选择两个权值最小的构成一棵小树,选择3,5,得到小树的根结点权为8,将权值序列的3,5删除,增加权值8,即29,7,8,14,23,11,8。在序列里找出两个权值最小的即7,8,同理序列删除7,8,增加15。再选8和19,序列加个19.。。以此类推得到哈夫曼树。

从此可以看出,只有叶子结点是初始权值,其他的值是我们构造出来的。

4.8 线索二叉树

在这里插入图片描述
线索二叉树提出的意义:二叉树很多结点有空的指针,把空闲的资源利用起来方便便利,就提出了线索二叉树。

前序线索是按照前序遍历序列找线索,中序后序以此类推。

以前序线索二叉树为例,前序遍历序列为ABDEHCFGI,看叶子结点D有两个空指针,左指针指向该序列中D的前一个结点B,右指针指向该序列中其后面的结点E。

其他线索二叉树以此类推。

4.9 平衡二叉树

在这里插入图片描述
对于一个数列来说,其排序二叉树并不唯一。有的排序二叉树效率较高,有的效率较低。一个排序二叉树越平衡,查找效率越高。

图中给出平衡二叉树定义,其中,每个结点的平衡度为左子树深度减右子树深度。

数字大小在序列中靠中间的数字做根结点,排序二叉树会比较平衡。

五、图

5.1 基本概念

在这里插入图片描述
左图为无向图,右图为有向图。

5.2 图的存储

图的存储有两种方式,第一种方式是邻接矩阵:
在这里插入图片描述
矩阵的大小取决于点的数量,总共有五个点,所以邻接矩阵是5*5的二维表。行号和列号均为每个点的编号。

对角线代表自己和自己没有边所以都为0。两点之间有边则值为1,如1和2有边,所以第一行第二列为1,以此类推。

对于无向图来说,邻接矩阵为对称矩阵,可以只存上三角或下三角的信息。

第二种方式是邻接表:
在这里插入图片描述
比如V1结点作为头结点,链表存储相邻结点号及其间距离的值。数组记录各个结点。

5.3 图的遍历

在这里插入图片描述
图的遍历包括深度优先遍历和广度优先遍历。

5.4 拓扑排序

在这里插入图片描述

拓扑排序指的是用一个序列来表达哪些事件可以先执行,哪些可以后执行。

拓扑排序可能有多个序列。

5.5 图的最小生成树

在这里插入图片描述
图的最小生成树指的是,将图中部分线删去,只留下权值最小的线将所有结点都连接起来。留下的边都是权值小的,是总和最小。

留下来的这部分是生成树,说明是树结构。树和图最大区别在于树没有环路,一棵树结点数为n,则边数最大为n-1,若大于等于n,则一定是图了。

求图的最小生成树算法有两种,第一种是普里姆算法:

从一个结点出发(可以是任意结点),把此节点设为红点集,其他点为蓝点集。找出红点集到蓝点集的最短距离,图中发现A能到BCEF,距离最小的是100,即A到B,被连接的点变成红点集,重复操作发现200最短,E也被连起来作为红点集,250最短,F进入红点集,下一个最短是200(F到D),然后是D到C。这样就形成最小生成树,这些线的值的和确保了是最小的,而且原则是这些线不形成环。

第二种是克鲁斯卡尔算法:

从最短的边开始选起,由于要形成数,边数确定要选5条最短的边,一条一条选下去直到发现下一条边和之前已选的边构成了环路,则弃这条边,选另一个最小的边。

六、算法

6.1 算法的特点

在这里插入图片描述

6.2 算法的复杂度

算法的复杂度分为时间复杂度和空间复杂度。
在这里插入图片描述
时间复杂度:所有常数级语句条数,都认为是常数级时间复杂度用O(1)表示。循环语句循环n次,时间复杂度为O(n),时间复杂度取各部分时间复杂度的最大级,双重循环为O(n²),以此类推。

其中 log ⁡ 2 n {\log _2}n log2n一般和对树的处理有关,比如平衡度很高的排序二叉树中查找键值。

其中 n log ⁡ 2 n {n\log _2}n nlog2n典型代表是堆排序。

空间复杂度消耗的临时的处理交换数据的空间数量。

七、查找问题

7.1 顺序查找

在这里插入图片描述
时间复杂度为O(n)。

7.2 二分查找

在这里插入图片描述
不是所有序列都能用二分查找法的,它要求数列是有序排列。

例:
在这里插入图片描述

注意:两个下标相加除以二后若得到小数,则向下取整。
在这里插入图片描述

7.3 散列表

类似于按内容存储的机制。

在这里插入图片描述
按此规则,如果要存储3和8,各自对5区域,都得到3,这时就涉及到了两种方法:线性探测法和伪随机数法。

线性探测法:三号空间被占,则将8放在三号后面的空间,即四号空间。12在二号空间,此时17本应在二号空间,被占向后移,也被占,以此类推,被存到五号空间。这又使得整体效率降低了。

伪随机数法:当发生地址冲突时候,地址增量为伪随机数序列。

八、排序问题

8.1 排序问题概述

在这里插入图片描述
稳定排序:如图所示一个数列中,有两个元素键值相同,黑色的21在红色的21之前,这样的顺序不会因排序而改变,则为稳定排序。

内排序:在内存中进行排序。

8.2 直接插入排序

在这里插入图片描述
第一步对前两个元素进行比较,顺序确定后,产生有两个元素的队列,第三个元素与队列中元素进行比较从而选择插入的位置,以此类推。

8.3 希尔排序

在这里插入图片描述
实质上是分组的插入排序。经过前面几轮的排序后,最后进行直接插入排序时,数列已经较为有序了,直接插入时就不需要做太多的比较。运用的原理是直接插入排序对于数据较少的数列效率还是可以的,希尔排序尽可能让顺序杂乱的数列切分成若干组,让直接插入排序的压力降低,当最后分组越来越少时,实际上数据的有序程度也提高了,这比直接进行直接插入排序效率要高。

8.4 直接选择排序

在这里插入图片描述
在所有记录中选择最小值,放在首位,其余元素在选择最小值放在剩余元素的首位,以此类推。

8.5 堆排序

堆的概念:
在这里插入图片描述
从图中可以看出,堆的排列方式和完全二叉树的排列方式一致。即所有孩子结点比自身小,为小顶堆,反之为大顶堆。

堆排序:
在这里插入图片描述
步骤为建立堆,取走堆顶,重新建立堆,再取走,以此类推。

初建堆:
在这里插入图片描述
按完全二叉树顺次排列下来,构成图1.1。

着手点在最后一个非叶子结点,即“5”,看其是否大于它的两个孩子,如果是则不变动,但是5<8,此时把“5”孩子结点的最大值与“5”交换。构成图1.2。

下一步调整倒数第二个非叶子结点,即“4”,同理做调整,构成图1.3

下一步调整倒数第三个非叶子结点,即“3”,这个结点调整较为复杂,因为涉及了多级调整。按规则,“3”和“8”应该做调整,构成图1.4,此时有一个问题,“3”换到新位置后又打破了左下角的堆规则,于是按规则“3”和“5”交换位置,得到图1.5。

以此类推,得到图1.7,完成堆的建造。

堆重构:
在这里插入图片描述
我们已经构建好堆,把堆顶元素取走之后,应该把最后一个结点移到根结点的位置,再按照上述方法把堆进行调整。其他元素都已经调整好了,所以只需要调整“20”。

在众多数据中,如果只想排序出前十的数据,而不需要全部排列出来,此方法非常合适。

8.6 冒泡排序

在这里插入图片描述
把第四个数和第三个数比较,若第四个数小于第三个数,则两个数交换位置;在比较第三个数和第二个数,以此类推,得到最小的数且保证其放在第一个位置。然后再从最后面两个数开始作比较,直到全部完成排序。

冒泡排序就是先比较出最小的,再比较出第二小的,以此类推。

8.7 快速排序

在这里插入图片描述
快速排序采用了分治法,把原问题分解成若干规模更小的子问题。用递归的方式解决这些问题。

任取一个数据作为基准,如图所示,最后以基准将数列分成了两个子数列,然后递归使用该方法完成排序任务。

8.8 归并排序

在这里插入图片描述
归并排序指把两个或两个以上的有序子表合并成新的有序表。多个有序表一般采用两两合并的方式。

上图为例,先两两一组,每组一次比较结束就可排序结束,然后再两两合并,以此类推。

8.9 基数排序

在这里插入图片描述
在这里插入图片描述

8.10 排序算法的时间复杂度和空间复杂度

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值