1.代码如下
#include<stdio.h>
#include<malloc.h>
#define MAX_DISTANCE 10000
/**
*a structure of a net
*/
typedef struct Net {
int **weights;
int numNodes;
} Net,*NetPtr;
/**
*Intialize a net.
*/
NetPtr initNet(int paraSize,int **paraData){
int i,j;
NetPtr resultPtr = (NetPtr)malloc(sizeof(Net));
resultPtr->numNodes = paraSize;
//Two stage space allocation.
resultPtr->weights = (int**)malloc(paraSize * sizeof(int *));
for(i = 0; i < paraSize; i++) {
resultPtr->weights[i]= (int*)malloc(paraSize * sizeof(int));
for(j=0; j<paraSize; j++){
resultPtr->weights[i][j] = paraData[i][j];
}//of for j
}//of for i
return resultPtr;
}//of initNet
/**
*The prim algorithm for spanning tree,or the Dijkstra algorithm for nearest path.
*@param paraAlgorithm 0 for Dijkstra,1 for Prim
*return The total cost of the tree.
*/
int dijkstraOrPrim(NetPtr paraPtr,int paraAlgorithm){
int i,j,minDistance,tempBestNode,resultCost;
int source = 0;
int numNodes = paraPtr->numNodes;
int *distanceArray =(int *) malloc(numNodes * sizeof(int));
int *parentArray = (int*)malloc(numNodes *sizeof(int));
//Essential boolean
int *visitedArray =(int*)malloc(numNodes * sizeof(int));
//step1.Initialize.Any node can be the source.
for(i=0;i<numNodes;i++){
distanceArray[i]=paraPtr->weights[source][i];
parentArray[i] = source;
visitedArray[i] = 0;
}//of for i
distanceArray[source] = 0;
parentArray[source] = -1;
visitedArray[source] = 1;
//step2.Main loops.
tempBestNode = -1;
for(i=0;i<numNodes -1;i++){
//step2.1 Find out the best next node.
minDistance = MAX_DISTANCE;
for(j=0;j<numNodes;j++) {
//This node is visited.
if(visitedArray[j]) {
continue;
}//of if
if(minDistance > distanceArray[j]){
minDistance = distanceArray[j];
tempBestNode = j;
}//of if
}//of for j
visitedArray[tempBestNode] = 1;
//step2.2 Prepare for the next round.
for(j = 0;j<numNodes;j++){
//This node is visited.
if(visitedArray[j]){
continue;
}//of if
//This node canot be reaached.
if(paraPtr->weights[tempBestNode][j] >= MAX_DISTANCE){
continue;
}//of if
//Attention:the difference between Dijkstrs and algorithms.
if(paraAlgorithm == 0){
if(distanceArray[j] > distanceArray[tempBestNode] +paraPtr->weights[tempBestNode][j]){
//change the distance.
distanceArray[j] = distanceArray[tempBestNode] + paraPtr->weights[tempBestNode][j];
//change the parent.
parentArray[j] = tempBestNode;
}//of if
}else{
if(distanceArray[j]>paraPtr->weights[tempBestNode][j]){
//change the distance
distanceArray[j] = paraPtr->weights[tempBestNode][j];
//cahnge the parent
parentArray[j] =tempBestNode;
}//of if
}//of if
}//of for j
}//of for i
printf("the parent of each node:");
for(i=0;i<numNodes;i++) {
printf("%d ,",parentArray[i]);
}//of for i
if(paraAlgorithm ==0){
printf("From node 0,path length to all nodes are:");
for(i=0;i<numNodes;i++){
printf("%d (%d),",i,distanceArray[i]);
}//of for i
}else{
resultCost = 0;
for(i=0;i<numNodes;i++) {
resultCost +=distanceArray[i];
printf("cost of node %d is %d,total = %d\r\n",i,distanceArray[i],resultCost);
}//of for i
printf("Finaly ,the total cost is %d.\r\n",resultCost);
}//of if
//step3.output for debug.
printf("\r\n") ;
return resultCost;
}//of dijkstrsOrPrim
/**
*Construct a sample net.
*revised from testGraphTranverse
*/
NetPtr constructSampleNet() {
int i,j;
int myGraph[6][6]={
{0,6,1,5,0,0},
{6,0,5,0,3,0},
{1,5,0,5,6,4},
{5,0,5,0,0,2},
{0,3,6,0,0,6},
{0,0,4,2,6,0}};
int **tempPtr;
int numNodes = 6;
printf("Preparing data\r\n");
tempPtr = (int**)malloc(numNodes * sizeof(int*));
for(i=0;i<numNodes;i++) {
tempPtr[i] = (int*)malloc(sizeof(int));
}//of for i
for(i=0;i<numNodes;i++){
for(j=0;j<numNodes;j++){
if(myGraph[i][j] == 0){
tempPtr[i][j] =MAX_DISTANCE;
}else{
tempPtr[i][j] =myGraph[i][j];
}//of if
}//of for j
}//of for i
printf("Data ready\r\n");
NetPtr resultNetPtr =initNet(numNodes,tempPtr);
return resultNetPtr;
}//of constructSampleNet
/**
*Test the prim algorithm.
*/
void testPrim(){
NetPtr tempNetPtr=constructSampleNet() ;
printf("=====Dijkstra algorthm=====\r\n");
dijkstraOrPrim(tempNetPtr,0);
printf("=====Prim algorithm=====\r\n");
dijkstraOrPrim(tempNetPtr,1);
}//of test prim
/**
*The entrnace
*/
int main() {
testPrim();
return 1;
}//of main
2.运行结果
3.小结
Prim算法和Dijkstra算法都是图论中的经典算法,主要用于解决图的最短路径问题,但它们的应用场景和目标有所不同。
Prim算法是用来寻找加权连通图中的最小生成树(Minimum Spanning Tree, MST)的算法之一。最小生成树是指一棵包含所有顶点且边的权重之和最小的树。
基本思想:
1)初始化:从图中任选一个顶点开始,将其加入到已选择顶点集合中。
2)迭代扩展:在每一步中,选择一个连接已选择顶点集合与未选择顶点集合的最小权重边,将这条边的另一端点加入已选择顶点集合。
3)重复步骤2),直到所有顶点都被加入到已选择顶点集合中,此时得到的边集即为最小生成树的边集。
适用情况:加权连通无向图。
复杂度:使用优先队列优化后,时间复杂度可以达到O(ElogV),其中E是边的数量,V是顶点的数量。
Dijkstra算法
目标: Dijkstra算法用于计算加权图中,从单一源点到其余各顶点的最短路径。
基本思想:
1)初始化:为每个顶点分配一个距离值,源点的距离设为0,其他所有顶点的距离设为无穷大。创建一个未访问顶点集合。
2)选择顶点:从未访问顶点中选择距离最小的顶点,访问并标记为已访问。
3)更新邻居距离: 对于当前顶点的所有未访问邻居,如果通过当前顶点到达该邻居的距离比已知的最短距离要短,则更新该邻居的最短距离。
4)重复步骤2)和3),直到所有顶点都被访问过或找到目标顶点为止。
适用情况: 加权连通图,可以是有向也可以是无向,但要求边的权重非负。
复杂度:使用优先队列优化后,时间复杂度同样为O(ElogV)。