【C++】圖

主要完成圖基本操作的實現,圖中頂點的數據類型爲char
主要完成下面6個操作:

  1. 以鄰接矩陣爲存儲結構,創建有向圖
  2. 以鄰接表爲存儲結構,創建無向圖
  3. 在圖中查找某個頂點的位置
  4. 以鄰接矩陣爲存儲結構,創建有向網
  5. 深度遍歷圖
  6. 廣度遍歷圖
  7. 使用迪傑斯特拉算法求圖中某個頂點到其它頂點的最短路徑
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;

#define MaxInt 32767    //權值的最大值
#define MVNum 100       //最大頂點數

//鄰接矩陣存儲結構定義
typedef struct{
	char vexs[MVNum];         //存放頂點的數組
	int arcs[MVNum][MVNum];    //存放鄰接矩陣的數組
	int vexnum,arcnum;         //頂點數和邊(弧)數
}AMGraph;    

//邊(弧)結點結構定義
typedef struct ArcNode{
	int adjvex;
	struct ArcNode *nextarc;
	int weight;	
}ArcNode;

//頂點類型定義
typedef struct VNode{
	char data;
	ArcNode *firstarc;
}VNode,AdjList[MVNum];    //頂點數組類型定義

//鄰接表結構定義
typedef struct{
	AdjList vertices;    //頂點數組
	int vexnum,arcnum;   //頂點數和邊(弧)數
}ALGraph;

//順序隊列結構定義
typedef struct{
	int front;      //隊頭
	int rear;       //隊尾
	char base[MVNum];   //存放隊列元素的數組
}SqQueue;

bool visited[MVNum];   //存放圖中頂點訪問標誌的數組

//初始化隊列
void InitQueue(SqQueue &Q)
{
	Q.front=Q.rear=0;
}

//判斷隊列Q是否爲空,爲空返回true,非空返回false
bool QueueEmpty(SqQueue Q)
{
	if(Q.rear==Q.front )
		return true;
	else
		return false;
}

//入隊操作,將n插入順序隊列Q的尾部
void EnQueue(SqQueue &Q,int n)
{
	if(Q.rear-Q.front==MVNum)  //隊滿時,不能執行入隊操作
		exit(-1);
	else
	{
		Q.base[Q.rear]=n;
		Q.rear++;
	}
}

//出隊操作,刪除隊列Q的隊頭元素,被刪元素用n返回
void DeQueue(SqQueue &Q,int &n)
{
	if(QueueEmpty(Q))     //若隊列爲空,不能執行出隊操作
		exit(-1);
	else
	{
		n=Q.base [Q.front];
		Q.front++;
	}
}

//在以鄰接表方式存儲的圖G中,查找值爲ch的頂點的位置
int LocateVex(ALGraph G,char ch)
{
	//請同學們在此處補充該操作
	for(int i=0;i<G.arcnum;i++)
		if(G.vertices[i].data==ch) return i;
	return -1;//代碼補充完整後,請修改此行代碼,返回值爲ch的頂點的位置
}

//以鄰接表爲存儲結構,創建無向圖G
void CreateUDG_AL(ALGraph &G)
{
	//請同學們在此處補充完整該操作
	char v1,v2;
	int i,j,k;
	ArcNode *p1,*p2;
	cin>>G.vexnum>>G.arcnum;
	for(i=0;i<G.vexnum;i++){
		cin>>G.vertices[i].data;
		G.vertices[i].firstarc=NULL;
	}
	for(k=0;k<G.arcnum;k++){
		cin>>v1>>v2;
		i=LocateVex(G,v1);j=LocateVex(G,v2);
		if(i==-1||j==-1) continue;
		p1=new ArcNode;
		p1->adjvex=j;
		p1->nextarc=G.vertices[i].firstarc;
		G.vertices[i].firstarc=p1;
		
		p2=new ArcNode;
		p2->adjvex=i;
		p2->nextarc=G.vertices[j].firstarc;
		G.vertices[j].firstarc=p2;
	}
}

//輸出圖G的鄰接表 
void PrintALGraph(ALGraph G)
{
	//請同學們在此處補充完整該操作
	ArcNode *p;
	for(int i=0;i<G.vexnum;i++){
		cout<<G.vertices[i].data<<"->";
		p=G.vertices[i].firstarc;
		while(p!=NULL){
			cout<<p->adjvex<<"->";
			p=p->nextarc;
		}
		cout<<"NULL\n";
	}
}

//在以鄰接矩陣方式存儲的圖G中,查找值爲ch的頂點的位置
int LocateVex1(AMGraph G,char ch)
{
	//請同學們在此處補充該操作
	int i;
	for(i=0;i<G.vexnum;i++)
		if(G.vexs[i]==ch) return i;
	return -1;//代碼補充完整後,請修改此行代碼,返回值爲ch的頂點的位置
}

//以鄰接矩陣爲存儲結構,創建有向圖G
void CreateDG_AM(AMGraph &G)
{
	//請同學們在此處補充該操作
	int i,j,k,w;
	char v1,v2;
	cin>>G.vexnum>>G.arcnum;
	for(i=0;i<G.vexnum;i++)
		cin>>G.vexs[i];
	for(i=0;i<G.vexnum;i++)
		for(j=0;j<G.vexnum;j++)
			G.arcs[i][j]=MaxInt;
	for(k=0;k<G.arcnum;k++){
		cin>>v1>>v2;
		i=LocateVex1(G,v1);
		j=LocateVex1(G,v2);
		if(i!=-1&&j!=-1)
			G.arcs[i][j]=1;
	}
}

//輸出有向圖G的信息,包括頂點數,弧數,頂點集合及鄰接矩陣 
void PrintGraphInfo(AMGraph G)
{
	cout<<"頂點數、邊數爲:";
	cout<<G.vexnum<<"  "<<G.arcnum<<endl;       
	cout<<"頂點集合爲:"<<endl;
	cout<<"{ "; 
	for(int i=0;i<G.vexnum;i++)
	{
		cout<<G.vexs[i]<<"  ";
	}
	cout<<"}"<<endl;
	cout<<"鄰接矩陣爲:"<<endl;
	for(int i=0;i<G.vexnum;i++)
	{
	
		for(int j=0;j<G.vexnum;j++)
		{
			printf("%-8d",G.arcs[i][j]);
			//cout<<G.arcs[i][j]<<"   ";
		}
		cout<<endl;
	}
	     
}

//從圖中的第v個頂點出發,深度遍歷圖G(以鄰接表爲存儲結構)
void DFS(ALGraph G,int v)
{
	//請同學們在此處補充該操作
	
	
	

}

//深度遍歷圖G
void DFSTraverse(ALGraph G)
{
	int v;
	for(v=0;v<G.vexnum ;v++)   //初始化所有頂點的訪問標誌位false
		visited[v]=false;
	for(v=0;v<G.vexnum ;v++)   //逐一檢查每個頂點的訪問標誌,找一個未被訪問過的頂點v爲出發點,對圖G進行深度遍歷
	{
		if(visited[v]==false)
			DFS(G,v);
	}
}

//從圖中的第v個頂點出發,廣度遍歷圖G(以鄰接表爲存儲結構)
void BFS(ALGraph G,int v)
{
	SqQueue Q;      //Q爲順序隊列
	ArcNode *p;
	int w,u;
	InitQueue(Q);     //初始化隊列Q
	cout<<G.vertices[v].data<<" ";    //輸出第v個頂點
	visited[v]=true;                   //設置第v個頂點的訪問標誌
	EnQueue(Q,v);                      //將第v個頂點入隊
	
	while(!QueueEmpty(Q))
	{
		//請同學們在此處補充剩餘操作
		
		
		

	}	
}

//廣度遍歷圖G
void BFSTraverse(ALGraph G)
{
	int v;
	for(v=0;v<G.vexnum ;v++)     //初始化所有頂點的訪問標誌位false
		visited[v]=false;
	for(v=0;v<G.vexnum ;v++)     //逐一檢查每個頂點的訪問標誌,找一個未被訪問過的頂點v爲出發點,對圖G進行廣度遍歷
	{
		if(visited[v]==false)
			BFS(G,v);
	}
}


//                        以下內容爲選作(求最短路徑,課下完成)
//*********************************************************************************************

//以鄰接矩陣爲存儲結構,創建有向網G
void CreateDN_AM(AMGraph &G)
{
	//請同學們在此處補充該操作
	int i,j,k,w;
	char v1,v2;
	cin>>G.vexnum>>G.arcnum;
	for(i=0;i<G.vexnum;i++)
		cin>>G.vexs[i];
	for(i=0;i<G.vexnum;i++)
		for(j=0;j<G.vexnum;j++)
			G.arcs[i][j]=MaxInt;
	for(k=0;k<G.arcnum;k++){
		cin>>v1>>v2>>w;
		i=LocateVex1(G,v1);
		j=LocateVex1(G,v2);
		if(i!=-1&&j!=-1)
			G.arcs[i][j]=w;
	}
}

//使用迪傑斯特拉算法求第v0個頂點到其它頂點的最短路徑
void ShortestPath_DIJ(AMGraph G,int v0)
{
	int D[MVNum],Path[MVNum],i,v,w,min;  //數組D存儲源點到其它頂點的最短路徑長度,Path數組存放每個頂點的前驅頂點
	bool S[MVNum];    //每個頂點是否已求得最短路徑的標誌存放在數組S中
	//初始化三個數組
	for(v=0;v<G.vexnum ;v++)
	{
		//請同學們在此處根據註釋,補充該循環




	}
	//將第v0個頂點設置爲源點
	S[v0]=true;
	D[v0]=0;
	//循環G.vexnum-1次,求第v0個頂點到圖中其它頂點的最短距離
	for(i=1;i<G.vexnum ;i++)
	{
		//尋找距離源點最近的第v個頂點
		//請同學們在此處根據註釋,補充該操作





		
		S[v]=true;      //將第v個頂點加入到S中,S表示已求得最短路徑的頂點集合
		//更新源點到其它頂點的最短距離
		for(w=0;w<G.vexnum ;w++)
		{
			//請同學們在此處根據註釋,補充該循環




		}//for(w)
	}//for(i)
	
	//輸出源點到其它頂點的最短路徑及路徑長度
	for(i=1;i<G.vexnum ;i++)
	{
		cout<<"頂點"<<G.vexs [v0]<<"到頂點"<<G.vexs [i]<<"的最短路徑長度爲"<<D[i]<<",路徑爲:";
		//從第i個頂點回溯,輸出第i個頂點到源點的最短路徑
		//請同學們在此處根據註釋,補充該操作,輸出源點到其它頂點的最短路徑





	}
}


int main() 
{
	ALGraph G;   //圖G使用鄰接表爲存儲結構 
	AMGraph G1,G2;   //G1爲有向網,G2爲有向圖,均使用鄰接矩陣爲存儲結構 
	char ch;
	int k;
    //以下操作完成無向圖G的創建(基於鄰接表存儲方式)、輸出G的信息 
	cout<<"以下操作完成無向圖G的創建(基於鄰接表存儲方式)、輸出G的信息"<<endl;
	CreateUDG_AL(G);     //創建無向圖G
	cout<<"無向圖G的鄰接表爲:"<<endl; 
	PrintALGraph(G);
	
	cout<<"圖G的深度遍歷序列爲:";
	DFSTraverse(G);       //深度優先遍歷圖G
	cout<<endl;
	cout<<"圖G的廣度遍歷序列爲:";
	BFSTraverse(G);        //廣度優先遍歷圖G
	cout<<endl<<endl;
	
	//以下操作完成有向圖G2的創建(基於鄰接矩陣存儲方式)、輸出G2的信息(包括頂點信息和鄰接矩陣等) 
	cout<<"以下操作完成有向圖G2的創建(基於鄰接矩陣存儲方式)、輸出G2的信息"<<endl;
	rewind(stdin);
	CreateDG_AM(G2);     //創建有向圖G2
	cout<<"有向圖G2的信息爲:"<<endl;
	PrintGraphInfo(G2); 
	  	

	//以下操作完成有向網G1的創建(基於鄰接矩陣存儲方式),並在G1中求最短路徑
	cout<<endl<<"****************************************************************************"<<endl;
	cout<<"以下操作完成有向網G1的創建(基於鄰接矩陣存儲方式),並在G1中求最短路徑"<<endl;
	CreateDN_AM(G1);    //創建有向網G1
	cout<<"請輸入源點:"<<endl;
	cin>>ch;                  //輸入源點     
	k=LocateVex1(G1,ch);       //求源點在G1中的位置k
	ShortestPath_DIJ(G1,k);    //使用迪傑斯特拉算法求第k個頂點到其它頂點的最短路徑
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章