edge.h
#ifndef _EDGE_H_
#define _EDGE_H_
typedef struct
{
int v; //顶点之一
int w; //另一个顶点
double weight; //边的权重
} EDGE;
void edgeInit(EDGE* pEdge, int v, int w, double weight);
int edgeWeight(EDGE* pEdge);
int edgeOther(EDGE* pEdge, int vertex);
int edgeCompareTo(EDGE* pThis, EDGE* pThat);
#endif
edge.c
#include <stdio.h>
#include <stdlib.h>
#include "edge.h"
//加权边对象初始化
void edgeInit(EDGE* pEdge, int v, int w, double weight)
{
if ( pEdge == NULL )
{
return;
}
pEdge->v = v;
pEdge->w = w;
pEdge->weight = weight;
}
//返回加权边对象任意一个顶点
int edgeWeight(EDGE* pEdge)
{
if ( pEdge == NULL )
{
return -1;
}
return pEdge->v;
}
//返回加权边对象的另一个顶点
int edgeOther(EDGE* pEdge, int vertex)
{
if ( pEdge->v == vertex )
{
return pEdge->w;
}
else if ( pEdge->w == vertex )
{
return pEdge->v;
}
return -1;
}
//比较加权边对象的加权值
int edgeCompareTo(EDGE* pThis, EDGE* pThat)
{
if ( pThis == NULL || pThat == NULL )
{
return -2;
}
if ( pThis->weight < pThat->weight )
{
return -1;
}
else if ( pThis->weight > pThat->weight )
{
return 1;
}
return 0;
}
edgeWeightedGraph.h
#ifndef _EDGE_WEIGHTED_GRAPH_H_
#define _EDGE_WEIGHTED_GRAPH_H_
#include "edge.h"
#define EDGE_WEIGHTED_GRAPH_TEST 0
#define CHECK_NULL_AND_RET(x) { if((x) == NULL) return -1; }
typedef struct _ADJ_ENTRY
{
EDGE edge;
struct _ADJ_ENTRY* pNext;
} ADJ_ENTRY;
typedef struct
{
struct _ADJ_ENTRY* entryHead;
} ADJ_HEAD;
typedef struct
{
int V; //顶点数
int E; //边数
ADJ_HEAD* adjTable; //邻接表
} EDGE_WEIGHTED_GRAPH;
void edgeWeightedGraphInit(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph, int V);
void edgeWeightedGraphUninit(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph);
int V(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph);
int E(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph);
void addEdge(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph, EDGE* pEdge);
void showGraph(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph);
#endif
edgeWeightedGraph.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "edgeWeightedGraph.h"
#include "edge.h"
//加权无向图对象初始化
void edgeWeightedGraphInit(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph, int V)
{
int i = 0;
if ( pEdgeWeightedGraph == NULL )
{
return;
}
pEdgeWeightedGraph->V = V;
pEdgeWeightedGraph->E = 0;
pEdgeWeightedGraph->adjTable = (ADJ_HEAD *)malloc(sizeof(ADJ_HEAD) * V);
if ( pEdgeWeightedGraph->adjTable == NULL )
{
return;
}
}
//加权无向图去初始化
void edgeWeightedGraphUninit(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph)
{
if ( pEdgeWeightedGraph == NULL )
{
return;
}
if ( pEdgeWeightedGraph->adjTable == NULL )
{
free(pEdgeWeightedGraph->adjTable);
pEdgeWeightedGraph->adjTable = NULL;
}
memset(pEdgeWeightedGraph, 0, sizeof(EDGE_WEIGHTED_GRAPH));
}
//获取加权无向图的顶点数
int V(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph)
{
if ( pEdgeWeightedGraph == NULL )
{
return -1;
}
return pEdgeWeightedGraph->V;
}
//获取加权无向图的边数
int E(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph)
{
if ( pEdgeWeightedGraph == NULL )
{
return -1;
}
return pEdgeWeightedGraph->E;
}
//邻接表添加条目
static int adjAdd(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph, int x, EDGE* pEdge)
{
ADJ_HEAD *pAdjHead = NULL;
ADJ_ENTRY *pNewAdjEntry = NULL;
if ( pEdgeWeightedGraph == NULL || pEdge == NULL )
{
return -1;
}
if ( x >= pEdgeWeightedGraph->V || x < 0 )
{
return -1;
}
pNewAdjEntry = (ADJ_ENTRY *)malloc(sizeof(ADJ_ENTRY));
CHECK_NULL_AND_RET(pNewAdjEntry);
memset(pNewAdjEntry, 0, sizeof(ADJ_ENTRY));
pNewAdjEntry->edge = *pEdge;
pAdjHead = (pEdgeWeightedGraph->adjTable + x);
pNewAdjEntry->pNext = pAdjHead->entryHead;
pAdjHead->entryHead = pNewAdjEntry;
return 0;
}
//向加权无向图中添加加权边
void addEdge(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph, EDGE* pEdge)
{
int v = 0;
int w = 0;
if ( pEdgeWeightedGraph == NULL || pEdge == NULL )
{
return;
}
v = edgeWeight(pEdge);
w = edgeOther(pEdge, v);
adjAdd(pEdgeWeightedGraph, v, pEdge);
adjAdd(pEdgeWeightedGraph, w, pEdge);
pEdgeWeightedGraph->E++;
}
//打印加权无向图信息
void showGraph(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph)
{
int i = 0;
if ( pEdgeWeightedGraph == NULL )
{
return;
}
printf("point count: %d\r\n", V(pEdgeWeightedGraph));
printf("edge count: %d\r\n", E(pEdgeWeightedGraph));
printf("-----------------------------------------\r\n");
for ( i = 0; i < V(pEdgeWeightedGraph); i++ )
{
ADJ_ENTRY* pCurEntry = (pEdgeWeightedGraph->adjTable + i)->entryHead;
while ( pCurEntry != NULL )
{
printf("[%d] %d <--> %d (weight %f)\r\n", \
i, pCurEntry->edge.v, pCurEntry->edge.w, pCurEntry->edge.weight);
pCurEntry = pCurEntry->pNext;
}
}
printf("-----------------------------------------\r\n");
}
#if EDGE_WEIGHTED_GRAPH_TEST
int main()
{
EDGE edgeObj = {0};
EDGE_WEIGHTED_GRAPH graph = {0};
edgeWeightedGraphInit(&graph, 10);
edgeInit(&edgeObj, 0, 1, 0.5);
addEdge(&graph, &edgeObj);
edgeInit(&edgeObj, 1, 2, 1.5);
addEdge(&graph, &edgeObj);
edgeInit(&edgeObj, 2, 3, 2.8);
addEdge(&graph, &edgeObj);
edgeInit(&edgeObj, 0, 4, 9.6);
addEdge(&graph, &edgeObj);
edgeInit(&edgeObj, 4, 7, 0.3);
addEdge(&graph, &edgeObj);
showGraph(&graph);
edgeWeightedGraphUninit(&graph);
return 0;
}
#endif
indexMinPQ.h
#ifndef _INDEX_MIN_PQ_H_
#define _INDEX_MIN_PQ_H_
#define INDEX_MIN_PQ_TEST 0
typedef struct
{
int index;
double cmpNum;
} INDEX_MIN_PQ_DATA;
typedef struct
{
int n;
int maxN;
INDEX_MIN_PQ_DATA* data;
} INDEX_MIN_PQ;
void indexMinPQInit(INDEX_MIN_PQ* pIndexMinPQ, int maxN);
void indexMinPQUninit(INDEX_MIN_PQ* pIndexMinPQ);
int indexMinPQInert(INDEX_MIN_PQ* pIndexMinPQ, int index, double cmpNum);
int indexMinPQDelMin(INDEX_MIN_PQ* pIndexMinPQ);
int indexMinPQIsEmpty(INDEX_MIN_PQ* pIndexMinPQ);
int indexMinPQContains(INDEX_MIN_PQ* pIndexMinPQ, int index);
int indexMinPQChange(INDEX_MIN_PQ* pIndexMinPQ, int index, double cmpNum);
#endif
indexMinPQ.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "indexMinPQ.h"
//最小优先队列初始化
void indexMinPQInit(INDEX_MIN_PQ* pIndexMinPQ, int maxN)
{
if ( pIndexMinPQ == NULL )
{
return;
}
pIndexMinPQ->data = (INDEX_MIN_PQ_DATA *)malloc(sizeof(INDEX_MIN_PQ_DATA) * maxN);
if ( pIndexMinPQ->data == NULL )
{
printf("failed to malloc\r\n");
return;
}
pIndexMinPQ->maxN = maxN;
pIndexMinPQ->n = 0;
}
//最小优先队列去初始化
void indexMinPQUninit(INDEX_MIN_PQ* pIndexMinPQ)
{
if ( pIndexMinPQ == NULL )
{
return;
}
if ( pIndexMinPQ->data != NULL )
{
free(pIndexMinPQ->data);
pIndexMinPQ->data = NULL;
}
memset(pIndexMinPQ, 0, sizeof(INDEX_MIN_PQ));
}
//最小优先队列的元素比较,是否小于
static int indexMinPQisLess(INDEX_MIN_PQ* pIndexMinPQ, int x, int y)
{
if ( pIndexMinPQ == NULL )
{
return 0;
}
return pIndexMinPQ->data[x].cmpNum < pIndexMinPQ->data[y].cmpNum;
}
//最小优先队列的元素交换
static void indexMinPQExchange(INDEX_MIN_PQ* pIndexMinPQ, int x, int y)
{
INDEX_MIN_PQ_DATA tmpData = {0};
if ( pIndexMinPQ == NULL )
{
return;
}
tmpData.index = pIndexMinPQ->data[x].index;
tmpData.cmpNum = pIndexMinPQ->data[x].cmpNum;
pIndexMinPQ->data[x].index = pIndexMinPQ->data[y].index;
pIndexMinPQ->data[x].cmpNum = pIndexMinPQ->data[y].cmpNum;
pIndexMinPQ->data[y].index = tmpData.index;
pIndexMinPQ->data[y].cmpNum = tmpData.cmpNum;
}
//最小优先队列指定索引的上升有序化
static void indexMinPQSwim(INDEX_MIN_PQ* pIndexMinPQ, int k)
{
while ( k > 1 && indexMinPQisLess(pIndexMinPQ, k, k/2) )
{
indexMinPQExchange(pIndexMinPQ, k/2, k);
k = k/2;
}
}
//最小优先队列指定索引的下沉有序化
static void indexMinPQSink(INDEX_MIN_PQ* pIndexMinPQ, int k)
{
while ( (k*2) <= pIndexMinPQ->n )
{
void* tmp = NULL;
int j = k * 2;
//如果存在右孩子,则先找出两个孩子之间的最小值
if ( (j < pIndexMinPQ->n) && indexMinPQisLess(pIndexMinPQ, j+1, j) )
{
j++;
}
//之后在比较当前父亲与最小的孩子之间的最小值
if ( !indexMinPQisLess(pIndexMinPQ, j, k) )
{
break;
}
indexMinPQExchange(pIndexMinPQ, k, j);
k = j;
}
}
//向最小优先队列中插入元素
//1、首先将元素插入到堆末尾
//2、之后比较新的元素是否小于父元素,如果小于,则不断进行上浮处理,直到孩子不再小于
// 父亲为止,或者已经上俘到最顶端。
int indexMinPQInert(INDEX_MIN_PQ* pIndexMinPQ, int index, double cmpNum)
{
if ( pIndexMinPQ->n >= pIndexMinPQ->maxN )
{
printf("already full.\r\n");
return -1;
}
//数组索引0没有使用,直接从1开始,主要是
//方便计算孩子、父亲索引之间的关系
pIndexMinPQ->n++;
pIndexMinPQ->data[pIndexMinPQ->n].index = index;
pIndexMinPQ->data[pIndexMinPQ->n].cmpNum = cmpNum;
indexMinPQSwim(pIndexMinPQ, pIndexMinPQ->n);
return 0;
}
//删除最小优先队列的最小值
//1、头部的最小值取出后,将尾部的元素填充到头部
//2、进行尾部复位,及减小总元素个数
//3、对头部元素进行下降处理
int indexMinPQDelMin(INDEX_MIN_PQ* pIndexMinPQ)
{
int retIndex = -1;
if ( indexMinPQIsEmpty(pIndexMinPQ) )
{
printf("already empty.\r\n");
return -1;
}
//数组索引0没有使用,直接从1开始,主要是
//方便计算孩子、父亲索引之间的关系
retIndex = pIndexMinPQ->data[1].index;
indexMinPQExchange(pIndexMinPQ, 1, pIndexMinPQ->n);
pIndexMinPQ->n--;
indexMinPQSink(pIndexMinPQ, 1);
return retIndex;
}
//检查最小优先队列是否为空
int indexMinPQIsEmpty(INDEX_MIN_PQ* pIndexMinPQ)
{
if ( pIndexMinPQ == NULL )
{
return 1;
}
return pIndexMinPQ->n <= 0;
}
//查找匹配最小优先队列数据index的数组索引
static int indexMinPQGetDataArrayIndex(INDEX_MIN_PQ* pIndexMinPQ, int index)
{
int i = 0;
if ( pIndexMinPQ == NULL )
{
return 0;
}
//数组索引0没有使用,直接从1开始,主要是
//方便计算孩子、父亲索引之间的关系
for ( i = 1; i <= pIndexMinPQ->n; i++ )
{
if ( pIndexMinPQ->data[i].index == index )
{
return i;
}
}
return 0;
}
//检查最小优先队列是否含有该数据index
int indexMinPQContains(INDEX_MIN_PQ* pIndexMinPQ, int index)
{
return indexMinPQGetDataArrayIndex(pIndexMinPQ, index) > 0;
}
//最小优先队列中指定数据的比较值进行了更改
int indexMinPQChange(INDEX_MIN_PQ* pIndexMinPQ, int index, double cmpNum)
{
int dataArrayIndex = -1;
if ( pIndexMinPQ == NULL )
{
return -1;
}
dataArrayIndex = indexMinPQGetDataArrayIndex(pIndexMinPQ, index);
if ( dataArrayIndex == 0 )
{
return -1;
}
if ( cmpNum > pIndexMinPQ->data[dataArrayIndex].cmpNum )
{
pIndexMinPQ->data[dataArrayIndex].cmpNum = cmpNum;
indexMinPQSink(pIndexMinPQ, dataArrayIndex);
}
else if ( cmpNum < pIndexMinPQ->data[dataArrayIndex].cmpNum )
{
pIndexMinPQ->data[dataArrayIndex].cmpNum = cmpNum;
indexMinPQSwim(pIndexMinPQ, dataArrayIndex);
}
return 0;
}
#if INDEX_MIN_PQ_TEST
int main()
{
INDEX_MIN_PQ indexMinPQObj = {0};
indexMinPQInit(&indexMinPQObj, 10);
indexMinPQInert(&indexMinPQObj, 0, 1.4);
indexMinPQInert(&indexMinPQObj, 1, 5.9);
indexMinPQInert(&indexMinPQObj, 2, 2.8);
indexMinPQInert(&indexMinPQObj, 3, 7.1);
indexMinPQInert(&indexMinPQObj, 4, 9.4);
indexMinPQInert(&indexMinPQObj, 5, 2.2);
indexMinPQInert(&indexMinPQObj, 6, 5.2);
indexMinPQInert(&indexMinPQObj, 7, 1.6);
indexMinPQInert(&indexMinPQObj, 8, 6.3);
printf("have index %d : %s\r\n", 8, \
indexMinPQContains(&indexMinPQObj, 8) ? "TRUE" : "FALSE");
printf("have index %d : %s\r\n", 9, \
indexMinPQContains(&indexMinPQObj, 9) ? "TRUE" : "FALSE");
indexMinPQChange(&indexMinPQObj, 3, 0.4);
indexMinPQChange(&indexMinPQObj, 6, 6.6);
printf("[0] delete index %d.\r\n", indexMinPQDelMin(&indexMinPQObj));
printf("[1] delete index %d.\r\n", indexMinPQDelMin(&indexMinPQObj));
printf("[2] delete index %d.\r\n", indexMinPQDelMin(&indexMinPQObj));
printf("[3] delete index %d.\r\n", indexMinPQDelMin(&indexMinPQObj));
printf("[4] delete index %d.\r\n", indexMinPQDelMin(&indexMinPQObj));
printf("[5] delete index %d.\r\n", indexMinPQDelMin(&indexMinPQObj));
printf("[6] delete index %d.\r\n", indexMinPQDelMin(&indexMinPQObj));
printf("[7] delete index %d.\r\n", indexMinPQDelMin(&indexMinPQObj));
printf("[8] delete index %d.\r\n", indexMinPQDelMin(&indexMinPQObj));
printf("[9] delete index %d.\r\n", indexMinPQDelMin(&indexMinPQObj));
indexMinPQUninit(&indexMinPQObj);
return 0;
}
#endif
primMST.c
//Prim最小生成树算法
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include "edge.h"
#include "indexMinPQ.h"
#include "edgeWeightedGraph.h"
#define POSITIVE_INFINITY DBL_MAX
//当前Prim最小生成树算法使用了如下数据结构,其中edgeTo\distTo\marked相当于
//对应元素类型的数组,minPQObj为优先权队列.
EDGE * edgeTo = NULL; //记载每个顶点与最小生成树最近的边
double* distTo = NULL; //记载每个顶点与最小生成树最近的边的权值
int* marked = NULL; //记载每个顶点是否已经在最小生成树中
INDEX_MIN_PQ minPQObj = {0}; //在最小生成树算法运算时,根据边的权值临时记载横切边
//算法初始化,根据图的顶点数分配资源
int primMSTInit(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph)
{
int i = 0;
int v = 0;
if ( pEdgeWeightedGraph == NULL )
{
return -1;
}
v = V(pEdgeWeightedGraph);
edgeTo = (EDGE *)malloc(sizeof(EDGE) * v);
if ( edgeTo == NULL )
{
return -1;
}
distTo = (double *)malloc(sizeof(double) * v);
if ( distTo == NULL )
{
return -1;
}
marked = (int *)malloc(sizeof(int) * v);
if ( marked == NULL )
{
return -1;
}
indexMinPQInit(&minPQObj, v);
for ( i = 0; i < v; i++ )
{
distTo[i] = POSITIVE_INFINITY;
}
return 0;
}
//算法去初始化
void primMSTUninit()
{
if ( edgeTo != NULL )
{
free(edgeTo);
edgeTo = NULL;
}
if ( distTo != NULL )
{
free(distTo);
distTo = NULL;
}
if ( marked != NULL )
{
free(marked);
marked = NULL;
}
indexMinPQUninit(&minPQObj);
}
//Prim最小生成树算法
int primMST(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph)
{
if ( pEdgeWeightedGraph == NULL )
{
return -1;
}
//这里将顶点0做为起始顶点,当前为只含有一个顶点的树,
//顶点距自身距离为0.0
distTo[0] = 0.0;
indexMinPQInert(&minPQObj, 0, 0.0);
//1 在上面已经将顶点0加入到最小优先队列中,这里检查优
// 先队列是否还有待处理的数据,如果有则取出离树最近的
// 顶点,即每次查找离树最近的边进行处理.
//2 将取出的最近顶点标记为marked,即表示当前顶点已经加
// 入到这棵最小生成树中
//3 遍历这个顶点所以相关联的边(对于已经在这棵最小生成
// 树的边则忽略),检查每个相关联的边的另一端顶点离当
// 前这棵最小生成树的距离是否比之前记录的值更近一些,
// 如果另一端顶点离这棵最小生成树的距离确实比之前记录
// 的值更近了,则更新这个顶点离最小生成树的距离为更新
// 的这个值,同时将此顶点加入到最小优先权队列中(如果
// 之前已经在最小优先权队列,但还未处理,则进行权值更
// 新),准备后续进行处理.
//4 之后一直循环查找优先队列是否还有待处理的数据,如果
// 有,则取出后,进行2~4的处理,直到优先队列是空,
// 则算法处理完毕.
while ( !indexMinPQIsEmpty(&minPQObj) )
{
ADJ_ENTRY* pCurAdjEntry = NULL;
int x = indexMinPQDelMin(&minPQObj);
if ( x < 0 || x >= V(pEdgeWeightedGraph) )
{
continue;
}
marked[x] = 1;
for ( pCurAdjEntry = pEdgeWeightedGraph->adjTable[x].entryHead; \
pCurAdjEntry != NULL; pCurAdjEntry = pCurAdjEntry->pNext )
{
EDGE* pEdgeObj = &pCurAdjEntry->edge;
int y = edgeOther(pEdgeObj, x);
if ( marked[y] )
{
continue;
}
if (distTo[y] > pEdgeObj->weight)
{
if ( indexMinPQContains(&minPQObj, y) )
{
indexMinPQChange(&minPQObj, y, pEdgeObj->weight);
}
else
{
indexMinPQInert(&minPQObj, y, pEdgeObj->weight);
}
distTo[y] = pEdgeObj->weight;
edgeTo[y] = *pEdgeObj;
}
}
}
return 0;
}
//创建加权无向图
//当前示例的图为:
// (0) <- 1.4 -> (1) <- 5.6 -> (2)
// ^ ^
// | |-- 3.2 --> (3) <------- 6.6 -----> (5)
// | | ^
// | |-- 7.8 -> (4) |-- 2.9 -> (6)
// | ^ |
// |-- 0.2 ->(9) | |-- 7.6 -> (7)
// | |
// |-- 2.5 -> (8) -> 3.5 <-|
//
void createGraph(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph)
{
EDGE edgeObj = {0};
if ( pEdgeWeightedGraph == NULL )
{
return;
}
edgeWeightedGraphInit(pEdgeWeightedGraph, 10);
edgeInit(&edgeObj, 0, 1, 1.4);
addEdge(pEdgeWeightedGraph, &edgeObj);
edgeInit(&edgeObj, 0, 9, 0.2);
addEdge(pEdgeWeightedGraph, &edgeObj);
edgeInit(&edgeObj, 1, 2, 5.6);
addEdge(pEdgeWeightedGraph, &edgeObj);
edgeInit(&edgeObj, 1, 3, 3.2);
addEdge(pEdgeWeightedGraph, &edgeObj);
edgeInit(&edgeObj, 1, 4, 7.8);
addEdge(pEdgeWeightedGraph, &edgeObj);
edgeInit(&edgeObj, 3, 5, 6.6);
addEdge(pEdgeWeightedGraph, &edgeObj);
edgeInit(&edgeObj, 4, 8, 2.5);
addEdge(pEdgeWeightedGraph, &edgeObj);
edgeInit(&edgeObj, 5, 6, 2.9);
addEdge(pEdgeWeightedGraph, &edgeObj);
edgeInit(&edgeObj, 5, 7, 7.6);
addEdge(pEdgeWeightedGraph, &edgeObj);
edgeInit(&edgeObj, 5, 8, 3.5);
addEdge(pEdgeWeightedGraph, &edgeObj);
}
//销毁加权无向图
void destroyGraph(EDGE_WEIGHTED_GRAPH* pEdgeWeightedGraph)
{
if ( pEdgeWeightedGraph == NULL )
{
return;
}
edgeWeightedGraphUninit(pEdgeWeightedGraph);
}
int main()
{
int i = 0;
EDGE_WEIGHTED_GRAPH graphObj = {0};
createGraph(&graphObj);
showGraph(&graphObj);
primMSTInit(&graphObj);
primMST(&graphObj);
for ( i = 0; i < V(&graphObj); i++ )
{
int x = edgeWeight(&edgeTo[i]);
int y = edgeOther(&edgeTo[i], x);
printf("[%d] %d<->%d weight %f\r\n", i, x, y, distTo[i]);
}
primMSTUninit();
destroyGraph(&graphObj);
return 0;
}