2020年中级数据库系统工程师考试笔记3—数据结构与算法

  数据结构(数据结构是计算机存储、组织数据的方式)是指数据元素的集合及元素间的相互关系和构造方法,结构就是元素之间的关系。在数据结构中,元素之间的相互关系是数据的逻辑结构,按照逻辑关系的不同将数据结构分为线性结构和非线性结构。

3.1 本章考点与知识点图谱

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

3.2 线性结构

3.2.1 线性表

  1. 线性表的定义

  一个线性表是n个有限序列(n≥0),通常表示为 ( a 1 , a 2 , … , a n ) (a_1,a_2,…,a_n) (a1,a2,,an),其特点是在非空的线性表中:
(1)存在唯一的一个称作“第一个”的元素;
(2)存在唯一的一个称作“最后一个”的元素;
(3)除第一个元素外,序列中的,每个元素均只有一个直接前驱;
(4)除最后一个元素外,序列中的每个元素均只有一个直接后继。

  1. 线性表的存储结构

(1)线性表的顺序存储:指用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。这种存储方式下,元素间的逻辑关系无须占用额外的空间来存储。
优点:可以随机存取表中的元素,按序号查找元素的速度很快;
缺点:插入和删除操作需要移动元素。
在这里插入图片描述
(2)线性表的链式存储(链表)
线性表的链式存储用节点来存储数据元素,元素的节点地址可以连续,也可以不连续,因此,存储数据元素的同时必须存储元素之间的逻辑关系。另外,节点空间只有在需要的时候才申请,无须实现分配,基本的节点结构:
在这里插入图片描述

  数据域存储数据元素的值,指针域存储当前元素的直接前驱或直接后继元素的位置信息,指针域中所存储的信息称为指针或链,单链表节点中只有一个指针域。

  Head指针不存储实际的数据元素,用于辅助数据元素的定位,方便插入和删除操作。
在这里插入图片描述

  优点:链式存储结构下进行插入和删除,实质是对相关指针的修改,不需要移动元素;

  缺点:只能顺序地访问元素,而不能对元素进行随机存储。

3.链表的类别

扫描二维码关注公众号,回复: 12921008 查看本文章

  根据节点中指针信息的实现方式,有:
(1)单链表:包含两个域,一个信息域和一个指针域,这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值。
在这里插入图片描述
(2)双向链表:每个节点包含两个指针,分别指明当前元素的直接前驱和直接后继信息,可在两个方向上遍历链表中的元素。
在这里插入图片描述
(3)循环链表:表尾节点的指针指向表中的第一个节点,可从表中任意节点开始遍历整个链表。
在这里插入图片描述
(4)静态链表:借助数组来描述线性表的链式存储结构。

3.2.2 栈和队列

  栈和队列与线性表逻辑结构相同,栈按“后进先出”规则进行操作(类似杯子喝水),队列“先进先出”规则进行操作(类似沙漏)。
1.栈:只能通过访问它的一端来实现数据存储和检索操作,按先进后出(FILO:First In Last Out)或后进先出(LIFO)规则进行插入删除操作。在栈中进行插入和删除操作的一端成为栈顶(Top),另一端成为栈底(Bottom)。
2.队列:是一种先进先出(FIFO:First In First Out)线性表,只允许在标的一段插入元素,而在标的另一端删除元素。允许插入元素的一端称为队尾,允许删除元素的一端称为对队头。

3.2.3 串

  串是仅有字符构成的有限序列,是取值范围受限的线性表。

  PS:2020年11月08日上午题选择题就考了线性表、栈、队列和串的概念题。

3.3 数组和矩阵

  数组可看作是线性表的推广,其特点是多维数组的数据元素仍然是一个表。

  从历年真题来看,本节考点为0,印象里有1道选择题是判断矩阵元素位置的有涉及到,应试来说可放弃本节内容,当然最好学一学,毕竟技多不压身。

3.4 树和图

3.4.1 树和二叉树

3.4.1.1 树

  树是n(n≥0)个节点的有限集合,当n=0时称为空树,在任一非空树(n>0)中,有且仅有一个称为根的节点,其余节点可分为m(m≥0)个互不相交的有限集 T 1 , T 2 , … , T m T_1,T_2,…,T_m T1,T2,,Tm,其中每个集合又是一棵树,并且称为根节点的子树。
在这里插入图片描述

  树相关术语:

  • 双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点,如上图中B节点是E、F节点的双亲节点;
  • 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点,如上图中B、C、D是A的子节点;
  • 兄弟节点:具有相同双亲节点的节点互称为兄弟节点,B、C、D和E、F互为兄弟节点;
  • 节点的度:一个节点含有的子树的个数称为该节点的度;
  • 叶子节点或终端节点:度为0的节点称为叶子节点,如上图C、E、F、G;
  • 非终端节点或分支节点:度不为0的节点;
  • 树的度:一棵树中,最大的节点的度称为树的度;
  • 节点的层次:从根开始定义,根为第1层,根的子节点为第2层,以此类推;
  • 树的高度或深度:树中节点的最大层次,上图中树的深度为2;
  • 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
  • 有序(无序)树:若将树中节点的各子树看成是从左到右具有次序的,即不能交换,则称该树为有序树,否则称为无序树。
  • 森林:m(m>=0)棵互不相交的树的集合;

3.4.1.2 二叉树

  二叉树是n(n≥0)个节点的有限集合,它或者是空树(n=0),或者是由一个根节点及两颗不相交的、分别称为左子树和右子树的二叉树所组成,简单来说,就是度不超过2的树(节点最多有两个叉)。
在这里插入图片描述

  树和二叉树的区别:

  • 二叉树中节点的子树要区分左子树和右子树,即使在节点只有一颗子树的情况下也要明确指出该子树是左子树还是右子树,树种则不区分;
  • 二叉树中节点的最大度为2,而树中不限制节点的度数。
    二叉树的性质:
  • 二叉树第 i i i层( i ≥ 1 i≥1 i1)上至多有 2 i − 1 2^{i-1} 2i1个节点;
  • 深度为k的二叉树至多有 2 k − 1 2^k-1 2k1个节点 ( k ≥ 1 ) (k≥1) k1;
  • 对任何一棵二叉树,若其终端节点数为 n 0 n_0 n0,度为2的节点数为 n 2 n_2 n2,则 n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1
  • 具有n个节点的完全二叉树的深度为 ⌊ l o g 2 n + 1 ⌋ ⌊log_2^n+1⌋ log2n+1

小知识科普:
向下取整函数 f l o o r ( x ) = ⌊ x ⌋ floor(x)=⌊x⌋ floor(x)=x:小于或等于 x x x的最大整数;
向上取整函数 c e i l ( x ) = ⌈ x ⌉ ceil(x)=⌈x⌉ ceil(x)=x:大于或等于 x x x的最小整数。

3.4.1.3 满二叉树和完全二叉树

  满二叉树:一个二叉树(深度为k),每一个层的节点数都达到最大值 2 k − 1 2^k-1 2k1

  完全二叉树:当深度k、有n个节点的二叉树,其每一个节点都与深度为k的满二叉树中编号为1~n的节点一一对应。叶子节点只能出现在最下层和次下层,并且最下面一层的节点都集中在该层最左边的若干位置的二叉树。
在这里插入图片描述
在这里插入图片描述

  满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树。

3.4.1.4 二叉树的存储结构

1.顺序存储

  用一组地址连续的存储单元存储二叉树中的节点,必须把节点排成一个适当的线性序列,并且节点再这个序列中的相互位置能反映出节点之间的逻辑关系。

  显然,顺序存储结构对完全二叉树而言既简单又节省空间,而对于一般二叉树来说浪费空间了,不适用。
在这里插入图片描述
2.链式存储

  由于二叉树中节点包含有数据元素、左子树根、右子树根及双亲等信息,因此可以用三叉链表或二叉链表(即一个节点含有3个指针或2个指针)来存储二叉树,链表的头指针指向二叉树的根节点。
在这里插入图片描述

3.4.1.5 二叉树的遍历

  遍历是按某种策略访问树中的每个节点,且仅访问一次。
按照遍历左子树要在遍历右子树之前进行的约定,依据访问根节点的位置的不同,可以得到二叉树的前序、中序和后序三种遍历方法。(2020年11月08日上午题选择题)
1.前序遍历(根→左→右):访问根结点的操作发生在遍历其左右子树之前,若二叉树非空,操作步骤:
(1)访问根节点;
(2)遍历左子树;
(3)遍历右子树。
2.中序遍历(左→根→右):访问根结点的操作发生在遍历其左右子树之中(间),若二叉树非空,操作步骤:
(1)中序遍历左子树;
(2)访问根节点;
(3)中序遍历右子树。
3.后序遍历(左→右→根):访问根结点的操作发生在遍历其左右子树之后,若二叉树非空,操作步骤:
(1)遍历左子树;
(2)遍历右子树;
(3)访问根节点。
4.层次遍历:按层自上而下,自左而右逐层访问树中各层节点。
在这里插入图片描述

3.4.1.6 最优二叉树

  最优二叉树又称为哈夫曼树,是一类带权路径长度最短的树。

  • 路径长度:从树中一个节点到另一个节点之间的通路称为节点间的路径,该通路上分支数目。
  • 树的路径长度:树根到每一个叶子之间的路径长度之和。
  • 节点的带权路径长度:从该节点到树根之间的路径长度与该节点权的乘积。

  树的带权路径长度为树中所有叶子节点的带权路径长度之和,记为:
在这里插入图片描述
  其中 n n n为带权叶子节点数目, w k w_k wk为叶子节点的权值, l k l_k lk为叶子节点到根节点的路径长度,根据定义,如下 b b b图的为最优二叉树。
在这里插入图片描述

3.4.1.7 二叉查找树

  二叉查找树又称为二叉排序树,它或者是一棵空树,或者是具有如下性质的二叉树:

1.若其左子树非空,则其左子树中每个节点的值(关键码)都小于该节点值(关键码);
2.若其右子树非空,则其右子树中每个节点的值(关键码)都大于该节点值(关键码);
3.左、右子树本身就是2棵二叉查找树。

  对二叉树进行中序遍历,可得到一个关键码递增有序的节点序列,使用二叉查找树来查找树中的数值比普通的二叉树更方便。
在这里插入图片描述

3.4.2 图

  图是比树结构更复杂的一种数据结构,在图结构中,任意两个节点之间都可能有直接的关系,所以图中一个节点的前驱和后继的数目是没有限制的

1.有向图:图中每条边都是有方向的,从顶点 v i v_i vi v j v_j vj的有向边 < v i , v j > <v_i,v_j> <vi,vj>, v i v_i vi称为弧尾, v j v_j vj称为弧头, < v i , v j > <v_i,v_j> <vi,vj> < v j , v i > <v_j,v_i> <vj,vi>为两条弧。
2.无向图:图中每条边都是无方向的, < v i , v j > <v_i,v_j> <vi,vj> < v j , v i > <v_j,v_i> <vj,vi>为同一条边。
3.完全图:一个无向图具有 n n n个顶点,且每个顶点与其他 n − 1 n-1 n1个顶点之间都有边则称为无向完全图, n n n个顶点的无向完全图的弧数目为 n ( n − 1 ) / 2 n(n-1)/2 n(n1)/2 n n n个顶点的有向完全图的弧数目为 n ( n − 1 ) n(n-1) n(n1),因为任意两个不同顶点之间都存在方向相反的两条弧。

  图的存储结构:

1.邻接矩阵表示法:利用一个矩阵来表示图中顶点之间的关系;
2.邻接链表表示法:为图中的每个顶点建立一个单链表,第 i i i个单链表中的节点表示依附于定点 v i v_i vi的边(对于有向图是以 v i v_i vi为尾的弧)。

  从历年真题来看目前来看图的知识点还不在考官的兴趣范围内,这部分根据个人需求看要不要照本研习一下,本人已放弃。

3.5 常用算法

高大上章节,有内涵有深度!

  计算机程序从根本上看包括两方面内容:一是对数据的描述,二是对操作(运算)的描述。

3.5.1 排序

  假设含有 n n n个记录的文件内容为 { R 1 , R 2 , … , R n } \{ {R_1,R_2,…,R_n}\} { R1,R2,,Rn},其相应的关键字为 { k 1 , k 2 , … , k n } \{ {k_1,k_2,…,k_n}\} { k1,k2,,kn}

  常见的内部排序算法:
1.直接插入排序:在插入第i个记录时, R 1 , R 2 , … , R i − 1 {R_1,R_2,…,R_{i-1}} R1,R2,,Ri1已经排好序,这时将记录 R i R_i Ri的关键字依次与关键字 k i − 1 , k i − 2 , … , k 1 k_{i-1},k_{i-2},…,k_1 ki1,ki2,,k1进行比较,从而找到 R i R_i Ri应该插入的位置,插入位置及其后的记录依次向后移动。

  待排序列:42 16 81 37 65
① 42
② 12 42
③ 12 42 81
④ 12 37 42 81
⑤ 12 37 42 65 81
2.冒泡排序:首先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序,则交换两个记录的值,然后比较第二个记录和第三个记录的关键字,以此类推,直至第n-1个记录和第n个记录的关键字比较完为止。
待排序列:35 12 67 29 51
在这里插入图片描述

3.简单选择排序:通过次关键字之间的比较,从个记录中选出关键字最小的记录,并和第个记录进行交换,当i等于n时所有记录有序排列。
待排序列:42 16 81 37 65
在这里插入图片描述
4.希尔排序:又称为“缩小增量排序”,是对直接插入排序方法的改进,先将整个待排记录序列分割成若干个子序列,然后分别进行直接插入排序,待整个序列中的记录基本有序时,再对全体记录进行一次直接插入排序。
待排序列:42 16 81 37 65 11 26 72
(1)初始增量d1=length/2=4,序列分为4组:[42,65],[16,11],[81,26],[37,72],执行直接插入排序,结果:42 11 26 37 65 16 81 72
在这里插入图片描述
(2)缩小增量d2=4/2=2,序列分为[42,26,65,81],[11,37,16,72],执行直接插入排序,结果:26 11 42 16 65 37 81 72
在这里插入图片描述
(3)再次缩小增量d3=2/2=1,对序列26 11 42 16 65 37 81 72执行直接插入排序,结果:11 16 26 37 42 65 72 81

5.快速排序:通过一趟排序将待排的记录划分为独立的两部分,称为前半区和后半区,其中,前半区中记录的关键字均不大于后半区记录的关键字,然后再分别对这两部分记录继续进行快速排序,从而是整个序列有序。

  具体做法:设置两个变量i(i=0,指向序列的第一个记录)、j(j=n-1,指向序列的最后一个记录),以第一个数组元素作为关键数据pivot,从j开始向前搜索,即由后开始向前搜索(j- -),找到第一个小于pivot的值与变量i的值互换位置;再从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于pivot的值与变量j的值互换位置,重复这两步,直到i=j。

  待排序列:39 58 32 47 46 19 25 55
在这里插入图片描述
6.堆排序:对一组待排序记录的关键字,首先把它们按堆的定义排成一个序列(即建立初始堆),从而输出堆顶的最小关键字(对于小顶堆而言)。然后将剩余的关键字再调整成新堆,便得到次小的关键字,如此反复,直到全部关键字排成有序序列为止。

  根据堆含义,完全二叉树中所有非终端节点的值均不大于或不小于其左右孩子结点的值;每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
在这里插入图片描述
7.常见的内部排序算法—归并排序:把一个有 n n n个记录的无序文件看成是由 n n n个长度为1的有序子文件组成的文件,然后进行两两归并,得到 ⌈ n 2 ⌉ ⌈\frac{n}{2}⌉ 2n个长度为2或1的有序文件,再两两归并,如此重复,直至最后形成包含 n n n个记录的有序文件为止。这种反复将两个有序文件归并成一个有序文件的排序方法称为两路归并排序。
在这里插入图片描述

  个人觉得书本的讲得略生涩,可以参知乎网友的分享,GIF图形象展示各排序的方法步骤:https://zhuanlan.zhihu.com/p/41923298。

  下图总结来自紫依教学视频:
在这里插入图片描述

3.5.3 查找算法

  查找表是指由同一类型的数据元素(或记录)构成的集合,分为静态查找表(只进行查找和检索操作)和动态查找表(还可进行插入和删除操作)。

  对于查找算法来说,其基本操作是“将记录的关键字与给定值进行比较”,因此,通常以“其关键字和给定值进行过比较的记录个数的平均值”作为衡量查找算法好坏的依据。为确定记录在查找表中的位置,需和给定值进行比较的关键字的个数的期望值,称为查找算法在查找成功时的平均查找长度。

  对于含有 n n n个数据元素的查找表,查找成功的平均查找长度为:
在这里插入图片描述
   P i P_i Pi为查找表中第 i i i个数据元素的概率,一般为 1 n \frac{1}{n} n1 C i C_i Ci为找到第 i i i个数据元素时已经比较过的次数。

1.顺序查找

  从表中的一段开始,逐个进行记录的关键字和给定值的比较,罗找到一个记录的关键字与给定值相等,则查找成功;若整个表中的记录均比较过,仍未找到关键字等于给定值的记录,则查找失败。

  顺序查找是对顺序存储和链式存储方式的查找表都适用,优点算法简单且适用面广,缺点查找效率较低。

  在等概率的情况下,顺序查找成功的平均查找长度为:
在这里插入图片描述
2.折半查找(二分查找)

  折半查找基本思想:先令查找表中间位置记录的关键字和给定值比较,若相等,则查找成功;若不等,则缩小范围,直至新的查找区间中间位置记录的关键字等于给定值或者查找区间没有元素时(表名查找不成功)为止。

  折半查找的平均查找长度为:
在这里插入图片描述

  折半查找比顺序查找的效率要高,但它要求查找表进行顺序存储并且按关键字有序排列,因此,折半查找适用于表不易变动,且经常进行查找的情况。
在这里插入图片描述
3.索引顺序查找

  索引顺序查找又称分块查找,是对顺序查找方法的一种改进。

  在分块查找过程中,首先将表分成若干块,每一块中关键字不一定有序,但块之间是有序的,即后一块中所有记录的关键字均大于前一个块中最大的关键字。此外,还建立一个“索引表”,索引表按关键字有序。
在这里插入图片描述
4.树表查找

  二叉查找树是一种动态查找表,其特点是表结构本身是在查找过程中动态生成的,即对于给定值key,若表中存在关键字等于key的记录,则查找成功返回,否则插入关键字等于key的记录。

  设关键字序列为{46,25,54,13,29,91}
在这里插入图片描述
5.哈希查找

  前面几种查找方法,由于记录的存储位置与其关键码之间不存在确定的关系,所以查找时都要通过一系列对关键字的比较,才能确定被查记录在表中的位置,即这类查找方法都建立在对关键字进行比较的基础之上。

  哈希表思想:依据记录的关键码直接得到对应的存储位置,即要求记录的关键码与其存储位置之间存在一一对应的关系,通过这个关系,能很快的由关键码找到记录。

  哈希函数:关键字作为自变量,关键字存放的地址作为因变量。
在这里插入图片描述

  冲突:对于某个哈希函数Hash和两个关键字 K 1 K_1 K1 K 2 K_2 K2,如果 K 1 ≠ K 2 K_1≠K_2 K1=K2 H a s h ( K 1 ) = H a s h ( K 2 ) Hash(K_1)=Hash(K_2) Hash(K1)=Hash(K2),则称为冲突,对哈希函数来说, K 1 K_1 K1 K 2 K_2 K2称为同义词。

  采用哈希法主要考虑的两个问题是哈希函数的构造和冲突的解决。

  冲突处理:开放定址法、链地址法、再哈希法等。
(1)开放定制法
在这里插入图片描述
   H a s h ( k e y ) Hash(key) Hash(key)为哈希函数, m m m为哈希表的表长, d i d_i di为增量序列。

  • d i = 1 , 2 , 3 , … , m − 1 d_i=1,2,3,…,m-1 di=1,2,3,,m1,称为线性探测再散列。

  • d i = 1 2 , − 1 2 , 2 2 , − 2 2 , 3 2 , … , ± k 2 ( k ≤ m / 2 ) d_i=1^2,-1^2,2^2,-2^2,3^2,…,±k^2(k≤m/2) di=12,12,22,22,32,,±k2(km/2),称为二次探测再散列。

  • d i = d_i= di=伪随机序列,称为随机探测再散列。

(2)链地址法

  链地址法是一种经常使用且很有效的方法,它将具有相同哈希函数值得记录组织成一个链表,当链域的值为NULL时,表示已没有后继记录。

  用链地址法解决冲突构造的哈希表中查找元素,就是根据哈希函数得到元素所在链表的头指针,然后在链表中进行顺序查找的过程。

3.5.3 图的相关算法

  生成树:设图 G = ( V , E ) G=(V,E) G=(V,E)是个连通图,如果其子图是一棵包含 G G G的所有顶点的树,则该子图成为 G G G的生成树。
在这里插入图片描述

  对于连通图来说,边是带权值的,生成树的各边也都带权值,于是就把生成树各边的权值总和成为生成树的权,把权值最小的生成树称为最小生成树,求最小生成树最常用的两种算法:

1.普利姆算法:以顶点为准,从已选顶点所关联的未选边中找出权重最小的边,并且生成树不存在环。
2.克鲁斯卡尔算法:以边为主,找权值最小的边。
3.求单源点的最短路径算法:是指给定带权有向图 G G G和源点 v 0 v_0 v0,求从 v 0 v_0 v0到G中其余各顶点的最短路径,按路径长度递增的次序产生最短路径的算法。

说明:
1.疏忽、遗漏、错误之处,欢迎留言批评指正。
2.至此第3章书本教程知识点总结结束,后续会继续完善补充本章的历年真题,转载请注明出处,整理不易,谢谢!

猜你喜欢

转载自blog.csdn.net/u010257584/article/details/109721946