算法与数据结构笔记三(图,前缀树,贪心算法)

5.0 图

图的存储方式:

  1. 邻接表(以点为单位,把自己的相邻的点表示出来)在这里插入图片描述

  2. 邻接矩阵在这里插入图片描述如何表达图?生成图?有向图?无向图?

描述图
在这里插入图片描述
描述点在这里插入图片描述
描述边
在这里插入图片描述
如何实现接口函数
在这里插入图片描述
在这里插入图片描述

5.1 图的宽度优先遍历

跟二叉树的宽度优先遍历有什么区别? 树是没有环的,而图是可能有环的。
图的宽度优先遍历
1,利用队列实现
2,从源节点开始依次按照宽度进队列,然后弹出
3,每弹出一个点,把该节点所有没有进过队列的邻接点放入队列
4,直到队列变空
== 一个点出来后在处理==
在这里插入图片描述
在这里插入图片描述

5.2 图的深度优先遍历

广度优先遍历
1,利用栈实现
2,从源节点开始把节点按照深度放入栈,然后弹出
3,每弹出一个点,把该节点下一个没有进过栈的邻接点放入栈
4, 直到栈变空
一个点进去时再处理
在这里插入图片描述

5.3 拓扑排序算法

适用范围:要求有向图,且有入度为0的节点,且没有环
import包,编译
寻找入度为0的点,然后寻找下一个入度为0 的点。
在这里插入图片描述

5.4 prim算法

适用范围:要求无向图
生成最小生成树:一定要保证点的联通性,并且整体边的权值最小
在这里插入图片描述
从哪里出发无所谓,所有边都没有被解锁,从第一个点出发,然后进行解锁相邻边,向权重最低的边出发,到达第二个点,在解锁相邻边,依次类推。(如果权重最低的边两个都遍历过了,就找下一个权重最低的边)
在这里插入图片描述

package class06;

import java.util.Comparator;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;

// undirected graph only
public class Code05_Prim {
   

	public static class EdgeComparator implements Comparator<Edge> {
   

		@Override
		public int compare(Edge o1, Edge o2) {
   
			return o1.weight - o2.weight;
		}

	}

	public static Set<Edge> primMST(Graph graph) {
   
		// 解锁的边进入小根堆
		PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(
				new EdgeComparator());
				
		HashSet<Node> set = new HashSet<>();  // 考察过的点
		
		Set<Edge> result = new HashSet<>();     //  一次挑选的边在result里
		
		for (Node node : graph.nodes.values()) {
     // 处理森林问题,不连通的情况
			// 随便挑一个点
			// node是开始点
			if (!set.contains(node)) {
   
				set.add(node);
				for (Edge edge : node.edges) {
    //由一个点,解锁所有相连的边
					priorityQueue.add(edge); //  放在优先级队列里
				}
				while (!priorityQueue.isEmpty()) {
   
					Edge edge = priorityQueue.poll(); // 弹出解锁的边中,最小的边
					Node toNode = edge.to;    // 可能的一个新的点
					if (!set.contains(toNode)) {
     // 不含有的时候,就是新的点。
						set.add(toNode);
						result.add(edge);
						for (Edge nextEdge : toNode.edges) {
   
							priorityQueue.add(nextEdge);
						}
					}
				}
			}
		}
		return result;
	}


5.5 Kruskal算法

1:20:00
适用范围:要求无向图
生成最小生成树:一定要保证点的联通性,并且整体边的权值最小
以边的角度出发,从最小的边出发,加边,然后判断把边加上能不能形成环,形成环的边就不加。(避圈法)

查并集
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

5.6 Dijkstra算法(迪杰斯特拉)

Dijkstra算法
适用范围:可以有权值为负数的边,不能有累加和为负数的环,单元最短路径算法。
2:04:00
一定要规定出发点,到目标点的最短距离。
在这里插入图片描述
先生成:在这里插入图片描述
每一次在这张表中,选距离最短的点,然后该点更新到各点的最短距离,然后该点距离就固定且不用了。然后再挑剩下的距离最短的点,更新该点到各点的最小距离(min(15,3+2))
在这里插入图片描述

在这里插入图片描述

package class06;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;

// no negative weight
public class Code06_Dijkstra {
   

	public static HashMap<Node, Integer> dijkstra1(Node head) {
   
		//从head出发到所有点的最小距离
		//key:从head出发到达key
		//value:从head出发到达key的最小距离
		//如果在表中,没有T的记录,含义是从head出发到T这个点的距离为正无穷
		HashMap<Node, Integer> distanceMap = new HashMap<>();
		distanceMap.put(head, 0);
		//已经求过距离的节点,存在selectedNodes中,以后再也不碰
		HashSet<Node> selectedNodes = new HashSet<>();
		Node minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);
		while (minNode != null) {
   
			int distance = distanceMap.get(minNode);
			for (Edge edge : minNode.edges) {
   
				Node toNode = edge.to;
				if (!distanceMap.containsKey(toNode)) {
   
					distanceMap.put(toNode, distance + edge.weight);
				}
				distanceMap.put(edge.to, Math.min(distanceMap.get(toNode), 
								distance + edge.weight));
			}
			selectedNodes.add(minNode);
			minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);
		}
		return distanceMap;
	}
	
	
	// 选最小的距离的参数,但是不能是已经选过的点
	public static Node getMinDistanceAndUnselectedNode(HashMap<Node, Integer> distanceMap, 
			HashSet<Node> touchedNodes) {
   
		Node minNode = null;
		int minDistance = Integer.MAX_VALUE;
		for (Entry<Node, Integer> entry : distanceMap.entrySet()) {
   
			Node node = entry.getKey();
			int distance = entry.getValue();
			if (!touchedNodes.contains(node) && distance < minDistance) {
   
				minNode = node;
				minDistance = distance;
			}
		}
		return minNode;
	}

小根堆方法
在这里插入图片描述
系统实现的堆 入堆后 改变不了值。 必须自己手动写
0:12:00

public static class NodeRecord {
   
		public Node node;
		public int distance;

		public NodeRecord(Node node, int distance) {
   
			this.node = node;
			this.distance = distance;
		}
	}


	// 自己改的堆
	public static class NodeHeap {
   
		private Node[] nodes; // 所有的节点放在数组里面
		private HashMap<Node, Integer> heapIndexMap; // 任何一个节点在数组上的位置是 value值,  进来了弹出去了标为-1
		private HashMap<Node, Integer> distanceMap; //   到head的值
		private int size;  // 一共有多少个节点

		public NodeHeap(int size) {
   
			nodes = new Node[size];
			heapIndexMap = new HashMap<>();
			distanceMap = new HashMap<>();
			this.size = 0;
		}

		public boolean isEmpty() {
   
			return size == 0;
		}

		public void addOrUpdateOrIgnore(Node node, int distance) {
   
			if (inHeap(node)) {
   
				distanceMap.put(node, Math.min(distanceMap.get(node), distance));
				insertHeapify(node, heapIndexMap.get(node)); // 往上交换 交换到小了,只能往上
			}
			if (!isEntered(node)) {
   // 从来没有进来过
				nodes[size] = node;
				heapIndexMap.put(node, size);
				distanceMap.put(node, distance);
				insertHeapify(node, size++);
			}
			// 进来过却不在堆上 ,啥都不做
		}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值