數據結構與算法 實驗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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章