Prim 算法
明天数据结构期末考试,估计也不会考这些代码(每次就考怎么画图?总感觉我考了个假的数据结构)
但是数据结构学到今天课本上也就是这个算法一直实现不了
今天看了下课本,给的代码也不全,自己理解了一下,给出其完整的伪代码和各个部分的伪代码实现
算法思想:和Dijkstra其实非常的类似
不同的是,对于Dijkstra其每次更新距离数组的值是对于图中的每一个顶点,考察它与"当前最小结点"的距离和加上"当前最小结点"自己的距离数值,用这个和它的距离值进行比较,如果和更小,就将这个距离值更新为这个更小的和的值
然而在Prim算法中,也有一个这样的标记数组,但这个标记数组的更新规则是每次找出最小的点(还没有被访问过的,这个和Dijkstra是一样的),然后对这个点的所有相邻结点进行分析,对于其相邻的结点,分析每一个,然后比较这些结点的距离数组中的对应的值和当前"最小的结点"之间的距离,如果距离更小,就更新这个距离作为结点距离数组中的值
其实,每次从距离数组中取出最小结点(没有被访问过的),本质上就是在找这一步要拓展出的新的(要加入MST)结点
下面是各个部分的伪代码实现(还可以使用优先队列进行优化,这里给出的寻找最小值的算法的时间复杂度为O(N**2))可以优化到O(nlogn),优化的选择算法在我的kruskal那篇博客里面已经给出,有兴趣可以自己去翻看查询
void prim_init(Graph* G, int* D, int s){ //s represents for starting point in short
for(int i = 0 ; i < G->n() ; i++){
D[i] = INFINITE;
}
D[s] = 0; //s as the first minimum point
}
int minVertex(Graph* G,int* D){ // n representds for n nodes in the graph, here use the G->n() function to get n
int min_index = 0;
int min_weight = 0;
for(int i = 0 ; i < G->n() ; i++){
if(G->checkMark(i) == UNVISITED){
min_index = i;
min_weight = G->weight(i);
}
}
for(int i = 0 ; i < G->n() ; i++){
if(G->checkMark(i) == UNVISITED && G->weight(i) < min_weight){
min_weight = G->weight(i);
min_index = i;
}
}
return min_index;
}
void Prim(Graph* G, int* D, int s){ //D for distance array
//n nodes and assign s as the target starting point,however we can get the parameter n with the G->n() function
int is_from[G->n()];
for(int i = 0 ; i < G->n() ; i++){ //G->n() times to form a MST
int v = minVertex(G, D);
if(D[v] == INFINITE) return; // impossible to create the MST
G->setMark(v, VISITED);
if(v != s) addEdgetoMST(is_from[v], v); // add the edge <V[v], v> into the MST
// V[v] is the starting point and v as the end point
for(int w = G->first(v) ; w != G->n() ; w = G->next(v, w)){ // go through all the edges from the node v
if(G->weight(w) < D[w]){
D[w] = G->weight;
is_from[w] = v; // w comes from v
}
}
}
}
int min_cost(Graph* G, int* D){
int sum = 0;
for(int i = 0 ; i < G->n() ; i++){
sum += D[i];
}
return sum;
}