Prim算法(求最小生成树)
- 将最小生成树中的顶点作为一个集合,非最小生成树中的顶点作为另外一个集合。1 索引最小优先队列存储所有的横切边;2 edgeTo数组存储当前顶点和最小生成树之间的最短边;3 distTo数组表示当前顶点和最小生成树之间的最短边的权重,初始值为无穷大;4 marked数组标识当前顶点是否在最小生成树中,如果在,值为true,如果不在,值为false;
- 选取起点0,令distTo[0] = 0.0,并将该点加入到索引最小优先队列中pq.insert(0, 0.0);
- 调用索引最小优先队列的delMin(),将当下最小横切边对应的顶点加入最小生成树的集合中(标记该顶点:marked数组中该顶点值设为true)。同时遍历该顶点的邻接表,更新edgeTo和distTo,并新增或更新横切边(更新索引最小优先队列);
- 重复3,直到索引最小优先队列为空,最终edgeTo数组里存储的就是最小生成树的边;
Kruskal算法(求最小生成树)
- 使用最小优先队列PriorityQueue存储所有边,每次使用.delMin()取出权重最小的边,并得到该边关联的两个顶点v和w;
- 通过并查集判断v和w是否已经连通,如果连通,则证明这两个顶点在同一棵树中,那么就不能把这条边添加到最小生成树中,因为在最小生成树的任意两个顶点上添加一条边,都会形成环,而最小生成树不能有环的存在;如果不连通,则通过并查集把顶点v所在的树和顶点w所在的树合并成一棵树,并把这条边加入到一个队列中;
- 直到队列中含有V-1条边(图中共V个顶点),最终队列中存储的就是最小生成树的所有边;
Dijstra算法(求最短路径)
思想
- 找出权重最小的顶点;
- 对于该顶点的邻居,检查是否有前往它们的更短路径,如果有,就更新其权重(松弛);
- 重复这个过程,直到对图中的每个顶点都这样做了;
实现
- edgeTo存储起点到当前顶点的最短路径的最后一条边,distTo存储起点到当前顶点的最短路径的总权重;
- 给定图G和起点s,初始化s到s的最短路径的总权重distTo[s]=0,起点s到其他顶点的总权重为无穷大;
- 借助索引最小优先队列(每次找出权重最小的顶点)使用松弛技术处理图的各个顶点,更新edgeTo、distTo及索引最小优先队列,直到索引最小优先队列为空,最终就得到了最短路径树;
拓扑排序
- 拓扑排序:给定一幅有向图,将所有的顶点排序,使得所有有向边均从排在前面的顶点指向排在后面的顶点,这样就可以明确地表示出每个顶点的优先级;
- 实现:基于一幅图,先检测有没有环;如果没有环,再调用顶点排序;
- 检测是否有环:对每个顶点调用深度优先搜索,如果当前顶点正在搜索,则把对应的onStack数组中的值改为true,标识进栈;如果当前顶点搜索完毕,则把对应的onStack数组中的值改为false,标识出栈;如果即将要搜索某个顶点,但该顶点已经在栈中,则图中有环;
- 顶点排序:添加一个栈用来存储顶点,当进行深度优先搜索时,每搜索完毕一个顶点,就把该顶点放入到栈中,如此就实现了顶点排序;
二分查找和二叉搜索树比较
- 二分查找针对顺序存储结构,且是有序的,比较次数少,查找速度快O(logn),插入删除困难;
- 二叉搜索树是链式存储结构,左小于中小于右,查询速度也比较快O(logn),但如果退化为链表比较慢O(n),插入删除容易;
- 如果数据查询多插入删除少且要求有序,就用顺序存储结构,二分查找;如果数据插入删除多,就用链式存储结构的二叉搜索树;