假設圖結構具有n個元素(頂點,n不大於500),數據元素爲字符,如果是加權圖,權值爲整數。請編碼實現圖ADT。
存儲結構的選擇: 1: 鄰接矩陣 2: 鄰接表
執行的操作:
1:創建圖
2:輸出圖的存儲結構(鄰接矩陣或鄰接表,格式見後面說明)
3:計算各個頂點的度(有向圖時,分爲入度和出度)
4:深度遍歷(需要輸入遍歷開始頂點)
5:廣度遍歷(需要輸入遍歷開始頂點)
0:退出
注:
(1)圖的類型分爲4種,
1:無向,不加權
2:有向,不加權
3:無向,加權
4:有向,加權
(2)邊用一對頂點元素表示,權值爲整數,例如非加權圖邊 ab,加權圖ab6
操作相關說明:
運行時首先選擇存儲結構,輸入1或2
然後選擇要執行的操作,輸入0-5中的一個,第1個操作必須是0或1
(1)創建圖:
輸入有多行,包括:
第一行,一個整數,指出圖的類型,見前面說明。
第二行,一個整數,輸入圖的頂點個數
第三行,輸入各個頂點元素字符
後面多行,輸入兩個字符表示頂點的各條邊,如果是加權圖,後面還有一個整數權值。當輸入**字符時(需要權值時,任意)表示邊的輸入結束。
最後是要執行的操作
頂點按輸入順序存儲;如果採用鄰接表存儲,輸入邊時鄰接點採用插入到前面(所在鏈表頭)
例如:
1 //鄰接矩陣存儲結構
1 //創建圖
1 //無向,不加權圖
6 //頂點個數
abcdef //頂點元素
ab // 邊(a,b),下同
ad
ae
bc
ce
df
ef
** //輸入兩個*表示邊輸入結束
(2)輸出圖存儲結構
如果是鄰接矩陣,就按矩陣形式輸出,有行、列元素標題。行標題佔位4,元素佔位6。如:
Adjacency Matrix is:
a b c d e f
a 0 1 0 1 1 0
b 1 0 1 0 0 0
c 0 1 0 0 1 0
d 1 0 0 0 0 1
e 1 0 1 0 0 1
f 0 0 0 1 1 0
如果是鄰接表,先輸出頂點元素,再輸出各個鄰接點,如果有權值則用括號把權值括起來。例如輸出:
Adjacency List is:
a:-->e-->d-->b
b:-->c-->a
c:-->e-->b
d:-->f-->a
e:-->f-->c-->a
f:-->e-->d
對於有權值圖,輸出爲 a:–>e(3)–>d(10)
(3) 計算各個頂點的度並輸出,對有向圖要分別計算出度和入度
無向圖輸出形式爲:
Degree of Vertex:
Degree(a)=3
Degree(b)=2
…
有向圖輸出形式爲:
Degree of Vertex:
Degree(a)=6
Out_Degree(a)=2;In_Degree(a)=4
Degree(b)=2
Out_Degree(b)=2;In_Degree(b)=0
…
(4) 深度遍歷
輸入:遍歷開始的頂點
輸出: 先換行,再輸出 Depth-First Traversal order: …
(5) 廣度遍歷
輸入:遍歷開始的頂點
輸出:先換行,再輸出 Breadth-First Traversal order: …
例如,下面是一個測試用例:
1 //選擇存儲結構,鄰接矩陣
1 //選擇操作,創建圖
1 //圖類型,無向無權圖
6 //頂點個數
abcdef //輸入頂點元素
ab //輸入一條邊(a,b)
ad
ae
bc
ce
df
ef
** //邊輸入結束
2 //輸出存儲結構
3 //計算圖頂點的度
0 //結束
例如:
輸入
1
1
1
6
abcdef
ab
ad
ae
bc
ce
df
ef
**
2
3
0
Result
Adjacency Matrix is:
a b c d e f
a 0 1 0 1 1 0
b 1 0 1 0 0 0
c 0 1 0 0 1 0
d 1 0 0 0 0 1
e 1 0 1 0 0 1
f 0 0 0 1 1 0
Degree of Vertex:
Degree(a)=3
Degree(b)=2
Degree(c)=2
Degree(d)=2
Degree(e)=3
Degree(f)=2
思路:
本題比較麻煩的是題目沒有說清楚輸出的格式,主要有以下幾點:
1)DFS和BFS都要遍歷所有節點
2)DFS和BFS的遍歷順序沒說清楚,具體遍歷順序見代碼
3)以鄰接矩陣格式輸出當其爲有權圖時,若其中兩個節點沒有相連,輸出∞(嘿嘿,沒想到吧!)
4)注意2,3操作前要換行(這個要看清楚題目)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
bool visit[505];
int getweight(char s[15])
{
int sum=0,len=strlen(s);
for(int i=2;i<len;i++)
sum=sum*10+s[i]-'0';
return sum;
}
class graph
{
public:
const int MARTIX=1;
const int LIST=2;
const int DIRECTED1=2;
const int DIRECTED2=4;
int save_type;///存儲結構
int type;///圖的類型
int siz;///元素個數
char node[505];///存儲元素
int has[500];///映射爲序號
int deg[505];///度數
int Out_deg[505];///出度
int In_deg[505];///入度
int g[505][505];///鄰接矩陣
void ini()///圖的初始化
{
siz=0;
memset(g,0,sizeof(0));
memset(deg,0,sizeof(0));
memset(Out_deg,0,sizeof(0));
memset(In_deg,0,sizeof(0));
memset(has,0,sizeof(0));
memset(node,0,sizeof(0));
}
void create()///建圖
{
ini();
cin>>type;
cin>>siz;///頂點個數;
for(int i=1;i<=siz;i++)
{
char c; cin>>c;
node[i]=c;
has[c-'\0']=i;///元素字符映射成序號,方便查詢是第幾個
}
char s[15];
while(cin>>s&&s[0]!='*')
{
int u=has[s[0]-'\0']; ///獲得節點序號
int v=has[s[1]-'\0'];
deg[u]++,deg[v]++;
if(type==1) g[u][v]=g[v][u]=1; ///無向無權圖
if(type==2) ///有向無權圖
{
g[u][v]=1;
Out_deg[u]++,In_deg[v]++;
}
if(type==3||type==4) ///加權圖
{
int w=getweight(s); ///獲得權值
if(type==3)g[u][v]=g[v][u]=w;///無向圖
if(type==4) ///有向圖
{
g[u][v]=w;
Out_deg[u]++,In_deg[v]++;
}
}
}
}
void print_graph()///輸出圖
{
if(save_type==MARTIX)///鄰接矩陣輸出
{
cout<<"Adjacency Matrix is:"<<endl;
cout<<" ";
for(int i=1;i<=siz;i++)
printf("%6c",node[i]);///行標
cout<<endl;
for(int i=1;i<=siz;i++)
{
printf("%4c",node[i]);///列標
for(int j=1;j<=siz;j++)
{
if(type==1||type==2)///無權圖
printf("%6d",g[i][j]);
else ///有權圖
{
if(i!=j&&g[i][j]==0)///無連邊輸出無窮
printf(" ∞");
else
printf("%6d",g[i][j]);
}
}
cout<<endl;
}
}
if(save_type==LIST)///鄰接表輸出
{
cout<<"Adjacency List is:"<<endl;
for(int i=1;i<=siz;i++)
{
cout<<node[i]<<':';
int u=has[node[i]-'\0'];
for(int j=siz;j>=1;j--)
{
if(g[u][j])
{
cout<<"-->"<<node[j];
if(type==3||type==4)///輸出權值
cout<<'('<<g[u][j]<<')';
}
}
cout<<endl;
}
}
}
void print_degree()
{
cout<<"Degree of Vertex:"<<endl;
for(int i=1;i<=siz;i++)
{
int u=has[node[i]-'\0'];///獲得元素序號
printf("Degree(%c)=%d\n",node[i],deg[u]);
if(type==DIRECTED1||type==DIRECTED2)///注意輸出時有兩個空行
printf("Out_Degree(%c)=%d;In_Degree(%c)=%d\n\n",node[i],Out_deg[u],node[i],In_deg[u]);
}
}
void DFS(int u)
{
if(!visit[u]) cout<<node[u];
visit[u]=true;
if(save_type==LIST)///以鄰接表方式存儲
{
for(int i=siz;i>=1;i--)///從第siz個節點開始遍歷
if(g[u][i]&&!visit[i]) DFS(i);
}
if(save_type==MARTIX)///以鄰接矩陣方式存儲
{
for(int i=1;i<=siz;i++)///從第1個節點開始遍歷
if(g[u][i]&&!visit[i]) DFS(i);
}
return;
}
void print_DFS(int u)
{
memset(visit,0,sizeof(visit));
cout<<"Depth-First Traversal order:";
for(int i=u;i<=siz;i++)///先從u到siz遍歷
if(!visit[i])DFS(i);
for(int i=1;i<=u-1;i++)///再從1到u遍歷
if(!visit[i])DFS(i);
cout<<endl;
}
void BFS(int u)
{
queue<int> q;
if(visit[u]) return;
visit[u]=true;
q.push(u);
while(!q.empty())
{
int v=q.front();
q.pop();
cout<<node[v];
if(save_type==LIST)///以鄰接表存儲
{
for(int i=siz;i>=1;i--)///從第siz個節點開始遍歷
{
if(g[v][i]&&!visit[i])
{
q.push(i);
visit[i]=true;
}
}
}
if(save_type==MARTIX)///以鄰接矩陣存儲
{
for(int i=1;i<=siz;i++)///從第1個節點開始遍歷
{
if(g[v][i]&&!visit[i])
{
q.push(i);
visit[i]=true;
}
}
}
}
}
void print_BFS(int u)
{
memset(visit,0,sizeof(visit));
cout<<"Breadth-First Traversal order:";
for(int i=u;i<=siz;i++)
if(!visit[i]) BFS(i);
for(int i=1;i<u;i++)
if(!visit[i]) BFS(i);
cout<<endl;
}
};
int main()
{
graph G;
cin>>G.save_type;
int op;
while(cin>>op)
{
if(op==0) break;
if(op==1) G.create();
if(op==2) cout<<endl,G.print_graph();
if(op==3) cout<<endl,G.print_degree();
if(op==4||op==5)
{
cout<<endl;
char e;
cin>>e;
int u=G.has[e-'\0'];///獲得起始點的下標
if(op==4) G.print_DFS(u);
if(op==5) G.print_BFS(u);
}
}
return 0;
}