主要完成圖基本操作的實現,圖中頂點的數據類型爲char
主要完成下面6個操作:
- 以鄰接矩陣爲存儲結構,創建有向圖
- 以鄰接表爲存儲結構,創建無向圖
- 在圖中查找某個頂點的位置
- 以鄰接矩陣爲存儲結構,創建有向網
- 深度遍歷圖
- 廣度遍歷圖
- 使用迪傑斯特拉算法求圖中某個頂點到其它頂點的最短路徑
#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;
}