#include<iostream>
#include<list>
#include<fstream>
using namespace std;
const double MAXCOST = 10000;
struct PathData
{
int start,dest;
double cost;
operator double()const{return cost;}
} ;
template <class T>
class Graph
{
struct EdgeNode
{
int dest;
double cost;
operator int() { return dest; }
};
T* VA;
list<EdgeNode>* HL;
int sizeV, sizeE;
int maxV;
public:
Graph(int n = 100) :sizeV(0), sizeE(0), maxV(n)
{
VA = new T[n];
HL = new list<EdgeNode>[n];
}
~Graph()
{
delete[]VA;
delete[]HL;
}
int Empty()const { return sizeV == 0; }
int Full()const { return sizeV == maxV; }
int SizeV()const { return sizeV; }
int SizeE()const { return sizeE; }
int FindNode(const T& v)const;
bool StoreNode(T&v,int pos)const;
double GetCost(const T& vl, const T& v2)const;
bool InsertV(const T& v);
bool InsertE(const T& v1, const T& v2, double w);
bool DeleteV(const T& v);
bool DeleteE(const T& v1, const T& v2);
void ReadGraph(const char* filename);
void WriteGraph(const char* filename);
void BuildHeap(PathData*E,int size)const;
void PercolateDown(PathData*E,int pos,int size)const;
bool Prim(const T&v,PathData* E,int ne)const;
friend istream& operator>>(istream& istr,Graph<T>& g)
{
char s[50];
int n;
double w;
T v1,v2;
istr>>s>>n;
for(int i=1;i<=n;++i)
{
istr>>v1;
g.InsertV(v1);
}
istr>>s>>n;
for(int i=1;i<=n;++i)
{
istr>>v1>>v2>>w;
g.InsertE(v1,v2,w);
}
return istr;
}
friend ostream& operator<<(ostream& ostr,const Graph<T>&g)
{
for(int i=0;i<g.sizeV;i++)
{
ostr<<i<<'-'<<g.VA[i]<<':';
typename list<Graph<T>::EdgeNode>::iterator first=g.HL[i].begin(),last=g.HL[i].end();
for(;first!=last;++first)
ostr<<'('<<(*first).dest<<','<<(*first).cost<<')'<<' ';
ostr<<endl;
}
return ostr;
}
};
template <class T>
int Graph<T>::FindNode(const T& v)const
{
for (int i = 0; i < sizeV; i++)
if (VA[i] == v)
return i;
return 0;
}
template<class T>
bool Graph<T>::StoreNode(T&v, int pos)const
{
if(pos<0||pos>sizeV-1)
return 0;
v=VA[pos];
return 1;
}
template<class T>
double Graph<T>::GetCost(const T& v1, const T& v2)const
{
int si = FindNode(v1), dj = FindNode(v2);
if (si < 0 || si >= sizeV || dj < 0 || dj >= sizeV || dj == si)
{
return 0;
}
typename list<EdgeNode>::const_iterator first = HL[si].begin(), last = HL[si].end();
for (; first != last; ++first)
{
if ((*first).dest == dj)
return (*first).cost;
}
return 0;
}
template<class T>
bool Graph<T>::InsertV(const T& v)
{
if (sizeV == maxV)
{
return 0;
}
VA[sizeV] = v;
sizeV++;
return 1;
}
template<class T>
bool Graph<T>::InsertE(const T& v1, const T& v2, double w)
{
int si = FindNode(v1), dj = FindNode(v2);
if (si < 0 || dj < 0 || si == dj)
{
return 0;
}
EdgeNode en;
en.dest = dj;
en.cost = w;
HL[si].insert(HL[si].end(), en);
sizeE++;
return 1;
}
template <class T>
bool Graph<T>::DeleteE(const T& v1, const T& v2)
{
int si = FindNode(v1), dj = FindNode(v2);
if (si < 0 || dj < 0 || si == dj)
{
return 0;
}
typename list<EdgeNode>::iterator first = HL[si].begin(), last = HL[si].end();
for (; first != last; ++first)
{
if ((*first).dest == dj)
{
HL[si].Erase(first);
sizeE--;
return 1;
}
}
return 0;
}
template<class T>
bool Graph<T>::DeleteV(const T& v)
{
int si = FindNode(v);
if (si<0 || si>sizeV - 1)
return 0;
int size = HL[si].size();
for (int i = si; i<sizeV-1; i++)
{
VA[i] = VA[i + 1];
HL[i] = HL[i + 1];
}
HL[sizeV - 1].clear();
sizeV--;
sizeE = sizeE - size;
typename list<EdgeNode>::iterator first, last;
for (int i = 0; i < sizeV; i++)
{
first = HL[i].begin(),last = HL[i].end();
for (; first != last; ++first)
{
if ((*first).dest ==si)
{
HL[i].erase(first);
sizeE--;
break;
}
}
}
for (int i = 0; i < sizeV; i++)
{
first = HL[i].begin(), last = HL[i].end();
for (; first != last; ++first)
{
if ((*first).dest > si)
{
(*first).dest--;
}
}
}
return 1;
}
template <class T>
void Graph<T>::ReadGraph(const char* filename)
{
char str[50];
int n;
double w;
T v1, v2;
ifstream fin;
fin.open(filename, ios::in);
if (!fin)
{
cout << "cannot open" << filename << endl;
exit(1);
}
fin >> str >> n;
for (int i = 1; i <= n; ++i)
{
fin >> v1;
InsertV(v1);
}
fin >> str >> n;
for (int i = 1; i <=n; ++i)
{
fin >> v1 >> v2 >> w;
InsertE(v1, v2, w);
}
}
template<class T>
void Graph<T>::WriteGraph(const char* filename)
{
ofstream fout;
fout.open(filename, ios::out);
if (!fout)
{
cout << "cannot open" << filename << endl;
exit(1);
}
for (int i = 0; i < sizeV; i++)
{
fout << i << '-' << VA[i] << ":";
typename list<Graph<T>::EdgeNode>::iterator first = HL[i].begin(), last = HL[i].end();
for (; first != last; ++first)
{
fout << '(' << (*first).dest << ',' << (*first).cost << ')' << ' ';
}
fout << endl;
}
}
template <class T>
void Graph<T>::PercolateDown(PathData*E,int pos,int size)const
{
int p=pos,c=2*p+1;
PathData temp=E[p];
while(c<size)
{
if(c+1<size&&E[c+1]<E[c])//隐式调用成员转换函数来比较权
++c;
if(temp<E[c])
break;
else
{
E[p]=E[c];
p=c;
c=2*p+1;
}
}
E[p]=temp;
}
template <class T>
void Graph<T>::BuildHeap(PathData*E,int size)const
{
for(int i=size/2-1;i>=0;i--)
PercolateDown(E,i,size);
}
template <class T>
bool Graph<T>::Prim(const T&v,PathData*E,int ne)const
{
int i,j,s,ns;
PathData item;
double cost;
s=FindNode(v);
if(s<0||s>sizeV-1)
return 0;
int id=0;
for(int i=0;i<=ne;i++)
{
if(i!=s)
{
item.start=s;
item.dest=i;
cost=GetCost(VA[s],VA[i]);
item.cost=(cost==0?MAXCOST:cost);
E[id++]= item; //???????????
}
}
int count=0;
BuildHeap(E,ne);//对候选边集建堆,取最小的
for(int i=0;i<ne;i++)
{
if(E[0]<MAXCOST)//调用成员转换函数比较权
count++;
ns=E[0].dest;
for(int j=1;j<ne-i;j++)
{
cost=GetCost(VA[ns],VA[E[j].dest]);
cost=(cost==0?MAXCOST:cost);
if(E[j]>cost)
{
E[j].cost=cost;
E[j].start=ns;
}
}
item=E[0];
E[0]=E[ne-1-i];
E[ne-1-i]=item;
PercolateDown(E,0,ne-1-i);
}
return (count==ne?1:0);
}
template <class T>
void Display(const Graph<T>&g,PathData*E,int ne)
{
T v1,v2;
for(int i=ne-1;i>-1;i--)
{
g.StoreNode(v1,E[i].start);
g.StoreNode(v2,E[i].dest);
E[i].cost=g.GetCost(v1,v2);
cout<<'('<<v1<<','<<v2<<','<<E[i].cost<<')'<<endl;
}
}
int main()
{
Graph<char> G;
G.ReadGraph("Graphmin.txt");
cout<<G;
PathData *E=new PathData[G.SizeV()-1];
if(G.Prim('A',E,G.SizeV()-1))
{
cout<<"Prim:\n";
Display(G,E,G.SizeV()-1);
}
return 0;
}
08-04
7565
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)