其他分享
首页 > 其他分享> > Graphs

Graphs

作者:互联网

Presentations

class Graph { // Graph abstract class
	public:
		virtual int n() =0; // # of vertices
		virtual int e() =0; // # of edges
		// Return index of first, next neighbor 
		virtual int first(int) =0; //
		virtual int next(int, int) =0;
		// Store new edge
		virtual void setEdge(int, int, int) =0;
		// Delete edge defined by two vertices
		virtual void delEdge(int, int) =0;
		// Weight of edge connecting two vertices
		virtual int weight(int, int) =0;
		virtual int getMark(int) =0;
		virtual void setMark(int, int) =0;
};

这里主要注意firstnext的使用方法, 下图中
first(0)=1 next(0,1)=4 (0的下一个的下一个)
first(3)=1 next(3,first(3))=2
next(4,next(4,first(4)))=2
在这里插入图片描述
这个其实是按照数字大小排序的

Graph Traversal

Depth First Search

在这里插入图片描述

// Depth first search
void DFS(Graph* G, int v) {
	PreVisit(G, v); // Take action
	G->setMark(v, VISITED);
	for (int w = G->first(v); 
			w < G->n(); 
			w = G->next(v,w))
		if (G->getMark(w) == UNVISITED)
			DFS(G, w);
	PostVisit(G, v); // Take action
}

一条路走到底 遇到不能走的再一个一个返回 注意在遍历的时候要顺着一个方向(本遍历是按照字母的顺序)

Breadth First Search

在这里插入图片描述
这个图画错了 第二层是``b和e 到了每个节点以后访问哪个节点是按照字母大小排序的

void BFS(Graph* G, int start,Queue<int>*Q) {
	int v, w;
	Q->enqueue(start); // Initialize Q
	G->setMark(start, VISITED);
	while (Q->length() != 0) { // Process Q
		Q->dequeue(v);
		PreVisit(G, v); // Take action
		for(w=G->first(v); w<G->n(); w=G->next(v,w))
			if (G->getMark(w) == UNVISITED) {
				G->setMark(w, VISITED);
				Q->enqueue(w);
			}
		PostVisit(G, v); // Take action
	}
}

一层一层向下遍历

Topological Sort (拓扑排序)

void topsort(Graph* G) { // Topological sort
	int i;
	for (i=0; i<G->n(); i++) // Initialize
		G->setMark(i, UNVISITED);		
	for (i=0; i<G->n(); i++) // Do vertices 
		if (G->getMark(i) == UNVISITED)
			tophelp(G, i); // Call helper
}
void tophelp(Graph* G, int v) { // Process v
	G->setMark(v, VISITED);
	for (int w = G->first(v); w < G->n(); w = G->next(v,w))
		if (G->getMark(w) == UNVISITED)
			tophelp(G, w);
	printout(v); // PostVisit for Vertex v
}

Shortest Paths Problems

Dijkstra’s Algorithm

Linear Approach

// Compute shortest path distances from s,
// return them in D
void Dijkstra(Graph* G, int* D, int s) {
	int i, v, w;
	for (i=0; i < G->n(); i++)  // Initialization
		D[i] = INFINITY;
	D[s] = 0;  //开始点的距离设置为0
	
	for (i=0; i < G->n(); i++) { // 访问所有顶点
		v = minVertex(G, D);  //找到当前的最小值
		if (D[v] == INFINITY) return;  //只有一个节点的情况
		G->setMark(v, VISITED); //标记已访问过
		for (w=G->first(v); w<G->n(); w = G->next(v,w))  //遍历当前节点的相邻节点 更新
			if (D[w] > (D[v] + G->weight(v, w)))
				D[w] = D[v] + G->weight(v, w);
	}
}

// Find min cost vertex
int minVertex(Graph* G, int* D) {
	int i, v;
	
	// Set v to an unvisited vertex
	//从第一个未被访问过的开始
	for (i=0; i<G->n(); i++)
		if (G->getMark(i) == UNVISITED)
			{ v = i; break; }
			
	// Now find smallest D value
	//找到最小的顶点值
	for (i++; i<G->n(); i++)
		if ((G->getMark(i) == UNVISITED) && (D[i] < D[v]))
			v = i;
	return v;
}

Min Heap Approach

class DijkElem {
	public:
	int vertex, distance;
	DijkElem() { vertex = NULL; distance = NULL; }
	DijkElem(int v, int d) { vertex = v; distance = d; }
};

void Dijkstra(Graph* G, int* D, int s) {
	int i, v, w; // v is current vertex
	DijkElem temp;
	DijkElem E[G->e()]; // Heap array
	temp.distance = 0; temp.vertex = s;
	E[0] = temp; // Initialize heap array
	minheap<DijkElem, DDComp> H(E, 1, G->e()); 
	for (i=0; i<G->n(); i++) { // Get distances
	   //v找到第一个unvisited
		do { 
			if(!H.removemin(temp)) return;
			v = temp.vertex;
		} while (G->getMark(v) == VISITED);
		
		G->setMark(v, VISITED); //标记访问过
		
		if (D[v] == INFINITY) return;  
		
		for(w=G->first(v); w<G->n(); w=G->next(v,w))
			if (D[w] > (D[v] + G->weight(v, w))) {
				D[w] = D[v] + G->weight(v, w);
				temp.distance = D[w]; temp.vertex = w;
				H.insert(temp); // Insert in heap
			}
	}
}

All Pairs Shortest Paths Problem

前面是找两个点之间的 这个是找全部的

Floyd’s Algorithm

d(i,k) VS d(i,j)+d(j,k) 找到一个连接两点的中间结点
每次按顺序 选择一个节点作为中间结点

//Floyd's all-pairs shortest paths algorithm
void Floyd(Graph* G) {
	int D[G->n()][G->n()]; // Store distances
	
	for (int i=0; i<G->n(); i++) // Initialize
		for (int j=0; j<G->n(); j++)
			D[i][j] = G->weight(i, j);
	
	// Compute all k paths
	for (int k=0; k<G->n(); k++)
		for (int i=0; i<G->n(); i++)
			for (int j=0; j<G->n(); j++)
				if (D[i][j] > (D[i][k] + D[k][j]))
					D[i][j] = D[i][k] + D[k][j];
}

Minimum-Cost Spanning Trees

Prim’s Algorithm

void Prim(Graph* G, int* D, int s) {
	int V[G->n()]; // Who's closest
	int i, w;
	for (i=0; i<G->n(); i++) { // Do vertices
		int v = minVertex(G, D); 
		G->setMark(v, VISITED);
		if (D[v] == INFINITY) return;
		if (v != s) AddEdgetoMST(V[v], v);
		for (w=G->first(v); w<G->n();w = G->next(v,w))
			if (D[w] > G->weight(v,w)) {
				D[w] = G->weight(v,w); // Update dist
				V[w] = v; // Update who it came from
			}
	}
}

Kruskal’s Algorithm

Class KruskElem {
public:
	int from, to, distance;
	KruskElem( ) { from=-1; to=-1; distance=-1; }
	KruskElem(int f, int t, int d) 
	{ from=f; to=t; distance=d; }
};
Kruskal(Graph& G) { // Kruskal's MST algorithm
	Gentree A[G->n( )]; // Equivalence class array
	KruskElem E[G->e( )]; // Array of edges for min-heap
	int edgecnt = 0;
	for (int i=0; i<G->n( ); i++) // Put edges on array
		for (int w = G->first(i); w<G->n( ); w = G->next(i,w)) {
			E[edgecnt].distance = G->weight(i,w);
			E[edgecnt].from = i;
			E[edgecnt++].to = w;
		}
	Minheap<KruskElem,KKComp> H(E, edgecnt, edgecnt); 
	int numMST = G->n( ); // Init n equiv classes
	for (i=0; numMST>1; i++) { // Combine equiv classes
		KruskElem temp;
		H.removemin(temp); // Get next cheap edge
		int v = temp.from;
		int u = temp.to;
		if (A.differ(v, u)) { // If different equiv classes
			A.UNION(v, u); // Combine equiv classes
			AddEdgetoMST(v,u); // Add to MST
			numMST--; // One less MST
		}
	}
}

标签:int,Graph,vertex,++,next,Graphs,first
来源: https://blog.csdn.net/yxyxxxyyyy/article/details/121525758