Prim's Minimal Spanning Tree Algorithm


Implementation file for Prim's Minimal Spanning Tree Algorithm demonstration.
//---------------------------------------------------------------
// File: Code306_Graphs.cpp
// Purpose: Demonstration of Minimal Spanning Tree Algorithm in 
//        a graph.
// Programming Language: C++
// Author: Dr. Rick Coleman
// Date: March, 2002
//---------------------------------------------------------------
#include <iostream>
#include <stdio.h> // Included to give access to sscanf()
#include <stdlib.h> // Included to give access to atoi()
#include <fstream>
#include <string.h>

using namespace std;

#define MAXVERTICES 6
#define Minimum(X,Y)  ((X)<(Y))?(X):(Y)
#ifndef MAXINT
#define MAXINT 65536
#endif

enum StatusType {intree, fringe, unseen};

void SpanningTree(int adjMatrix[MAXVERTICES][MAXVERTICES], int n, int v);
bool getNextLine(ifstream& inF, char *line, int lineLen);

int main(void)
{
    int            adjMatrix[MAXVERTICES][MAXVERTICES];
    ifstream    inFile;
    char        line[81], townName[32];
    int            i, num, vStart;

    // Try to open the file with the graph data
    inFile.open("graph.txt", ifstream::in); 
    if(!inFile.is_open())
    {
        // inFile.is_open() returns false if the file could not be found or
        //    if for some other reason the open failed.
        cout << "Unable to open file graph.txt. \nProgram terminating...\n";
        return 0;
    }

    getNextLine(inFile, line, 81);
    num = atoi(line);
    // Build the adjaceny matrix
    for(i=0; i<num; i++)
        {
        getNextLine(inFile, line, 81);
        sscanf(line, "%s %d %d %d %d %d %d", townName, &adjMatrix[i][0], 
            &adjMatrix[i][1], &adjMatrix[i][2], &adjMatrix[i][3], 
            &adjMatrix[i][4], &adjMatrix[i][5]);
        }

    cout << "\n\nEnter starting node number.\n";
    cin >> vStart;
    SpanningTree(adjMatrix, MAXVERTICES, vStart);
        return 0;
 }


//-------------------------------------------
// SpanningTree() 
// 
// Calculate the minimal spanning tree 
//  using Prim's algorithm.
//-------------------------------------------
void SpanningTree(int adjMatrix[MAXVERTICES][MAXVERTICES], int n, int v)
{
    int         ShortestDist[MAXVERTICES][2]; // 0 = shortest dist, 1 = from node
    StatusType  status[MAXVERTICES];
    int         nextTreeIdx = 0;            // Index in Tree where next node number will be stored
    int         Tree[MAXVERTICES][2];       // Tree being built. 0 = next vertex, 1 = last vertex
    int         w;                          // Current selected vertex
    int         edgeTotal = 0;
    int         i;
    int         minDist;
    int         fromNode = -1;

    //---------------- Initialization Section -----------------
    for(i=0; i<MAXVERTICES; i++)
        {
        ShortestDist[i][0] = MAXINT;
        ShortestDist[i][1] = -1;
        status[i] = unseen;
        Tree[i][0] = Tree[i][1] = -1;
        }

    //------------------- Setup Section -----------------------
    Tree[nextTreeIdx][0] = v;    // Add node v to Tree
    Tree[nextTreeIdx][1] = 0;    // This one had no "from" node
    nextTreeIdx++;
    ShortestDist[v - 1][0] = 0;  // Set shortest distanct from v to v = 0
    status[v - 1] = intree;      // Set status of v to intree
    for(i=0; i<MAXVERTICES; i++) // Search for nodes adjacent to v
        {
        if(adjMatrix[v - 1][i] > 0) // This one is adjacent
            {
            status[i] = fringe;                        // Set status to fringe
            ShortestDist[i][0] = adjMatrix[v - 1][i];  // Set shortest distance
            ShortestDist[i][1] = v;                    // Save where this is from
            }
        }

    //------------------ Main Loop Section ---------------------
    while(nextTreeIdx < MAXVERTICES)  // Repeatedly enlarge tree until it includes 
    {                                 // all vertices in the graph 
        // Find node w among those in the fringe at minimum distance from v 
        //   where v is any node in the tree
        minDist = MAXINT;
        for(i=0; i<MAXVERTICES; i++)
            if((ShortestDist[i][0] < minDist) && (status[i] == fringe))
                {
                minDist = ShortestDist[i][0];
                w = i + 1;                              // Set to node number not index
                }
        Tree[nextTreeIdx][0] = w;                       // Add node to tree
        Tree[nextTreeIdx][1] = ShortestDist[w - 1][1];  // Save from node
        status[w - 1] = intree;                         // Set status of w to intree
        edgeTotal += minDist;                           // Add distance to running total
        for(i=0; i<MAXVERTICES; i++)
            {                                           // For each node adjacent to w
            if((adjMatrix[w - 1][i] > 0) && (status[i] == unseen)) // This one is adjacent and not in fringe
                status[i] = fringe;                     // Set this one to in fringe
            // Set new minimum distance if appropriate
            if((adjMatrix[w - 1][i] > 0) && (status[i] == fringe)) // This one is adjacent and not in fringe
                ShortestDist[i][0] = Minimum(ShortestDist[i][0], adjMatrix[w - 1][i]);
            if(ShortestDist[i][0] == adjMatrix[w - 1][i])
                ShortestDist[i][1] = w;  // Set from node 
            }
        nextTreeIdx++;
        }

     //-------------------- Report Section ---------------------
    cout << "\n\nMinimal Spanning Tree:\n";
    cout << "----------------------\n";
    for(i=1; i<MAXVERTICES; i++)
        cout << "(" << Tree[i][1] << " to " << Tree[i][0] << ") dist = " <<
        ShortestDist[i][0] << "\n";
    cout << "----------------------\n";

    cout << "\nTotal distance = " << edgeTotal << "\n";
}

//-------------------------------------------
// GetNextLine()
// Read the next line from the file.
//-------------------------------------------
bool getNextLine(ifstream& inF, char *line, int lineLen)
{
    int    done = false;

    while(!done)
    {
        inF.getline(line, lineLen);
        
        if(inF.good())    // If a line was successfully read
        {
           if(strlen(line) == 0)  // Skip any blank lines
                continue;
            else if(line[0] == '#')  // Skip any comment lines
                continue;
            else done = true;    // Got a valid data line so return with this line
        }
        else
        {
            strcpy(line, "");
            return false;    // Flag end of file with null string
        }
    } // end while
    return true; // Flag successful read
}