假设图结构具有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;
}