以鄰接表作為儲存結構的圖的深度優先遍曆和廣度優先遍曆(c++版)

來源:互聯網
上載者:User

標籤:沒有   number   int   快速   protected   ring   code   鏈表   訪問   

一、圖的儲存

用鄰接表法儲存圖,儲存結構分為兩部分,一部分為儲存圖的所有頂點的數組,另一部分為掛載在數組的每個元素後面的用來表示頂點的鄰接點的鏈表。

1、儲存頂點的結構單元為:

class vnode{public:    string nodename;    bool visted;//進行圖的遍曆時用於標記圖是否被訪問過    node *next;    vnode()    {        visted = false;        next = NULL;    }};

鏈表的結構單元為:

class node{public:    string nodename;    int nodeindex;//節點的索引,用於快速定位節點在頂點數組中的位置    int weight;//權值,用於儲存頂點之間的資訊    node *next;    node() { next = NULL; }};

2、現在聲明Graph這個類,類的聲明為(有關圖的遍曆的成員函數也以包含進來):

class Graph{public:    Graph();                    ~Graph();    bool DeepFirstSearch(int nodeindex);    void ClearVisited();    bool WideFirstSearch(int nodeindex);protected:    vnode *pvnode;    int vnumber;};

 

3、下面是Graph類的成員函數的定義為(先實現關於圖的儲存的成員函數):

Graph::Graph(){    cout << "請輸入節點的個數:";    cin >> vnumber;    pvnode = new vnode[vnumber];        //通過new建立頂點數組    for (int i = 0; i < vnumber; i++)   //通過for迴圈將圖的資訊輸入    {        cout << endl;        cout << "請輸入節點:";        cin >> pvnode[i].nodename;        string check;                   //輸入某個頂點的鄰接點時,以"#"作為輸入的結束標誌        while (1)        {            cout << "請輸入節點的相鄰節點:";            cin >> check;            if (check == "#") { break; }//如果輸入的"#"就跳出輸入迴圈            node *temp = new node;      //如果不是,就分配節點記憶體,完善相關資訊            temp->nodename = check;            cout << "請輸入相鄰節點的序號和權值:";            cin >> temp->nodeindex >> temp->weight;            temp->next = pvnode[i].next;  //並將新輸入的節點放到相應的鏈表中            pvnode[i].next = temp;        }    }}Graph::~Graph()                         //釋放記憶體時,先釋放鏈表佔用的記憶體,然後釋放數組佔用的記憶體{    node*currentnode = NULL;             //釋放鏈表佔用的記憶體    node*temp = NULL;    for (int i = 0; i < vnumber; i++)    {        currentnode = pvnode[i].next;        while (currentnode != NULL)        {            temp = currentnode->next;    //儲存當前節點的下一個節點的記憶體            delete currentnode;          //釋放當前節點的記憶體            currentnode = temp;          //下一個節點作為當前的節點        }    }    delete[]pvnode;                      //釋放數組佔用的記憶體}

二、圖的遍曆

1、深度優先遍曆

深度優先遍曆通過遞迴的演算法實現

下面是實現圖的深度優先遍曆的成員函數的實現:

bool Graph::DeepFirstSearch(int nodeindex){    if (nodeindex < 0 || nodeindex >= vnumber)            //判斷指定的起始節點是否合法    {        cout << "The nodeindex does not exist..";        return false;    }    if (pvnode[nodeindex].visted == false)                //判斷當前節點是否被訪問過,如果沒有,則繼續    {        cout << pvnode[nodeindex].nodename << " ";        //輸出節點的名字        pvnode[nodeindex].visted = true;                  //修改訪問記錄        node *currentnode=pvnode[nodeindex].next;         //找到當前節點相鄰的一個節點        while (currentnode != NULL)        {            DeepFirstSearch(currentnode->nodeindex);      //通過遞迴繼續上述操作            currentnode = currentnode->next;              //換當前節點的另一個相鄰節點試試        }    }    return true;}

 2、廣度優先遍曆

廣度優先遍曆需要藉助隊列這種資料結構。

代碼實現:

bool Graph::WideFirstSearch(int nodeindex){    if (nodeindex < 0 || nodeindex >= vnumber)          //判斷輸入的節點索引是否合法    {        cout << "The nodeindex does not exist..";        return false;    }    Queue<int> queue(vnumber);    cout << "廣度優先搜尋的遍曆結果為:";    cout << pvnode[nodeindex].nodename << " ";          //將起始節點的名字列印出來    pvnode[nodeindex].visted = true;                    //更改起始節點的訪問記錄    queue.EnQueue(nodeindex);                           //起始節點入隊列    int temp=0;                        node *currentnode = NULL;    while (queue.QueueEmpty() == false)                 //對於每一個入隊的節點,    {        queue.DeQueue(temp);        currentnode = pvnode[temp].next;                //按入隊順序訪問其相鄰的全部節點        while (currentnode!= NULL)        {            if (pvnode[currentnode->nodeindex].visted == false)            {                cout << currentnode->nodename << " ";                pvnode[currentnode->nodeindex].visted = true;     //已經訪問過的節點更改訪問記錄併入隊                queue.EnQueue(currentnode->nodeindex);                        }            currentnode = currentnode->next;        }    }    cout << endl;    return true;}

3、由於這兩種演算法都需要對節點的訪問記錄進行修改,所以每次用這兩種的某一種演算法實現遍曆後需要初始化訪問記錄才能繼續使用。

初始化訪問記錄的函數代碼實現為:

void Graph::ClearVisited(){    for (int i = 0; i < vnumber; i++)    {        pvnode[i].visted = false;    }}


註:完整的代碼在下面賦上,另附上實現隊列的完整代碼

http://files.cnblogs.com/files/Rcchio/Graph.rar

以鄰接表作為儲存結構的圖的深度優先遍曆和廣度優先遍曆(c++版)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.