图的建立:
大家都知道一般创建图可以用两种存储结构:邻接矩阵和邻接表。这里我们采取邻接矩阵的方法。。这两种具体的结构在这里不介绍了。
struct MyGraphic
{
int vertex,edge; //顶点和边
int Matrix[MAX_VERTEX][MAX_VERTEX]; //临接矩阵
};
这就是我做的创建图基本的结构,包括:点数(vertex),边数(edge),存储具体的边( 邻接矩阵)。
下面我们就用这个来创建一个简单的无向图:
#include<iostream>
using namespace std;
#define MAX_VERTEX 10
struct MyGraphic
{
int vertex,edge; //顶点和边
int Matrix[MAX_VERTEX][MAX_VERTEX]; //临接矩阵
};
void CreateGraphic(MyGraphic& myGraphic)
{
cout<<"请输入顶点数和边数:";
cin>>myGraphic.vertex>>myGraphic.edge;
cout<<endl;
int i,j;
for(i=0;i<myGraphic.vertex;i++)
{
for(j=0;j<myGraphic.vertex;j++)
{
myGraphic.Matrix[i][j]=0;
}
}
int vertex1,vertex2;
for(i=0;i<myGraphic.edge;i++)
{
cout<<"请输入第"<<i<<"条边的两个顶点:";
cin>>vertex1>>vertex2;
myGraphic.Matrix[vertex1][vertex2]=1;
myGraphic.Matrix[vertex2][vertex1]=1; //无向图
cout<<endl;
}
}
void printGraphicMatrix(MyGraphic graphic)
{
int i,j;
for(i=0;i<graphic.vertex;i++)
{
for(j=0;j<graphic.vertex;j++)
{
cout<<graphic.Matrix[i][j]<<" ";
}
cout<<endl;
}
}
void main()
{
MyGraphic myGraphic;
CreateGraphic(myGraphic);
printGraphicMatrix(myGraphic);
}
本来想画个图的,但是没有好的工具。
图的遍历:
深度遍历:
bool isVisit[MAX_VERTEX];
struct EdgeInfo
{
int weight; //权重
int flag; //标记是否有边
};
void depth_visit(MyGraphic graphic,int vertex)
{
cout<<" 节点"<<vertex<<" ";
isVisit[vertex]=true;
int j;
for(j=0;j<graphic.vertex;j++)
{
if(graphic.Matrix[vertex][j].flag&&!isVisit[j])
{
depth_visit(graphic,j);
}
}
}
//深度遍历
void depth_traverse(MyGraphic graphic)
{
int i;
for(i=0;i<graphic.vertex;i++)
{
if(!isVisit[i])
{
depth_visit(graphic,i);
}
}
}
广度遍历:
vector<int>g_currentTraverse; //正在访问的节点集合
vector<int>g_waitingTraverse;//等待访问的节点集合
void width_visit(MyGraphic graphic)
{
if(g_currentTraverse.empty())
return;
vector<int>::iterator it=g_currentTraverse.begin();
int j;
for(it;it!=g_currentTraverse.end();it++)
{
if(!isVisit[*it])
{
cout<<"节点"<<*it<<" ";
isVisit[*it]=true;
}
for(j=0;j<graphic.vertex;j++)
{
if(graphic.Matrix[*it][j].flag&&!isVisit[j])
{
g_waitingTraverse.push_back(j);
}
}
}
g_currentTraverse.clear();
g_currentTraverse=g_waitingTraverse;
g_waitingTraverse.clear();
width_visit(graphic);
}
//广度遍历
void width_traverse(MyGraphic graphic)
{
int i;
for(i=0;i<graphic.vertex;i++)
{
if(!isVisit[i])
{
g_currentTraverse.push_back(i);
width_visit(graphic);
}
}
}
完整的遍历程序:
#include<iostream>
#include<vector>
#include<list>
using namespace std;
#define MAX_VERTEX 10
bool isVisit[MAX_VERTEX];
vector<int>g_currentTraverse; //正在访问的节点集合
vector<int>g_waitingTraverse;//等待访问的节点集合
struct EdgeInfo
{
int weight; //权重
int flag; //标记是否有边
};
struct MyGraphic
{
int vertex,edge; //顶点和边
EdgeInfo Matrix[MAX_VERTEX][MAX_VERTEX]; //临接矩阵
};
void CreateGraphic(MyGraphic& myGraphic) //图的建立,初始化
{
cout<<"请输入顶点数和边数:";
cin>>myGraphic.vertex>>myGraphic.edge;
cout<<endl;
int i,j;
for(i=0;i<myGraphic.vertex;i++)
{
for(j=0;j<myGraphic.vertex;j++)
{
myGraphic.Matrix[i][j].flag=0;
myGraphic.Matrix[i][j].weight=0;
}
}
int vertex1,vertex2;
int weight;
for(i=0;i<myGraphic.edge;i++)
{
cout<<"请输入第"<<i<<"条边的两个顶点和权重:";
cin>>vertex1>>vertex2>>weight;
myGraphic.Matrix[vertex1][vertex2].flag=1;
myGraphic.Matrix[vertex2][vertex1].flag=1; //无向图
myGraphic.Matrix[vertex1][vertex2].weight=weight;
myGraphic.Matrix[vertex2][vertex1].weight=weight;
cout<<endl;
}
}
void depth_visit(MyGraphic graphic,int vertex)
{
cout<<" 节点"<<vertex<<" ";
isVisit[vertex]=true;
int j;
for(j=0;j<graphic.vertex;j++)
{
if(graphic.Matrix[vertex][j].flag&&!isVisit[j])
{
depth_visit(graphic,j);
}
}
}
//深度遍历
void depth_traverse(MyGraphic graphic)
{
int i;
for(i=0;i<graphic.vertex;i++)
{
if(!isVisit[i])
{
depth_visit(graphic,i);
}
}
}
void width_visit(MyGraphic graphic)
{
if(g_currentTraverse.empty())
return;
vector<int>::iterator it=g_currentTraverse.begin();
int j;
for(it;it!=g_currentTraverse.end();it++)
{
if(!isVisit[*it])
{
cout<<"节点"<<*it<<" ";
isVisit[*it]=true;
}
for(j=0;j<graphic.vertex;j++)
{
if(graphic.Matrix[*it][j].flag&&!isVisit[j])
{
g_waitingTraverse.push_back(j);
}
}
}
g_currentTraverse.clear();
g_currentTraverse=g_waitingTraverse;
g_waitingTraverse.clear();
width_visit(graphic);
}
//广度遍历
void width_traverse(MyGraphic graphic)
{
int i;
for(i=0;i<graphic.vertex;i++)
{
if(!isVisit[i])
{
g_currentTraverse.push_back(i);
width_visit(graphic);
}
}
}
//输出图信息
void printGraphicMatrix(MyGraphic graphic)
{
int i,j;
//输出边的信息
for(i=0;i<graphic.vertex;i++)
{
for(j=0;j<graphic.vertex;j++)
{
cout<<graphic.Matrix[i][j].flag<<" ";
}
cout<<endl;
}
cout<<endl;
//输出边的权重
for(i=0;i<graphic.vertex;i++)
{
for(j=0;j<graphic.vertex;j++)
{
cout<<graphic.Matrix[i][j].weight<<" ";
}
cout<<endl;
}
}
//遍历图的初始化
void initVisit(MyGraphic graphic)
{
int i;
for(i=0;i<graphic.vertex;i++)
{
isVisit[i]=false;
}
}
void main()
{
MyGraphic myGraphic;
CreateGraphic(myGraphic);
printGraphicMatrix(myGraphic);
initVisit(myGraphic);
cout<<"深度遍历:"<<endl;
depth_traverse(myGraphic);
initVisit(myGraphic);
cout<<endl;
cout<<"广度遍历:"<<endl;
width_traverse(myGraphic);
}
最小生成树(Prime算法)
普利姆(Prim)算法思想
设:N =(V , E)是个连通网,另设U为最小生成树的顶点集,TE为最小生成树的边集。
普利姆(Prim)算法步骤:
(1)初始状态: U ={u0 },( u0 ∈V ),TE= φ,
(2)在u∈U ,v∈(V-U)所有的边(u,v)∈E中,找一条代价最小的边(u0,v0),并将边(u0,v0)并入集合TE,同时v0并入U。
(3)重复(2),直到U=V为止。
此时TE中必有n-1条边,T=(V,{TE})就是最小生成树。
注:在最小生成树的生成过程中,所选的边都是一端在U中,另一端在V-U中。选最小边的过程是一个向集合U中添加顶点的过程。
list<int>g_EleInPrimeTree; //U集合,即已经加入最小生成树的点集合
list<int>g_EleNotInPrimeTree; //V-U集合
#define MAX_WEIGHT 65536
void prime(MyGraphic graphic)
{
if(g_EleNotInPrimeTree.empty())
return;
int min_weight=MAX_WEIGHT;
int index1=0;
int index2=0;
list<int>::iterator it_inPrimeTree=g_EleInPrimeTree.begin();
list<int>::iterator it_notInPrimeTree;
list<int>::iterator temp_it=NULL;
for(it_inPrimeTree;it_inPrimeTree!=g_EleInPrimeTree.end();it_inPrimeTree++)
{
for(it_notInPrimeTree=g_EleNotInPrimeTree.begin();it_notInPrimeTree!=g_EleNotInPrimeTree.end();it_notInPrimeTree++)
{
if(graphic.Matrix[*it_inPrimeTree][*it_notInPrimeTree].flag
&&graphic.Matrix[*it_inPrimeTree][*it_notInPrimeTree].weight<min_weight)
{
min_weight=graphic.Matrix[*it_inPrimeTree][*it_notInPrimeTree].weight;
index1=*it_inPrimeTree;
index2=*it_notInPrimeTree;
temp_it=it_notInPrimeTree;
}
}
}
if(index2&&temp_it!=NULL)
{
g_EleInPrimeTree.push_back(index2);
cout<<"节点"<<index1<<"----"<<"节点"<<index2<<endl;
g_EleNotInPrimeTree.erase(temp_it);
prime(graphic);
}
}
//求最小生成树的初始化
void initPrime(MyGraphic graphic)
{
int i;
g_EleInPrimeTree.push_back(0);
for(i=1;i<graphic.vertex;i++)
{
g_EleNotInPrimeTree.push_back(i);
}
}
我这里实现的很简单,也没优化代码。具体代码如下:
#include<iostream>
#include<vector>
#include<list>
using namespace std;
#define MAX_VERTEX 10
#define MAX_WEIGHT 65536
bool isVisit[MAX_VERTEX];
vector<int>g_currentTraverse; //正在访问的节点集合
vector<int>g_waitingTraverse;//等待访问的节点集合
list<int>g_EleInPrimeTree; //U集合,即已经加入最小生成树的点集合
list<int>g_EleNotInPrimeTree; //V-U集合
struct EdgeInfo
{
int weight; //权重
int flag; //标记是否有边
};
struct MyGraphic
{
int vertex,edge; //顶点和边
EdgeInfo Matrix[MAX_VERTEX][MAX_VERTEX]; //临接矩阵
};
void CreateGraphic(MyGraphic& myGraphic) //图的建立,初始化
{
cout<<"请输入顶点数和边数:";
cin>>myGraphic.vertex>>myGraphic.edge;
cout<<endl;
int i,j;
for(i=0;i<myGraphic.vertex;i++)
{
for(j=0;j<myGraphic.vertex;j++)
{
myGraphic.Matrix[i][j].flag=0;
myGraphic.Matrix[i][j].weight=0;
}
}
int vertex1,vertex2;
int weight;
for(i=0;i<myGraphic.edge;i++)
{
cout<<"请输入第"<<i<<"条边的两个顶点和权重:";
cin>>vertex1>>vertex2>>weight;
myGraphic.Matrix[vertex1][vertex2].flag=1;
myGraphic.Matrix[vertex2][vertex1].flag=1; //无向图
myGraphic.Matrix[vertex1][vertex2].weight=weight;
myGraphic.Matrix[vertex2][vertex1].weight=weight;
cout<<endl;
}
}
void depth_visit(MyGraphic graphic,int vertex)
{
cout<<" 节点"<<vertex<<" ";
isVisit[vertex]=true;
int j;
for(j=0;j<graphic.vertex;j++)
{
if(graphic.Matrix[vertex][j].flag&&!isVisit[j])
{
depth_visit(graphic,j);
}
}
}
//深度遍历
void depth_traverse(MyGraphic graphic)
{
int i;
for(i=0;i<graphic.vertex;i++)
{
if(!isVisit[i])
{
depth_visit(graphic,i);
}
}
}
void width_visit(MyGraphic graphic)
{
if(g_currentTraverse.empty())
return;
vector<int>::iterator it=g_currentTraverse.begin();
int j;
for(it;it!=g_currentTraverse.end();it++)
{
if(!isVisit[*it])
{
cout<<"节点"<<*it<<" ";
isVisit[*it]=true;
}
for(j=0;j<graphic.vertex;j++)
{
if(graphic.Matrix[*it][j].flag&&!isVisit[j])
{
g_waitingTraverse.push_back(j);
}
}
}
g_currentTraverse.clear();
g_currentTraverse=g_waitingTraverse;
g_waitingTraverse.clear();
width_visit(graphic);
}
//广度遍历
void width_traverse(MyGraphic graphic)
{
int i;
for(i=0;i<graphic.vertex;i++)
{
if(!isVisit[i])
{
g_currentTraverse.push_back(i);
width_visit(graphic);
}
}
}
//输出图信息
void printGraphicMatrix(MyGraphic graphic)
{
int i,j;
//输出边的信息
for(i=0;i<graphic.vertex;i++)
{
for(j=0;j<graphic.vertex;j++)
{
cout<<graphic.Matrix[i][j].flag<<" ";
}
cout<<endl;
}
cout<<endl;
//输出边的权重
for(i=0;i<graphic.vertex;i++)
{
for(j=0;j<graphic.vertex;j++)
{
cout<<graphic.Matrix[i][j].weight<<" ";
}
cout<<endl;
}
}
//遍历图的初始化
void initVisit(MyGraphic graphic)
{
int i;
for(i=0;i<graphic.vertex;i++)
{
isVisit[i]=false;
}
}
void prime(MyGraphic graphic)
{
if(g_EleNotInPrimeTree.empty())
return;
int min_weight=MAX_WEIGHT;
int index1=0;
int index2=0;
list<int>::iterator it_inPrimeTree=g_EleInPrimeTree.begin();
list<int>::iterator it_notInPrimeTree;
list<int>::iterator temp_it=NULL;
for(it_inPrimeTree;it_inPrimeTree!=g_EleInPrimeTree.end();it_inPrimeTree++)
{
for(it_notInPrimeTree=g_EleNotInPrimeTree.begin();it_notInPrimeTree!=g_EleNotInPrimeTree.end();it_notInPrimeTree++)
{
if(graphic.Matrix[*it_inPrimeTree][*it_notInPrimeTree].flag
&&graphic.Matrix[*it_inPrimeTree][*it_notInPrimeTree].weight<min_weight)
{
min_weight=graphic.Matrix[*it_inPrimeTree][*it_notInPrimeTree].weight;
index1=*it_inPrimeTree;
index2=*it_notInPrimeTree;
temp_it=it_notInPrimeTree;
}
}
}
if(index2&&temp_it!=NULL)
{
g_EleInPrimeTree.push_back(index2);
cout<<"节点"<<index1<<"----"<<"节点"<<index2<<endl;
g_EleNotInPrimeTree.erase(temp_it);
prime(graphic);
}
}
//求最小生成树的初始化
void initPrime(MyGraphic graphic)
{
int i;
g_EleInPrimeTree.push_back(0);
for(i=1;i<graphic.vertex;i++)
{
g_EleNotInPrimeTree.push_back(i);
}
}
void main()
{
MyGraphic myGraphic;
CreateGraphic(myGraphic);
printGraphicMatrix(myGraphic);
initVisit(myGraphic);
cout<<"深度遍历:"<<endl;
depth_traverse(myGraphic);
initVisit(myGraphic);
cout<<endl;
cout<<"广度遍历:"<<endl;
width_traverse(myGraphic);
//Prime树
cout<<endl;
cout<<"最小生成树:"<<endl;
initPrime(myGraphic);
prime(myGraphic);
}