数据结构之图详解

图的建立:

大家都知道一般创建图可以用两种存储结构:邻接矩阵和邻接表。这里我们采取邻接矩阵的方法。。这两种具体的结构在这里不介绍了。
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);
}
  

 

posted @ 2013-09-04 19:15  pangbangb  阅读(482)  评论(0编辑  收藏  举报