图的结构与算法
一、图的表示
经典基本数据结构有矩阵和邻接表表示法
图的基本属性:边和点
**遍历算法**
**BFS**
使用栈开始,将第一节点入栈,将所有邻接点入栈,做好标记,只要图联通,所有点都可以遍历到。
mystack.add(node);
myset.add(node);
// dealing code
while(!mystack.isEmpty()){
Node cur = mystact.pop();
for(NewNodes in cur.nexts){
if(NewNodes not in set)
myset.add(NewNode);
mystack.add(NewNode);
//dealing code
}
DFS 从节点一层层往下走
while(!mystack.isEmpty()){
node cur = mystack.pop();
for (NewNodes in cur.nexts){
if(NewNodes not in set){
myset.add(NewNode);
mystack.add(cur);
mystack.add(NewNode);
//dealing code
break;
}
}
拓扑排序 工程应用问题,无环
找到逐个进出的顺序
a -> b ->c ->d (入度为零,则为起始节点,消除入度为零节点的出度)
List<node> sortedTopology(Graph graph){
map<node , int> inMap = new map<>();
Queue<node> zero_InQueue = new queue();
for(Node in graph.nodes){
inMap.put(Node,Node.in);
if(Node.in == 0 ) zero_InQueue.add(Node);
}
List<node> result = new List<>();
while(!zero_InQueue.isEmpty()){
node cur = zero_InQueue.pop();
result.add(cur);
for(next in cur.nexts){
inMap.put(next, inMap.get(next)-1);
if(inMap.get(next) == 0)
zero_InQueue.add(next);
}
}
return result;
二、生成最小生成树
若边带有权值,生成连通且整棵树的边权值最小。
算法
并查集需要了解一下
K算法
基于边权值考虑,边权值排列,从最小的边开始,逐条边考虑,加入后无形成环,到最后一条边结束。集合之间的合并
class mySets{
HashMap<node,list<node>> setMap;
mySets(list<node> node){
for(new_node in node){
List<node> set = new List<node>();
set.add(new_node);
setMap(new_node,set);
}
bool isSameSet(node from,node to){
list<node> fromset = setMap.get(from);
list<node> toset = setMap.get(to);
return fromset == toset;
}
void Union(node from,node to){
List<node> fromSet= setMap.get(from);
List<node> toSet = setMap.get(to);
for (new_node in fromSet){
toSet.add(new_node);
setMap.put(new_node,toSet);
}
}
}
}
//kruskal-algorithm
EdgeComparator(Edge front, Edge behind){
return front.value - behind.value;
}
set<Edge> kruskalMST(Graph graph){
mySets unionFind = new mySets(graph.nodes);
PriorityQueue<edge> priorityQueue =new Priority<>(new EdgeComparator());
for( new_edge in graph.egdes)
priority.add(new_edge);
}
Set<Edge> result = new Set<>();
while(!priority.isEmpty()){
Edge new_edge = priorityQueue.pop();
if( !isSameSet(edge.from, edge.to)){
mySets.Union(edge.from,edge.to);
result.add(edge);
}
}
return result;
}
prim-algorithm
要求权值不能为负数 环出现累加为负,累加和无限累加负数,不断缩小。
(1).找到一个给点节点开始,寻找次边最小权值边加入,并记录节点
(2).寻找已加入节点的边中最短节点,并且次边节点两节点不再已加入节点
(3). 重复(2)
// prim-algorthm
set<Edge> primMST<Graph graph>{
PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(EdgeComparetor());
list<Edge> result = new list<>();
set<node> TagSetNodes =new set<>();
for(node in graph.nodes){
if(node not in TagSetNodes){
TagSetNodes.add(node);
for(edge in node.edges)
priorityQueue.add(edge);
/********************/
while(!priorityQueue.isEmpty()){/** 防止图不连通 ************/
Edge new_edge = priorityQueue.pop();
node toNOde = new_edge.to;
if(toNode not in TagSetNodes){
TagsetNOdes.add(toNode);
result.put(new_edge);
for(edge in toNode.edges)
priorityQueue.add(edge);
}
}
}
return result;
}
三、 单元最短路路径算法
迪杰斯特拉算法
/ 优化迪杰斯特拉 手写堆,每一次堆值更改后调正堆
从特点节点出发,找到于当前节点到其他所有节点的最短路径。
思路:
(1)初始化出发节点到每一节点距离,不相邻则无穷大
(2)挑选其他的节点,找到已更新节点集合最小的距离节点的点,逐一考虑通过此节点距离,加上此节点后到第三节点距离是否有变化,若距离更短则更新节点距离
(3) 重复(2)步骤刷完所有节点
Node getMini_Noselect_Node(HashMap<Node,int> distanceMap,set<Node> targeNode){
int mini_distance = INT_MAX;
Node cur_node = NULL;
for(node in HashMap.keyvalues()){
if( HashMap.get(node) < mini_distance && node not in targeNode){
cur_node = node;
mini_distance = HashMap.get(node);
}
return cur_node;
}
HashMap<Node,int> dijkstral(Node head){
HashMap<Node, int> distanceMap = new HashMap<>();
distanceMap.put(head,0);
set<Node> targetNode = new set<>();
Node miniNode = getMini_Noselect_Node(distanceMap,targetNode);
while(miniNode != NULL){
int cur_distance = distanceMap.get(miniNode);
for(edge in miniNode.edges){
node nextNode = edge.toNode;
if( nextNode not in distanceMap.keyvalues()){
distanceMap.put(miniNode,cur_distance+edge.weight);
}
distanceMap.put(miniNode,min(distanceMap(miniNode),cur_distance+edge.weight)
}
targeNode.add(mininNode);
miniNode = getMini_Noselect_Node(distanceMap,targeNode);
}
return distanceMap;
}