数据结构复习重点
P1数据结构定义
定义:数据结构是描述数据对象和数据对象之间关系的统称
分类:线性结构、非线性结构
数据结构是分层的:
逻辑结构、物理结构、操作及其实现
软件是需要分层次的
P2递归
P2递归(物理过程)
程序自己调用自己的过程
把复杂的问题展开为更小的问题的求解
软工一递归的三角模型不错
压栈->压栈->压栈… ->出栈->出栈->出栈
迭代:
利用变量的原值推算出变量的新值
递归中一定有迭代,迭代不一定是递归
P3算法复杂度
算法:为解决某个问题而进行的一系列操作
空间复杂度 + 时间复杂度
难以精准地得出时间复杂度以及空间复杂度的确切值:数量级
代码优化降低复杂度
大O表示法:上界
Ω表示法:下界
θ表示法:折中——考试使用
P4线性表
逻辑结构 + 物理结构 + 实现
线性表是对象或者值得集合
包含一些基本方法
数组
请求连续内存
查询特定项的复杂度为O(1)
查找某个数的时间复杂度O(n)
删除、插入均为O(n)
链表
不是连续内存
单链表、双链表
查找特定项的时间复杂度为O(n)
移除节点的复杂度为O(1)(其实说法感觉并不准确,毕竟得先查找前一项)
查找前一项的复杂度为O(n)
一些应用
循环链表、双链表一般不考
栈
先进后出
单链表、数组实现栈
栈的使用
队列
先进先出
P5树
树的高度:层数 - 1(如果根为高度0)
二叉树
性质:
n个结点的二叉树之间有n-1条边
第i层的节点数最多是2^i个
如果一棵二叉树有n0个树叶,并且结点度数为2的节点有n2个,则n0=n2+1个
有n个结点的二叉树的高度最大为n-1,最小为log2(n+1)(向上取整)-1
满二叉树
排满
完全二叉树
尽可能排满
物理实现
数组实现
链表实现
*遍历*
深度优先遍历:先序遍历、中序遍历、后序遍历(递归)
广度优先遍历(按层的顺序自上而下自左往右遍历)
存储方式
广义表(不考)
双亲表示法
左子女-右兄弟表示(较为重要)
森林的遍历
1.根据左子女-右兄弟转化为一棵二叉树进行遍历
2.依据树的顺序依次进行相对应的遍历
线索二叉树
目的:加快二叉树的遍历
特点:在树的节点中加入指针
n个结点的二叉树有2n个链域,其中真正有用的是n–1个,其它n+1个都是空域(null)。为了充分利用结点中的空域,使得对某些运算更快,如前驱或后继等运算。
霍夫曼树
构建增长数
计算权重之和,取最小
霍夫曼算法(没太理解课件表达的意思)
思想:权大的外结点靠近根,权小的远离根
算法:从m个权值中找出两个最小值W1,W2构成
霍夫曼编码(应用多)
左0右1
划分二进制编码
搜索树
二叉搜索树
删除算法:
1.本身不属于树,无需操作
2.属于树:
- 无子树:直接删除
- 一棵子树:直接连接
- 两棵子树:选取左子树最大节点或右子树最小节点作为新节点
算法复杂度:O(log2 n)
索引二叉树
leftsize = 左子树大小 + 1
AVL树
AVL树是一棵二叉搜索树
加入平衡因子,即一个节点左右子树高度差不能超过1
AVL树插入:从下往上递归进行旋转处理
**算法思想:**插入一个新结点后,需要从插入位置沿通向根的路径回溯,检查各结点左右子树的高度差,如果发现某点高度不平衡则停止回溯。要确定节点位于外侧还是内侧,决定进行单旋还是双旋
无论哪种情况,内侧、外侧都是针对出现不平衡的节点而言的
左外侧加高:右下旋
右外侧加高:左下旋
左内侧加高:左下旋 + 右下旋(两次旋转的节点不同
右内侧加高:右下旋 + 左下旋
AVL树插入具体步骤:
1.正确插入
2.向上找到最小不平衡树
3.判别插入是在该不平衡树外侧还是内侧
4.根据判定结果,进行单旋或者双旋
AVL树删除
方法:与二叉搜索树一样,不过需根据平衡因子进行调整
B树(粗略了解)
平衡m路搜索树
满足性质:
每个根节点至少两个子女
所有内节点都至少有m/2个子节点(连一半都占不满,简直不像话O(∩_∩)O)
所有外节点必须在同一层
P6散列函数
取余、平方取中、乘法杂凑
散列表冲突问题
- 线性探测(会产生堆积问题)+n
- 二次探测(平方)+n^2
- 双散列哈希 hash1(k) = d hash2(k) = c;if d is not empty,try d + c, d + 2c…(必要时可能进行rehash)
- 分离链接(相当于每个对应编号后面增加长串链表)
P7优先级队列
一个优先级队列是0个或者更多元素的集合。每一个元素都有一个优先级或者值
进入队列的时候有优先级,出队列优先出高优先级的.
- 以下我们确定元素的优先级是通过数字的大小来确定
分类:最小优先级队列、最大优先级队列
最大优先级队列
物理实现:Heap(最大堆),最大堆是一棵完全二叉树,每一个节点的值都大于它的子节点
插入算法:插入在末端,依次与根节点比较大小,看是否需要互换,算法复杂度log2 n
删除算法:将根删除,用最末尾元素替代树根,并进行比较
优先级队列应用
堆排序
求第K个小的元素:N*log N
P7排序
虽然是重点但感觉考不了什么,算法大概看一下,复杂度记一下应该就行了
插入排序
从后向前比较,n^2,稳定的
折半插入排序
折半查找所需比较次数与初始排序无关,仅依赖于对象个数
n*log2 n,稳定
希尔排序
取一增量区间,对每组进行分别排序,并逐渐对半减少增量
与选择缩小的增量有关,不稳定
交换排序
冒泡排序
稳定
快速排序
取一个基准对象,将比它小的和比它大的分别划分在其两侧,在两边的子序列中继续重复相同操作
不稳定,n * log2 n
选择排序
不断选出最大的,不稳定, n^2
锦标赛排序
n*log2 n,稳定
堆排序
上一章节提及,稳定n * log2 n
秩排序
重新启用一个数组用以记录排名
基数排序
不断比较每一位的数字,从而达到排序的目的
归并排序
分治思想
将两个序列分别排序,每次取出各自最小元素进行比较,最后合并
n*log2 n,稳定
P8并查集
感觉不是很重要,一带而过,这部分离散数学应该也有涉及
物理实现:森林(多棵树)根节点存储0,其他节点存储根节点的值
对于并查集性能的一些优化
P9图论
离散数学也有涉及
有向图、无向图
顶点度数 = 出度 + 入度
度数之和 = 边数 * 2
连通图:环
加权图:给边分配权重
邻接矩阵:0和1表示
注意区别无向图和有向图
无向图的每个顶点的度数等于矩阵中每一行的和
有向图的邻接矩阵
- 出度对行求和
- 入度对列求和
加权图(网络)的邻接矩阵
- 注意使用的无穷表示没有通路
图的遍历:深度优先、广度优先
用邻接表:n+e
邻接矩阵:n^2
最小生成树
算法核心:贪心算法
Kruskal算法:
对所有边的权重进行排序,依次选择边,但保证不与先前选出的边构成回路,选取n-1条边
取最小边利用最小堆
时间复杂度有点鬼,算了,懒得记了
Prim算法:
选择一个起点,取与其他顶点权重最小的,将该其他顶点拉入己方,重复上述操作,直至所有顶点均在我方
n^3
优化:以后抽空研究研究
最短路径
核心算法:贪心算法
Dijkstra算法
先对起点到其余各个顶点权重进行排序,选取最小的,加入该点,比较通过改点起始点与其他剩余点的权重大小,再次选取最小的,加入改点,重复上述步骤
n^2
局限性:只适用于含非负权值的路径
贝尔曼-福特算法
n^3
通过遍历更新表格的形式
可适用于含负权值的路径
floyed算法
前提:各边权值均大于0的带权有向图
把有向图的每一个顶点作为源点,重复执行Dijkstra算法n次,执行时间为O(n^3)
活动网络(常考)
AOV网络
先决条件,用弧表示活动间的优先关系
AOV网中,不能出现有向环
拓扑排序
有环图无拓扑排序
算法思想:从图中选择一个入度为0节点输出,删除此节点及其所有出边,重复上述过程,如果最后还有节点,但入度非0,说明原图存在环路
算法实现:AOV网用邻接表来实现数组count存放各顶点的入度,并且为了避免每次从头到尾查找入度为0的顶点,建立入度为0的顶点栈,栈顶指针为top,初始化时为-1
AOE网络(没太看懂)
用边表示活动的网络(AOE网络, Activity On Edge Network)又称为事件顶点网络
有唯一入度为0的开始节点,同时有唯一出度为0的结束节点
- 目的: 利用事件顶点网络,研究完成整个工程需要多少时间 加快那些活动的速度后,可使整个工程提前完成。
- 关键路径:具有从开始顶点(源点)->完成顶点(汇点)的最长的路径
排序算法 线性表(数组、单链表、栈......) 循环链表、双链表一般不考 广义表不考 遍历(常考)、线索化二叉树、AVL树算法流程 开放地址 散列表 邻接多重表不考 五个算法的算法流程 活动网络(常考) 拓扑排序、关键路径算法 快速排序
ps:考完总结,基本往年卷,早知道不整理费那么多时间了,没太看懂的AOE网络考了,学习还是得注意方方面面啊,有问题不能逃避。