組み合わせ数学実験——最小重み生成ツリーのPrimアルゴリズム
前のブログと
アルゴリズム:組み合わせ数学中国語第4版機械工業出版社P 328
1 6 10 1 2 28 2 7 14 2 3 16 6 5 25 7 5 24 7 4 18 5 4 22 3 4 12
アルゴリズム:組み合わせ数学中国語第4版機械工業出版社P 328
//////////////////////////////////////////////
// //
// Project Name: PrimTree //
// //
// File Name: P_Tree.h //
// //
// Author: Victor Zhang //
// //
// ID: 21*****92 //
// //
// Create Date: May 20. 2009 //
// //
//////////////////////////////////////////////
#include <iostream>
#include <fstream>
using namespace std;
struct Edge
{
int point_a;
int point_b;
int weigh;
Edge* next;
};
struct Point
{
int value;
Point* next;
};
class P_Tree
{
private:
Edge* EdgeHead;
Point* PHead;
ofstream outputFile;
int TotalWeigh;
bool DelEdge(int, int);
void DelAll();
bool AddPoint(int);
void FindNext();
bool FindPoint(int);
public:
P_Tree()
{
EdgeHead = NULL;
PHead = NULL;
TotalWeigh = 0;
outputFile.open("Graph_output.txt", ios::out);
};
bool AddEdge(int, int, int);
void Prim();
bool ReadFromFile();
~P_Tree()
{
if (EdgeHead) DelAll();
TotalWeigh = 0;
outputFile.close();
};
};
//////////////////////////////////////////////
// //
// Project Name: PrimTree //
// //
// File Name: P_Tree.cpp //
// //
// Author: Victor Zhang //
// //
// ID: 21*****92 //
// //
// Create Date: May 20. 2009 //
// //
//////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include <iomanip>
#include "P_Tree.h"
using namespace std;
bool P_Tree::AddEdge(int x, int y, int w)
{
if (x == y) return false;
if (!(this->EdgeHead))
{
Edge* pH = new Edge;
if (!pH) return false;
pH->next = NULL;
pH->point_a = (x > y) ? x : y;
pH->point_b = (x > y) ? y : x;
pH->weigh = w;
this->EdgeHead = pH;
return true;
}
else
{
Edge* p = this->EdgeHead;
Edge* pH;
while ((p->next) && (p->next->weigh <= w))
{
p = p->next;
};
if ((p->next) && (p->weigh <= w))
{
pH = new Edge;
if (!pH) return false;
pH->next = p->next;
pH->weigh = w;
pH->point_a = (x > y) ? x : y;
pH->point_b = (x > y) ? y : x;
p->next = pH;
}
else if (p->weigh <= w)
{
pH = new Edge;
if (!pH) return false;
pH->next = NULL;
pH->weigh = w;
pH->point_a = (x > y) ? x : y;
pH->point_b = (x > y) ? y : x;
p->next = pH;
}
else
{
pH = new Edge;
if (!pH) return false;
pH->next = p;
pH->weigh = w;
pH->point_a = (x > y) ? x : y;
pH->point_b = (x > y) ? y : x;
this->EdgeHead = pH;
};
return true;
};
};
bool P_Tree::DelEdge(int x, int y)
{
if (x == y) return false;
Edge* p;
Edge* pp;
Edge* pc;
p = this->EdgeHead;
if (!p) return false;
pp = p->next;
if (x < y)
{
int t = x;
x = y;
y = t;
};
while (p && (p->point_a == x) && (p->point_b == y))
{
pp = p->next;
delete p;
p = pp;
this->EdgeHead = pp;
};
if (!p) return true;
pp = p->next;
while (pp)
{
while (pp && (pp->point_a == x) && (pp->point_b == y))
{
pc = pp;
pp = pp->next;
delete pc;
p->next = pp;
};
if (!pp) return true;
p = pp;
pp = p->next;
};
return true;
};
void P_Tree::DelAll()
{
Edge* p;
Point* pP;
while (this->EdgeHead)
{
p = this->EdgeHead->next;
delete this->EdgeHead;
this->EdgeHead = p;
};
while (this->PHead)
{
pP = this->PHead->next;
delete this->PHead;
this->PHead = pP;
};
};
bool P_Tree::AddPoint(int v)
{
Point* p = new Point;
p->value = v;
p->next = this->PHead;
this->PHead = p;
return true;
};
bool P_Tree::FindPoint(int v)
{
Point* p;
p = this->PHead;
while (p && (p->value != v))
p = p->next;
if (p) return true;
return false;
};
void P_Tree::FindNext()
{
if (!(this->EdgeHead)) return;
if (!(this->PHead))
{
this->outputFile<<"("<<this->EdgeHead->point_a<<","<<this->EdgeHead->point_b<<")
";
cout<<"("<<this->EdgeHead->point_a<<","<<this->EdgeHead->point_b<<")
";
this->AddPoint(this->EdgeHead->point_a);
this->AddPoint(this->EdgeHead->point_b);
this->TotalWeigh += this->EdgeHead->weigh;
this->DelEdge(this->EdgeHead->point_a, this->EdgeHead->point_b);
return;
}
else
{
int NewP;
Edge* p;
Point* pP;
p = this->EdgeHead;
while(p)
{
if (this->FindPoint(p->point_a))
{
this->outputFile<<"("<<p->point_a<<","<<p->point_b<<")
";
cout<<"("<<p->point_a<<","<<p->point_b<<")
";
NewP = p->point_b;
this->TotalWeigh += p->weigh;
this->AddPoint(NewP);
pP = this->PHead;
while (pP)
{
this->DelEdge(NewP, pP->value);
pP = pP->next;
};
return;
};
if (this->FindPoint(p->point_b))
{
this->outputFile<<"("<<p->point_a<<","<<p->point_b<<")
";
cout<<"("<<p->point_a<<","<<p->point_b<<")
";
NewP = p->point_a;
this->TotalWeigh += p->weigh;
this->AddPoint(NewP);
pP = this->PHead;
while (pP)
{
this->DelEdge(NewP, pP->value);
pP = pP->next;
};
return;
};
p = p->next;
};
return;
};
};
void P_Tree::Prim()
{
while (this->EdgeHead)
this->FindNext();
cout<<this->TotalWeigh<<endl;
this->outputFile<<this->TotalWeigh<<endl;
};
bool P_Tree::ReadFromFile()
{
ifstream inputFile ("Graph_data.txt", ios::in);
if (!inputFile)
{
cout<<"Error in reading file :\"Graph_data.txt\"."<<endl;
system("pause");
return false;
};
try
{
int i;
int j;
int r;
i = j = r = 0;
inputFile>>i>>j>>r;
if (!(this->AddEdge(i, j, r))) return false;
while(inputFile>>i>>j>>r)
if (!(this->AddEdge(i, j, r)))
return false;
}
catch(...)
{
cout<<"Error in reading file :\"Graph_data.txt\"."<<endl;
system("pause");
inputFile.close();
return false;
};
inputFile.close();
return true;
};
//////////////////////////////////////////////
// //
// Project Name: PrimTree //
// //
// File Name: main.cpp //
// //
// Author: Victor Zhang //
// //
// ID: 21*****92 //
// //
// Create Date: May 20. 2009 //
// //
//////////////////////////////////////////////
#include <iostream>
using namespace std;
#include "P_Tree.h"
void main()
{
P_Tree a;
a.ReadFromFile();
a.Prim();
system("pause");
};
サンプル入力ファイル:1 6 10 1 2 28 2 7 14 2 3 16 6 5 25 7 5 24 7 4 18 5 4 22 3 4 12