假设图结构具有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:" ,后面是深度遍历得到的顶点元素序列。
例如:Depth-First Traversal order:abcde
(5) 广度遍历
输入:遍历开始的顶点
输出:先换行,再输出 “Breadth-First Traversal order:”,后面是广度遍历得到的顶点元素序列。
例如:Breadth-First Traversal order:abcde
例如,下面是一个测试用例:
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
输出
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
输入
2
1
3
5
abcde
ab3
ad2
ae10
bc4
bd8
cd3
ce5
de1
**0
2
3
4
d
5
a
0
输出
Adjacency List is:
a:-->e(10)-->d(2)-->b(3)
b:-->d(8)-->c(4)-->a(3)
c:-->e(5)-->d(3)-->b(4)
d:-->e(1)-->c(3)-->b(8)-->a(2)
e:-->d(1)-->c(5)-->a(10)
Degree of Vertex:
Degree(a)=3
Degree(b)=3
Degree(c)=3
Degree(d)=4
Degree(e)=3
Depth-First Traversal order:decba
Breadth-First Traversal order:aedbc
#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
const int maxSize=505;
int visit[505];//记录访问的元素
template<class T>
class Queue//队列ADT
{
private:
T a[maxSize];
int head,tail;
public:
Queue(){
head=0;tail=0;}
void Push(T x){
a[tail]=x;tail=(tail+1)%maxSize;}
void Pop(){
head=(head+1)%maxSize;}
T Front(){
return a[head];}
T Back(){
return a[tail-1];}
int Size(){
return (tail-head+maxSize)%maxSize;}
bool Empty(){
return head==tail;}
};
Queue<int>q;
class graph//图ADT
{
private:
int ver[505];//根据字符确定位置
int g1[505][505];//邻接矩阵
int len;//顶点个数
int dir;//是否有向:1表示有向,2表示无向
int wei;//是否加权:1表示不加权,2表示加权
int sto;//存储类型:1表示邻接矩阵,2表示邻接表
int d[505];//各个结点的度
int in_d[505];//各个结点的入度
int out_d[505];//各个结点的出度
char elements[505];//所有的结点
public:
void Init();
void create(int d1,int w,int s);
void show();//输出存储结构
void showDeg();//输出各顶点的度
void show_dfs();//输出dfs结果
void BFS();//输出bfs结果
void DFS(int x);//深度度遍历
};
void graph::Init()
{
for(int i=1;i<=500;i++)
for(int j=1;j<=500;j++)g1[i][j]=0;
for(int i=1;i<=500;i++)
{
d[i]=0;
in_d[i]=0;
out_d[i]=0;
}
}
void graph::create(int d1,int w,int s)
{
Init();
dir=d1;
wei=w;
sto=s;
int i,weight,x,y;
char e[10];
scanf("%d",&len);
scanf("%s",elements+1);
for(i=1;i<=len;i++)
{
ver[(int)elements[i]]=i;//字符对应的索引
}
while(scanf("%s",e)!=EOF&&e[0]!='*')
{
x=ver[(int)e[0]];
y=ver[(int)e[1]];
if(wei==1)//不加权
{
if(dir==1)//有向
{
g1[x][y]=1;
out_d[x]++;
in_d[y]++;
d[x]++;
d[y]++;
}
else if(dir==2)//无向
{
g1[x][y]=1;
g1[y][x]=1;
d[x]++;
d[y]++;
}
}
else if(wei==2)//加权
{
weight=0;
for(int i=2;e[i]!='\0';i++)weight=weight*10+e[i]-'0';//权不一定是一位
if(dir==1)
{
g1[x][y]=weight;
out_d[x]++;
in_d[y]++;
d[x]++;
d[y]++;
}
else if(dir==2)
{
g1[x][y]=weight;
g1[y][x]=weight;
d[x]++;
d[y]++;
}
}
}
}
void graph::show()
{
if(sto==1)//邻接矩阵
{
printf("Adjacency Matrix is:\n");
printf(" ");
for(int i=1;i<=len;i++)printf("%6c",elements[i]);
printf("\n");
for(int i=1;i<=len;i++)
{
printf("%4c",elements[i]);
for(int j=1;j<=len;j++)
{
if(wei==1)printf("%6d",g1[i][j]);
else if(wei==2)
{
if(i!=j&&g1[i][j]==0)printf(" ∞");//有权图中权
else printf("%6d",g1[i][j]);
}
}
printf("\n");
}
}
else if(sto==2)//邻接表
{
printf("Adjacency List is:\n");
for(int i=1;i<=len;i++)
{
printf("%c:",elements[i]);
for(int j=len;j>=1;j--)
{
if(g1[i][j]!=0)
{
if(wei==1)printf("-->%c",elements[j]);
else if(wei==2)printf("-->%c(%d)",elements[j],g1[i][j]);
}
}
printf("\n");
}
}
}
void graph::showDeg()
{
printf("Degree of Vertex:\n");
if(dir==1)
{
for(int i=1;i<=len;i++)
{
printf("Degree(%c)=%d\n",elements[i],d[i]);
printf("Out_Degree(%c)=%d;In_Degree(%c)=%d\n\n",elements[i],out_d[i],elements[i],in_d[i]);
}
}
else if(dir==2)
{
for(int i=1;i<=len;i++)printf("Degree(%c)=%d\n",elements[i],d[i]);
}
}
void graph::show_dfs()
{
char poi[5];
scanf("%s",poi);
for(int i=1;i<=len;i++)visit[i]=0;
int start=ver[(int)poi[0]];
printf("Depth-First Traversal order:");
for(int i=start;i<=len;i++)if(visit[i]==0)DFS(i);//从当前结点遍历到最后
for(int i=1;i<=start-1;i++)if(visit[i]==0)DFS(i);//从第一个结点遍历到当前结点
printf("\n");
}
void graph::DFS(int x)
{
printf("%c",elements[x]);
visit[x]=1;
if(sto==1)
for(int i=1;i<=len;i++)
{
if(g1[x][i]!=0&&visit[i]==0)DFS(i);
}
else if(sto==2)
for(int i=len;i>=1;i--)
{
if(g1[x][i]!=0&&visit[i]==0)DFS(i);
}
}
void graph::BFS()
{
char poi[5];
scanf("%s",poi);
for(int i=1;i<=len;i++)visit[i]=0;
int start=ver[(int)poi[0]];
visit[start]=1;
q.Push(start);
printf("Breadth-First Traversal order:");
int t;
if(sto==1)
{
while(!q.Empty())//借助队列完成广度遍历
{
t=q.Front();
q.Pop();
printf("%c",elements[t]);
for(int i=1;i<=len;i++)//邻接矩阵从前往后
{
if(g1[t][i]!=0&&visit[i]==0)
{
q.Push(i);
visit[i]=1;
}
}
}
}
else if(sto==2)
{
while(!q.Empty())
{
t=q.Front();
q.Pop();
printf("%c",elements[t]);
for(int i=len;i>=1;i--)//邻接表从后往前
{
if(g1[t][i]!=0&&visit[i]==0)
{
q.Push(i);
visit[i]=1;
}
}
}
}
}
graph g;
int main()
{
int storage,kind,op;
scanf("%d",&storage);
if(storage==1)
{
while(1)
{
scanf("%d",&op);
switch(op)
{
case 0:
exit(0);
case 1:
scanf("%d",&kind);
if(kind==1)g.create(2,1,1);//无向,不加权
else if(kind==2)g.create(1,1,1);//有向,不加权
else if(kind==3)g.create(2,2,1);//无向,加权
else if(kind==4)g.create(1,2,1);//有向,加权
break;
case 2:
printf("\n");
g.show();
break;
case 3:
printf("\n");
g.showDeg();
break;
case 4:
printf("\n");
g.show_dfs();
break;
case 5:
printf("\n");
g.BFS();
break;
}
}
}
else if(storage==2)
{
while(1)
{
scanf("%d",&op);
switch(op)
{
case 0:
exit(0);
case 1:
scanf("%d",&kind);
if(kind==1)g.create(2,1,2);//无向,不加权
else if(kind==2)g.create(1,1,2);//有向,不加权
else if(kind==3)g.create(2,2,2);//无向,加权
else if(kind==4)g.create(1,2,2);//有向,加权
break;
case 2:
printf("\n");
g.show();
break;
case 3:
printf("\n");
g.showDeg();
break;
case 4:
printf("\n");
g.show_dfs();
break;
case 5:
printf("\n");
g.BFS();
break;
}
}
}
return 0;
}