1、拓扑排序
void topsort() throws CycleFoundException{
Queue<Vertex> q = new Queue<>();
// 序号
int counter = 0;
for each Vertex v:
if(v.indegree == 0)
q.add(v);
while(!q.isEmpty()) {
Vertex v = q.poll();
v.topNum = ++ counter;
for each Vertex w adjacent to v :
if(-- w.indegree == 0)
q.add(w);
}
if(counter != VETICES_NUM)
throw new CycleFoundException();
}
2、最短路径算法
就目前的算法,求从源s到目的地d的最短路径的复杂度,和求s到其他所有点的复杂度相同
(1)Dijkstra 迪杰斯特拉算法
void dijkstra(Vertex s) {
for each Vertex v{
v.dist = Infinity;
v.known = false;
}
s.dist = 0;
while(there is an unknown vertex) {
Vertex v = smallest unknown vertex;
v.known = true;
for each Vertex w adjacent to v{
if(!w.known && v.dist + dvw < w.dist) {
w.dist = v.dist + dvw;
w.path = v;
}
}
}
}
O(|E| + |V| * |V|),E是边数,V是顶点数,如果用堆找最小距离的点复杂度是O(|E| + |V|log|V|)
|E|一般和|V| * |V|近似,复杂度总体上是O(n2),n是顶点数
(2)Bellman-Ford(贝尔曼——福特算法)
boolean bellman_Ford(Vertex s) {
for each Vertex v:
v.dist = Infinity;
s.dist = 0;
// 对每条边松弛|V| - 1次
for i in range(|V| - 1):
for each edge Evu:
if(u.dist > v.dist + duv) {
u.dist = v.dist + duv;
u.path = v;
}
// 如果没有松弛完毕说明有负值圈,返回false
for each edge Euv:
if(u.dist > v.dist + duv)
return false;
return true;
}
O(|V| * |E|),对每条边松弛|V| - 1次,O(n3)的复杂度
(3)Floyd算法,动态规划算法
for(int k = 0; k < n; k ++)
for(int i = 0; i < n; i ++)
for(int j = 0; j < n; j ++) {
if(d[i][j] > d[i][k] + d[k][j]) {
d[i][j] = d[i][k] + d[k][j];
path[i][j] = k;
}
}
O(n3),n是边数。假设所有的点只能经由前k个点到达,k++直到k==n,动态规划
3、最小生成树算法
(1)Prim算法
类似Dijkstra,将如下中的v.dist + dvw改成v.dist,即不是路径最小,只是到树上任一节点的距离最小
if(!w.known && v.dist + dvw < w.dist) {
w.dist = v.dist + dvw;
w.path = v;
}
(2)Kruskal算法
利用并查集union-find,贪心算法,每次找到最小的边,如果边的两个端点有一个不在树上,则加上,如果都在树上继续找最小的边
4、哈夫曼树
带权路径长度最短的二叉树,可用于编码,权值即为字符出现的次数
每次取出两个权值最小的子树,生成新的子树,重复这一过程最后生成哈夫曼树
5、红黑树
定义:根是黑色的,从根到每个null节点黑色节点数目相同,不能有连续的红色节点
插入:新插入的节点(N)为红色
(1)父亲节点为黑色则直接插入;
(2)父节点为红色,叔节点为红色,反转父节点、叔节点、祖父节点颜色,递归向上插入;
(3)父节点为红色,叔节点为黑色,则旋转进行调整(右图转化成了左图的情况,可以再次调整)
删除:二叉树删除的实际是中序遍历的前驱,要删除某非叶子节点,实际上只是做了节点val的替换,实际删除了中序遍历的前驱(或者后继),所以红黑树实际被删除的节点的孩子数≤1
(1)如果被删除的节点是红色,必定是叶子结点,直接删除即可
(2)如果被删除的节点是黑色且有一个红色儿子(如果有子节点的话一定只有一个红色儿子),用红色儿子代替它并且染成黑色
(3)如果被删除的节点是黑色且是叶子结点:
【1】待删除节点D的兄弟节点S为红色
转化为
变成了兄弟节点为黑色的情况
【2】待删除节点D的兄弟节点S为黑色,又分为四种情况
&1 没有上色的节点表示红黑均可,如果SL为黑色,则一定是null节点
转化为
&2 兄弟节点S有红色儿子
&2.1 兄弟节点S的左儿子SL为红色
转化为
&2.2 兄弟节点S的右儿子SR为红色,SL为红色或者null,P为黑色或者红色都可,最后S与P原先的颜色一致
&3 父节点为红色,兄弟节点为黑色
转化为
&4 父节点为黑色,兄弟节点为黑色
转化为
删除D,将S变为红色,再将P作为要删除的节点(并不实际删除P),上溯