《数据结构与算法分析(Java语言描述)》读书笔记——图论、哈夫曼树和红黑树

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),上溯

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值