(此文为王道数据结构学习笔记,只供个人后续复习使用,若有错误,还望指出我改正,谢谢)
有向无环图(DAG图):不存在环路的有向图
Step 1:把各个操作数不重复地排成一排
Step 2:标出各个运算符的生效顺序(先后顺序有点出入无所谓)
Step 3:按顺序加入运算符,注意“分层”
Step 4:从底向上逐层检查同层的运算符是否可以合体
拓扑排序
AOV网:用顶点表示活动的图,即每个顶点代表一个要做的事情
拓扑排序:找到做事的先后顺序,有回路的AOV图则不存在拓扑排序
求一个AOV网的拓扑排序
bool TopologicalSort(Graph G){
IniiStack(S); //初始化栈,存入度为0的点
for(int i=0;i<G.vexnum;i++)
if(indegree[i]==0)
Push(S,i); //将所有度为0的点入栈
int count=0; //记录当前已经输出的顶点数
while(!IsEmpty(S)){ //栈不为空,则存在入度为0的点
Pop(S,i); //栈顶元素出栈
print[count++]=i;//输出顶点i
for(p=G.vertices[i].firstarc;p;p=p->nextarc){
//将所有i指向的点入度减1,并且将入度减为0的点压入栈
v=p->adjvex;
if(!(--indegree[v]))
Push(S,v); //入度为0,则入栈
}
}
if(count<G.vexnum)
return false; //有回路,排序失败
else
return true; //拓扑排序成功
}
逆拓扑排序:将入度改为考虑出度即可
逆拓扑排序可使用DFS算法实现
关键路径
AOE网:顶点表示瞬时事件,有向边表示持续活动,权值为该活动的开销
AOE网具有以下两个性质:
①只有在某顶点所代表的事件发生后,从该顶点出发的各有向边所代表的活动才能开始;
②只有在进入某顶点的各有向边所代表的活动都已结束时,该顶点所代表的事件才能发生。
另外,有些活动是可以并行进行的;
在AOE网中仅有一个入度为0的顶点,称为开始顶点(源点),它表示整个工程的开始;也仅有一个出度为O的顶点,称为结束顶点(汇点),它表示整个工程的结束。
从源点到汇点的有向路径可能有多条,所有路径中,具有最大路径长度的路径称为关键路径,而把关键路径上的活动称为关键活动。完成整个工程的最短时间就是关键路径的长度,若关键活动不能按时完成,则整个工程的完成时间就会延长。
事件 Vk 的最早发生时间 ve(k) ——决定了所有从v开始的活动能够开工的最早时间
活动 ai 的最早开始时间 e(i) ——指该活动弧的起点所表示的事件的最早发生时间
事件 Vk 的最迟发生时间 vl(k) ——它是指在不推迟整个工程完成的前提下,该事件最迟必须发生的时间。
活动 ai 的最迟开始时间 l(i) ——它是指该活动弧的终点所表示事件的最迟发生时间与该活动所需时间之差。
事件余量 d(i) = l(i) - e(i) ——表示在不增加完成整个工程所需的总时间的情况,活动 ai 可以拖延的时间,若一个活动的时间余量为0,则说明该活动必须如期完成,为关键活动
求关键路径的步骤:
求所有事件的最早发生时间ve():按拓序列
求所有事件的最迟发生时间vl():按逆拓扑序列
求所有活动的最早发生时间e()
求所有活动的最迟发生时间l()
求所有活动的时间余量d(),d(i)=0的活动就是关键活动,由关键活动可得关键路径
查找
查找——在数据集合中寻找满足某种条件的数据元素的过程称为查找
查找——在数据集合中寻找满足某种条件的数据元素的过程称为查找
查找表(查找结构)——用于查找的数据集合称为查找表,它由同一类型的数据元素(或记录)组成。(图、表等)
关键字——数据元素中唯一标识该元素的某个数据项的值,使用基于关键字的查找,查找结果应该是唯一的。
只进行查找符合条件的数据元素——静态查找表
查找外,需要插入、删除——动态查找表
查找长度——一次查找中需要对比关键字的次数
平均查找长度(ASL)——按概率算比较次数的平均值(通常分成功和失败两种平均查找长度)
顺序查找:又叫线性查找,通常用于线性表
算法思想:从头到尾进行遍历查找
顺序查找的实现
typedef struct{//查找表的数据结构(顺序表)
ElemType *elem;//动态数组基址
int TableLen;//表的长度
}SSTable;
//顺序查找
int Search_Seq( SSTable ST,ElemType key){
int i;
for(i=0; i<ST.TableLen && ST.elem[i] !=key; ++i) ;
//查找成功,则返回元素下标;查找失败,则返回-1
return i==ST.TableLen? -1 : i;
}
顺序查找的实现(哨兵):0号位置存哨兵(无需判断是否越界,效率稍高一点)
int Search_Seq( SSTable ST,ElemType key){
ST.elem[o]=key;//哨兵
int i;
for(i=ST.TableLen; ST.elem[i] !=key; --i) ;
//查找成功,则返回元素下标;查找失败,则返回0
return i;
}
成功ASL = ( 1 / n ) * ( 1 + 2 + 3 + 4 + ... + n ) = ( n + 1 ) / 2 O(n)时间复杂度
失败ASL = n + 1 O(n)时间复杂度
顺序查找的优化:
对于有序表,当一个元素不可能位于某一元素后序时,停止继续遍历
对于被查概率不相等,将被查概率大的放在靠前位置
折半查找(二分查找)适用于有序的顺序表
设定头尾指针low high,以及中间指针mid,mid=(low+high)/2
每次判断目标与mid的大小,如果大于mid,则将low=mid+1,重新计算mid;如果小于mid,将high=mid-1,重新计算mid,重复上述操作,直到目标元素与mid相等,则查找成功,反之失败。
int Binary_Seach(SSTable L,ElemType key){
int low=0,high=L.TableLen-1,mid;
while(low<=high){
mid=(low+high)/2;
if(L.elem[mid]==key)
return mid;
else if(L.elem[mid]>key)
high=mid-1;
else
low=mid+1;
}
return -1;
}
折半查找判定树:二叉平衡树
时间复杂度O(LOG2 n)