數據結構:一道實驗題的想法(SDU實驗七 圖的操作)

一道實驗題的想法(圖)

這門課又雙叒叕要寫實驗了…
好在是最後一個實驗,做完了豈不就可以…(浮想聯翩ing)

言歸正傳,先來看看題目:

實驗七 圖的操作
一、 要求完成時間
實驗開始後的第八週之前完成
二、 實驗目的
掌握無向圖的創建、遍歷方法。
三、 實驗內容
1、創建圖類,存儲結構使用鄰接矩陣。
2、輸入圖的節點數 n(不超過 10 個)、邊數 m,節點分別用 1-n 代表。
3、採用“起始節點,終止節點,權值”輸入圖的 m 條邊,創建圖。
4、輸出從節點 1 開始的 BFS 遍歷,在遍歷過程中,如有多個可以選擇
的節點,則優先選擇編號較小的節點。
5、輸出從節點 1 開始的 DFS 遍歷,在遍歷過程中,如有多個可以選擇
的節點,則優先選擇編號較小的節點。
6、輸出從第 1 節點到第 n 節點最短路徑的長度,如果沒有路經,輸出 0。

四、 測試用例及答案
測試如下所有用例及答案,且確保運行後出現完全一樣的輸出,
(操作系統提示“請按任意鍵繼續….”等,可以不一樣。)

看起來貌似很容易是吧,本大少打了半天,看了看樣例,結果他長着樣:
在這裏插入圖片描述
這輸入的是個啥…

好吧,做完了實驗,開始想了想圖的一些東西,嗯,有那味兒了。
關於圖的知識,應該會在另一篇博文中寫道(寫不寫其實還是看本大少心情2333333333)

單純來講講實驗吧

創建圖類,那我們就得了解圖的組成,題目要求說無向加權圖,那麼我們的三個要素:頂點,邊,權值,那我們先來定義一個邊得類:

class edge{
public:
    edge(string str);//構造函數
    int begin;
    int end;
    int length;
};
edge::edge(string str) {
    int n1,n2,theLength;
    int strLength = str.length();
    char strChar[strLength];
    for(int i=0;i<strLength;i++)
        strChar[i] = str.at(i);
    n1 = strChar[0]-'0';
    n2 = strChar[2]-'0';
    int b = strLength-4;
    if(b==1){
        theLength = strChar[4]-'0';
    } else if(b==2){
        theLength = (strChar[4]-'0')*10 + (strChar[5]-'0');
    } else if(b==3){
        theLength = (strChar[4]-'0')*100+(strChar[5]-'0')*10+(strChar[6]-'0');
    }
    begin = n1;
    end = n2;
    length = theLength;
}

那個構造函數是爲了解析題目的輸入,不要在意這種細節23333333

既然邊有了,那麼該來構造圖了:

class WGraph
{
public:
    int n;//頂點個數
    int e;//邊數
    int **a;
    int noEdge = 0;
    WGraph(int numberOfVer);//構造函數
   
};

初始化一個圖只需要知道它的點集,而且我們是使用鄰接矩陣來表示圖,那麼我們要對圖進行操作:插入帶權值的邊,進行寬度優先搜索,深度優先搜索,求最短路徑,接下來就好辦了,寫幾個方法並擴充剛剛定義的WGraph類

class WGraph
{
public:
    int n;//頂點個數
    int e;//邊數
    int **a;
    int noEdge = 0;
public:
    WGraph(int numberOfVer);
    void insertEdge(edge *theEdge);
    void bfs();//寬度優先搜索
    void dfs();//深度優先搜索
    void rdfs(int v,int reach[]);//深度優先搜索遞歸函數
    void path();//最短路徑
};
WGraph::WGraph(int numberOfVer) {
    n=numberOfVer;
    a = new int *[n+1];
    for(int i=0;i<n+1;i++){
        a[i] = new int[n+1];
    }
    for(int i=1;i<n+1;i++)
        for(int j=1;j<n+1;j++)
            a[i][j] = noEdge;
}
void WGraph::insertEdge(edge *theEdge) {
    int v1 = theEdge->begin;
    int v2 = theEdge->end;
    int length = theEdge->length;
    if(a[v1][v2]==noEdge){
        a[v1][v2] = length;
        a[v2][v1] = length;
    }

}

void WGraph::bfs() {
    arrayQueue q;
    arrayQueue out;
    int v = 1;
    int label = 1;
    int reach[n+1];
    for(int i=0;i<n+1;i++)
        reach[i] = 0;
    reach[v] = label;
    q.push(v);
    while (!q.empty()){
        int w = q.front();
        q.pop();
        out.push(w);
        for(int u=1;u<=n;u++){
            if(a[w][u]!=0&&reach[u]==0){
                q.push(u);
                reach[u] = label;
            }
        }
    }
    int temp = out.size();
    for(int i=0;i<temp;i++){
        if(i==temp-1){
            cout<<out.front()<<endl;
        } else{
            cout<<out.front()<<",";
        }
        out.pop();
    }
}
void WGraph::dfs() {
    int reach[n+1];
    for(int i=0;i<=n;i++){
        reach[i] = 0;
    }
    rdfs(1,reach);
    int temp = m->size();
    for(int i=0;i<temp;i++){
        if(i==temp-1){
            cout<<m->front()<<endl;
        } else{
            cout<<m->front()<<",";
        }
        m->pop();
    }
}

void WGraph::rdfs(int v, int *reach) {
    reach[v] = 1;
    m->push(v);
    for(int u = 1;u<=n;u++){
        if(a[v][u]!=0&&reach[u]==0){
            rdfs(u,reach);
        }
    }
}

void WGraph::path() {
    int max = 1000;
    int min,x;
    int len[n+1];
    len[1] = 0;
    int reach[n+1];
    for(int i=0;i<=n;i++){
        reach[i] = 0;
    }
    reach[1]=1;
    for(int i=2;i<=n;i++) {
        len[i] = max;
    }
    for(int i=1;i<=n;i++){
        if(a[1][i]!=0){
            len[i] = a[1][i];
        }
    }
    for(int i=1;i<n;i++){
        min = max;
        for(int j=1;j<=n;j++){
            if(reach[j]==0&&len[j]<min){
                min = len[j];
                x = j;
            }
        }
        reach[x] = 1;
        for(int y=1;y<=n;y++){
            if(a[x][y]!=0){
                if(len[y]>len[x]+a[x][y]){
                    len[y] = len[x]+a[x][y];
                }
            }
        }
    }
    if(len[n]==max){
        cout<<0<<endl;
    } else{
        cout<<len[n]<<endl;
    }

}

這便是關於圖的全部代碼,有些地方爲了契合題目輸出的需要,可能會有一些多餘(咬我啊)
接下來放上實驗的全部代碼:

#include <iostream>
#include <string>
using namespace std;
//邊
class edge{
public:
    edge(string str);
public:
    int begin;
    int end;
    int length;
};
edge::edge(string str) {
    int n1,n2,theLength;
    int strLength = str.length();
    char strChar[strLength];
    for(int i=0;i<strLength;i++)
        strChar[i] = str.at(i);
    n1 = strChar[0]-'0';
    n2 = strChar[2]-'0';
    int b = strLength-4;
    if(b==1){
        theLength = strChar[4]-'0';
    } else if(b==2){
        theLength = (strChar[4]-'0')*10 + (strChar[5]-'0');
    } else if(b==3){
        theLength = (strChar[4]-'0')*100+(strChar[5]-'0')*10+(strChar[6]-'0');
    }
    begin = n1;
    end = n2;
    length = theLength;
}
//隊列
class arrayQueue
{
public:
    arrayQueue(int initialCapacity = 50);
    ~arrayQueue() {delete [] queue;}
    bool empty() const {return theFront == theBack;}
    int size() const
    {return (theBack - theFront + arrayLength) % arrayLength;}
    int& front()
    {
        return queue[(theFront + 1) % arrayLength];
    }
    int& back()
    {
        return queue[theBack];
    }
    void pop()
    {
        theFront = (theFront + 1) % arrayLength;
    }
    void push(const int& theElement);
private:
    int theFront;
    int theBack;
    int arrayLength;
    int *queue;
};
arrayQueue::arrayQueue(int initialCapacity)
{
    arrayLength = initialCapacity;
    queue = new int[arrayLength];
    theFront = 0;
    theBack = 0;
}
void arrayQueue::push(const int& theElement)
{
    if ((theBack + 1) % arrayLength == theFront)
    {
        int* newQueue = new int[2 * arrayLength];

        int start = (theFront + 1) % arrayLength;
        if (start < 2)
            copy(queue + start, queue + start + arrayLength - 1, newQueue);
        else
        {
            copy(queue + start, queue + arrayLength, newQueue);
            copy(queue, queue + theBack + 1, newQueue + arrayLength - start);
        }
        theFront = 2 * arrayLength - 1;
        theBack = arrayLength - 2;
        arrayLength *= 2;
        queue = newQueue;
    }
    theBack = (theBack + 1) % arrayLength;
    queue[theBack] = theElement;
}
arrayQueue *m = new arrayQueue;
//加權無向圖
class WGraph
{
public:
    int n;//頂點個數
    int e;//邊數
    int **a;
    int noEdge = 0;
public:
    WGraph(int numberOfVer);
    void insertEdge(edge *theEdge);
    void bfs();
    void dfs();
    void rdfs(int v,int reach[]);
    void path();
};
WGraph::WGraph(int numberOfVer) {
    n=numberOfVer;
    a = new int *[n+1];
    for(int i=0;i<n+1;i++){
        a[i] = new int[n+1];
    }
    for(int i=1;i<n+1;i++)
        for(int j=1;j<n+1;j++)
            a[i][j] = noEdge;
}
void WGraph::insertEdge(edge *theEdge) {
    int v1 = theEdge->begin;
    int v2 = theEdge->end;
    int length = theEdge->length;
    if(a[v1][v2]==noEdge){
        a[v1][v2] = length;
        a[v2][v1] = length;
    }

}

void WGraph::bfs() {
    arrayQueue q;
    arrayQueue out;
    int v = 1;
    int label = 1;
    int reach[n+1];
    for(int i=0;i<n+1;i++)
        reach[i] = 0;
    reach[v] = label;
    q.push(v);
    while (!q.empty()){
        int w = q.front();
        q.pop();
        out.push(w);
        for(int u=1;u<=n;u++){
            if(a[w][u]!=0&&reach[u]==0){
                q.push(u);
                reach[u] = label;
            }
        }
    }
    int temp = out.size();
    for(int i=0;i<temp;i++){
        if(i==temp-1){
            cout<<out.front()<<endl;
        } else{
            cout<<out.front()<<",";
        }
        out.pop();
    }
}
void WGraph::dfs() {
    int reach[n+1];
    for(int i=0;i<=n;i++){
        reach[i] = 0;
    }
    rdfs(1,reach);
    int temp = m->size();
    for(int i=0;i<temp;i++){
        if(i==temp-1){
            cout<<m->front()<<endl;
        } else{
            cout<<m->front()<<",";
        }
        m->pop();
    }
}

void WGraph::rdfs(int v, int *reach) {
    reach[v] = 1;
    m->push(v);
    for(int u = 1;u<=n;u++){
        if(a[v][u]!=0&&reach[u]==0){
            rdfs(u,reach);
        }
    }
}

void WGraph::path() {
    int max = 1000;
    int min,x;
    int len[n+1];
    len[1] = 0;
    int reach[n+1];
    for(int i=0;i<=n;i++){
        reach[i] = 0;
    }
    reach[1]=1;
    for(int i=2;i<=n;i++) {
        len[i] = max;
    }
    for(int i=1;i<=n;i++){
        if(a[1][i]!=0){
            len[i] = a[1][i];
        }
    }
    for(int i=1;i<n;i++){
        min = max;
        for(int j=1;j<=n;j++){
            if(reach[j]==0&&len[j]<min){
                min = len[j];
                x = j;
            }
        }
        reach[x] = 1;
        for(int y=1;y<=n;y++){
            if(a[x][y]!=0){
                if(len[y]>len[x]+a[x][y]){
                    len[y] = len[x]+a[x][y];
                }
            }
        }
    }
    if(len[n]==max){
        cout<<0<<endl;
    } else{
        cout<<len[n]<<endl;
    }

}

int main()
{
    cout<<"Input"<<endl;
    string str1;
    cin>>str1;
    int str1Length = str1.length();
    int n,m;
    n = str1.at(0)-'0';
    if(str1Length==3){
        m = str1.at(2)-'0';
    } else if(str1Length==4){
        m = (str1.at(2)-'0')*10+(str1.at(3)-'0');
    }
    WGraph wg(n);
    for(int i=0;i<m;i++){
        string str2;
        cin>>str2;
        edge *e = new edge(str2);
        wg.insertEdge(e);
    }
    cout<<"Output"<<endl;
    wg.bfs();
    wg.dfs();
    wg.path();
    cout<<"End";
    return 0;
}

造福SDUers,有要的就拿走吧。

不管是東南風,還是西北風,都是我的歌,我的歌…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章