zoukankan      html  css  js  c++  java
  • 数据结构之图详解

    图的建立:

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

  • 相关阅读:
    PE格式详细讲解10 系统篇10|解密系列
    复杂的数据类型1 C++快速入门07
    复杂的数据类型2 C++快速入门08
    复杂的数据类型2 C++快速入门08
    复杂的数据类型1 C++快速入门07
    PE格式详细讲解10 系统篇10|解密系列
    Win32基础知识1 Win32汇编语言002
    开题篇 Win32汇编语言001
    开题篇 Win32汇编语言001
    Win32基础知识1 Win32汇编语言002
  • 原文地址:https://www.cnblogs.com/pangblog/p/3301776.html
Copyright © 2011-2022 走看看