實驗五 圖的操作(數據結構實驗C++編寫)

1.實驗目的

(1)掌握圖的鄰接矩陣和鄰接表存儲方式;
(2)掌握圖的遍歷算法;
(3)掌握圖的實際應用——最短路徑算法。

2.實驗內容

(1)採用鄰接矩陣/鄰接表建立圖;
(2)採用深度優先/廣度優先搜索方式遍歷圖;
(3)編程實現Dijkstra最短路徑算法。

3.實驗步驟

  1. 編寫代碼,採用鄰接表法建立有向圖:
    (1)輸入總邊數、總點數;
    (2)依次輸入點的信息存入頂點表,使每個表頭結點的指針域初始化爲NULL;
    (3)創建鄰接表,依次輸入每條邊依附的兩個頂點,以及邊的權值,確定這兩個定點的序號i和j後,將邊結點分別插入v_i和v_j對應的兩個邊鏈表的頭部。
  2. 編寫代碼,實現深度優先搜索方式遍歷圖:
    (1)從圖中某個頂點v出發,訪問v,並設置visited[v]的值爲true;
    (2)依次檢查v的所有鄰接點w,如果visited[w]的值爲false,再從w出發進行遞歸遍歷,直到圖中所有頂點都被訪問過。
  3. 編程實現Dijkstra最短路徑算法。
    (1)初始化最短路徑數組D,將其賦值爲最大值10000;
    (2)如果v0與vi之間有弧,則將他們的權值賦給D[i];
    (3)初始化數組S,將源點v0加到S中,即S[v0] = true;
    (4)選擇下一條最短路徑的終點vk,令S[k]=true;
    (5)根據條件更新從v0到其他頂點的最短路徑的長度,若D[k]+p->info<D[p->adjvex],則令D[p->adjvex] = D[k]+p->info。

4.實驗代碼

#include <iostream>
#include <iomanip>

using namespace std;
#define MVNum 100
bool visited[100] = {false};
//有向圖的鄰接表存儲表示 95
typedef int OtherInfo;
typedef char VerTexType;
//邊結點
typedef struct ArcNode
{
    int adjvex;                 //該邊指向的頂點的位置
    struct ArcNode *nextarc;    //指向下一條邊的指針
    OtherInfo info;             //權值
}ArcNode;
//頂點信息
typedef struct VNode
{
    VerTexType data;            //頂點的值
    ArcNode *firstarc;          //指向第一條依附該頂點的邊的指針
}VNode,AdjList[MVNum];
//鄰接表
typedef struct
{
    AdjList vertices;
    int vexnum,arcnum;          //圖的頂點數,邊數
}ALGraph;
//確定定點u在圖中的位置
int LocateVex(ALGraph G,VerTexType u);
//創建有向圖
void CreateDG(ALGraph &G);
//深度優先遍歷
void DFS_AL(ALGraph G,int v);
//Dijkstra算法
void ShortestPath_DIJ(ALGraph G,int v0);


int main()
{
    int v0;
    VerTexType data;

    ALGraph G;
    CreateDG(G);
    cout << "請輸入v0的值:" ;
    cin >> data;
    v0 = LocateVex(G,data);
    cout << "深度優先遍歷後得到的頂點順序爲:";
    DFS_AL(G,v0);
    cout << endl;
    cout << "請輸入v0的值:" ;
    cin >> data;
    v0 = LocateVex(G,data);
    ShortestPath_DIJ(G,v0);

    return 0;
}

int LocateVex(ALGraph G,VerTexType u)
{
    //若G中存在頂點u,則返回該頂點的位置,否則返回-1.
    for(int i=0;i<G.vexnum;++i)
        if(u == G.vertices[i].data)
            return i;
    return -1;
}
void CreateDG(ALGraph &G)
{
    VerTexType v1,v2;
    OtherInfo otherInfo;
    //VerTexType ch[8] = "abcdefg";
    //VerTexType ch1[12] = "aaabcceffgd";
    //VerTexType ch2[12] = "bcdeefggdbg";
    //OtherInfo oi[11] = {15,2,12,6,8,4,9,10,5,4,3};
    int j,k;
    cout << "請輸入圖的總邊數,總點數:";
    cin >> G.arcnum >> G.vexnum;
    //G.arcnum = 11;
    //G.vexnum = 7;
    cout << "請輸入頂點的值:";

    //表頭結點
    for(int i=0;i<G.vexnum;++i)
    {
        //G.vertices[i].data = ch[i];
        cin >> G.vertices[i].data;
        G.vertices[i].firstarc = NULL;
    }
    cout << "請輸入一條邊依附的兩個頂點以及邊的權值:";

    //邊結點
    for(int i=0;i<G.arcnum;++i)
    {
        cin >> v1 >> v2 >> otherInfo;
        //v1 = ch1[i];v2 = ch2[i];otherInfo = oi[i];
        j = LocateVex(G,v1);
        k = LocateVex(G,v2);
        ArcNode* p1 = new ArcNode;
        p1->adjvex = k;
        p1->info = otherInfo;
        p1->nextarc = G.vertices[j].firstarc;
        G.vertices[j].firstarc = p1;
    }
}

void DFS_AL(ALGraph G,int v)
{

    int w;
    cout << v << ":" << G.vertices[v].data << " ";
    visited[v] = true;
    ArcNode* p = G.vertices[v].firstarc;
    while(p != NULL)
    {
        w = p->adjvex;
        if(!visited[w])
            DFS_AL(G,w);
        p = p->nextarc;
    }

}
void ShortestPath_DIJ(ALGraph G,int v0)
{
    int n = G.vexnum,k;
    bool S[n] = {false};
    OtherInfo D[n],Min;
    int Path[n];

    ArcNode* p;
    //初始化最短路徑的值
    for(int v=0;v<n;++v)
        D[v] = 10000;
    p = G.vertices[v0].firstarc;
    //將與v0相關聯的邊的權值賦給D[]
    while(p != NULL)
    {
        D[p->adjvex] = p->info;
        p = p->nextarc;
    }
    S[v0] = true;       //將v0加入終點集
    Path[0] = v0;       //記錄最短路徑
    D[v0] = 0;
    for(int v=1;v<n;++v)
    {
        Min = 10000;
        //尋找最小值
        for(int w=0;w<n;++w)
        {
            if(!S[w] && D[w]<Min)
            {
                k = w;
                Min = D[w];
            }
        }
        S[k] = true;
        Path[v] = k;
        p = G.vertices[k].firstarc;
        while(p != NULL)
        {
            if(!S[p->adjvex] && D[k]+p->info<D[p->adjvex])
                D[p->adjvex] = D[k]+p->info;
            p = p->nextarc;
        }
    }
    for(int i=1;i<n;i++)
    {
        cout << "終點集爲:";
        for(int j=0;j<=i;j++)
            cout << G.vertices[Path[j]].data;
        cout << setw(15) << "最短路徑值爲:" << D[Path[i]] << endl;
    }
}



5.實驗總結

(1)鄰接矩陣法適合建立稠密圖;鄰接表法適合建立稀疏圖。
(2)深度優先搜索遍歷類似於樹的先序遍歷,藉助於棧結構來實現遞歸;廣度優先搜索遍歷類似於樹的層次遍歷,藉助於隊列結構來實現。
(3)Dijkstra算法求最短路徑求解過程是,按照路徑長度遞增的次序產生最短路徑,時間複雜度是O(n^2)。

數據結構核心原理與算法應用

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