数据结构与算法 实验8:图ADT的基本实现

假设图结构具有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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章