// File: Kruskal.h-------------------------------------------------------------
#ifndef _MY_KGRAPH_H
#define _MY_KGRAPH_H

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

class Edge {
      int v1, v2;
      float w;
public:
      Edge(int v1=0, int v2=0, float w=0);
      int getV1();
      int getV2();
      float getW();
      ostream& Show(ostream& outDev) const;
      friend bool operator < (const Edge& e1, const Edge& e2);
      friend bool operator == (const Edge& e1, const Edge& e2);
      friend istream& operator >> (istream&, Edge&);
      friend ostream& operator << (ostream&, const Edge&);
};

class KruskalAlgo {
      vector<int> Label;
      vector<Edge> Edges;
      vector<Edge> T;
      int nVer;
      void UpdateLabels(int v1, int v2);
      void InitAlg();
public:
      void LoadEdges(istream& inDev) ;
      bool LoadEdges(char* fName) ;
      int RunAlg();
      void ShowT(ostream& outDev);
};

#endif
// end of File: Kruskal.h-------------------------------------------------------
// File Kruskal.cpp-----------------------------------
#include "Kruskal.h"

// Methods and operators for Edge class
Edge::Edge(int v1, int v2, float w){
      this->w=w;
      this->v1=v1;
      this->v2=v2;
}

int Edge::getV1() {
      return v1;
}

int Edge::getV2() {
      return v2;
}

float Edge::getW() {
       return w;
}

ostream& Edge::Show(ostream& outDev) const {
      outDev << v1 << "----"<< v2 << " ; w = " << w;
      return outDev;
}

bool operator < (const Edge& e1, const Edge& e2){
      return e1.w < e2.w;
}

bool operator == (const Edge& e1, const Edge& e2){
      return e1.w == e2.w;
}

istream& operator >> (istream& inDev, Edge& e){
       inDev >> e.v1 >> e.v2 >> e.w;
       return inDev;
}


ostream& operator << (ostream& outDev, const Edge& e){
      return e.Show(outDev);
}
// Methods and operators for KruskalAlgo class
void KruskalAlgo::LoadEdges(istream& inDev)
{
      int nE;
      Edge e;

      inDev >> nVer >> nE;
      for (int i=0; i<nE; i++){
             inDev >> e;
             Edges.push_back(e);
      }
}

bool KruskalAlgo::LoadEdges(char* fName)
{
      ifstream inFile(fName);
      if (inFile){
              LoadEdges(inFile);
              return true;
      }
      return false;
}

void KruskalAlgo::UpdateLabels(int v1, int v2)
{
      if (v1<0 || v1 >= nVer || v2<0 || v2>=nVer){
             return;
      }
      int minLabel = Label[v1], maxLabel = Label[v2];
      if (minLabel > Label[v2]){
             minLabel = Label[v2];
             maxLabel = Label[v1];
      }
      for (int i=0; i<nVer; i++)
             if (Label[i] == maxLabel){
                    Label[i] = minLabel;
             }
}

/* LƯU Ý: Ghi nhận đoạn mã sai sau đây đế rút kinh nghiệm:
if (Label[v1] < Label[v2]){
       for (int i=0; i<nVer; i++)
              if (Label[i] == Label[v2])
                     Label[i] = Label[v1];
}
else{
       for (int i=0; i<nVer; i++)
              if (Label[i] == Label[v1])
                     Label[i] = Label[v2];
}*/
void KruskalAlgo::InitAlg(){
      Label.resize(nVer);
      for (int i=0; i<Label.size(); i++){
             Label[i]=i;
      }
      sort(Edges.begin(), Edges.end());
}

int KruskalAlgo::RunAlg(){ // Thuaät toaùn chính
       InitAlg(); // Böôùc 1
       int nE = Edges.size(), nT = 0;
       for (int i=0; i<nE; i++) { // Böôùc 2
              Edge e=Edges[i];
              int v1=e.getV1(), v2=e.getV2();
              if (Label[v1] != Label[v2]){
                      T.push_back(e);
                      UpdateLabels(v1, v2);
              }
              if ( (nT=T.size()) == nVer-1)
                      break;
       }
       return nT==nVer-1;
}

void KruskalAlgo::ShowT(ostream& outDev)
{
      int nT = T.size(); float w=0;
      for (int i=0; i<nT; i++){
             outDev << T[i] << endl;
             w += T[i].getW();
      }
      outDev << "Total weight = " << w << endl;
}

// end of File Kruskal.cpp---------------------------
// File MainPrg.cpp---------------------------------------
#include "Kruskal.h"

#include <conio.h>
void main() // Lấy dữ liệu từ file
{
      KruskalAlgo g;
      if (g.LoadEdges("gData.txt")){
             g.RunAlg();
             g.ShowT(cout);
      }
      else
             cout << "File not found!" << endl;
      getch();
}

/*
void main() // Lấy dữ liệu từ thiết bị nhập chuẩn (bàn phím console hay tập tin)
{
      KruskalAlgo g;
      g.LoadEdges(cin);
      g.RunAlg();
      g.ShowT(cout);
      getch();
}
*/

// end of File MainPrg.cpp-------------------------------------------

Kruskal algorithm

  • 1.
    // File: Kruskal.h------------------------------------------------------------- #ifndef_MY_KGRAPH_H #define _MY_KGRAPH_H #include <iostream> #include <fstream> #include <vector> #include <algorithm> using namespace std; class Edge { int v1, v2; float w; public: Edge(int v1=0, int v2=0, float w=0); int getV1(); int getV2(); float getW(); ostream& Show(ostream& outDev) const; friend bool operator < (const Edge& e1, const Edge& e2); friend bool operator == (const Edge& e1, const Edge& e2); friend istream& operator >> (istream&, Edge&); friend ostream& operator << (ostream&, const Edge&); }; class KruskalAlgo { vector<int> Label; vector<Edge> Edges; vector<Edge> T; int nVer; void UpdateLabels(int v1, int v2); void InitAlg(); public: void LoadEdges(istream& inDev) ; bool LoadEdges(char* fName) ; int RunAlg(); void ShowT(ostream& outDev); }; #endif // end of File: Kruskal.h-------------------------------------------------------
  • 2.
    // File Kruskal.cpp----------------------------------- #include"Kruskal.h" // Methods and operators for Edge class Edge::Edge(int v1, int v2, float w){ this->w=w; this->v1=v1; this->v2=v2; } int Edge::getV1() { return v1; } int Edge::getV2() { return v2; } float Edge::getW() { return w; } ostream& Edge::Show(ostream& outDev) const { outDev << v1 << "----"<< v2 << " ; w = " << w; return outDev; } bool operator < (const Edge& e1, const Edge& e2){ return e1.w < e2.w; } bool operator == (const Edge& e1, const Edge& e2){ return e1.w == e2.w; } istream& operator >> (istream& inDev, Edge& e){ inDev >> e.v1 >> e.v2 >> e.w; return inDev; } ostream& operator << (ostream& outDev, const Edge& e){ return e.Show(outDev); }
  • 3.
    // Methods andoperators for KruskalAlgo class void KruskalAlgo::LoadEdges(istream& inDev) { int nE; Edge e; inDev >> nVer >> nE; for (int i=0; i<nE; i++){ inDev >> e; Edges.push_back(e); } } bool KruskalAlgo::LoadEdges(char* fName) { ifstream inFile(fName); if (inFile){ LoadEdges(inFile); return true; } return false; } void KruskalAlgo::UpdateLabels(int v1, int v2) { if (v1<0 || v1 >= nVer || v2<0 || v2>=nVer){ return; } int minLabel = Label[v1], maxLabel = Label[v2]; if (minLabel > Label[v2]){ minLabel = Label[v2]; maxLabel = Label[v1]; } for (int i=0; i<nVer; i++) if (Label[i] == maxLabel){ Label[i] = minLabel; } } /* LƯU Ý: Ghi nhận đoạn mã sai sau đây đế rút kinh nghiệm: if (Label[v1] < Label[v2]){ for (int i=0; i<nVer; i++) if (Label[i] == Label[v2]) Label[i] = Label[v1]; } else{ for (int i=0; i<nVer; i++) if (Label[i] == Label[v1]) Label[i] = Label[v2]; }*/
  • 4.
    void KruskalAlgo::InitAlg(){ Label.resize(nVer); for (int i=0; i<Label.size(); i++){ Label[i]=i; } sort(Edges.begin(), Edges.end()); } int KruskalAlgo::RunAlg(){ // Thuaät toaùn chính InitAlg(); // Böôùc 1 int nE = Edges.size(), nT = 0; for (int i=0; i<nE; i++) { // Böôùc 2 Edge e=Edges[i]; int v1=e.getV1(), v2=e.getV2(); if (Label[v1] != Label[v2]){ T.push_back(e); UpdateLabels(v1, v2); } if ( (nT=T.size()) == nVer-1) break; } return nT==nVer-1; } void KruskalAlgo::ShowT(ostream& outDev) { int nT = T.size(); float w=0; for (int i=0; i<nT; i++){ outDev << T[i] << endl; w += T[i].getW(); } outDev << "Total weight = " << w << endl; } // end of File Kruskal.cpp---------------------------
  • 5.
    // File MainPrg.cpp--------------------------------------- #include"Kruskal.h" #include <conio.h> void main() // Lấy dữ liệu từ file { KruskalAlgo g; if (g.LoadEdges("gData.txt")){ g.RunAlg(); g.ShowT(cout); } else cout << "File not found!" << endl; getch(); } /* void main() // Lấy dữ liệu từ thiết bị nhập chuẩn (bàn phím console hay tập tin) { KruskalAlgo g; g.LoadEdges(cin); g.RunAlg(); g.ShowT(cout); getch(); } */ // end of File MainPrg.cpp-------------------------------------------