1. 程式人生 > >資料結構基礎 之 圖 的 鄰接矩陣實現與鄰接表實現

資料結構基礎 之 圖 的 鄰接矩陣實現與鄰接表實現

【鄰接矩陣】

鄰接矩陣,就是一個反應邊與邊之間聯絡的二維陣列。這個二維陣列我們用matrix[numV][numV]表示,其中numV是頂點數。

對於無權圖

若頂點Vi和Vj之間有邊,則matrix[Vi][Vj]=1;否則matrix[Vi][Vj]=0。

對於有權圖

若頂點Vi和Vj之間有邊,且權值為weight,則matrix[Vi][Vj]=weight;否則matrix[Vi][Vj]=0或MAXWEIGHT(取最小權值或最大權值)。

【鄰接表】

當圖中的邊數較少時,用鄰接矩陣來實現圖結構,則會浪費很多記憶體空間。因此,考慮另一種實現圖結構的方法:鄰接表。在鄰接表中主要有兩種節點結構體:

頂點節點((vertex)表示節點資料,也可以是節點下標;以及下一節點地址(next))

邊節點((vertex)表示節點資料,也可以是節點下標;(adjvex)通俗理解就是(vertex)節點出度表;以及出度表中下一出度節點地址(next))

【原始碼示例】

  • 鄰接矩陣建圖
void Graph::createGraph()  
{  
    cout << "輸入邊數 ";  
    while (cin >> numE && numE < 0)  
        cout << "輸入有誤!,重新輸入 ";  
  
    int i, j, w;  
    if (!isWeighted)  //無權圖  
    {  
        if (!isDirected)  //無向圖  
        {  
            cout << "輸入每條邊的起點和終點:\n";  
            for (int k = 0; k < numE; k++)  
            {  
                cin >> i >> j;  
                while (!check(i, j))  
                {  
                    cout << "輸入的邊不對!重新輸入\n";  
                    cin >> i >> j;  
                }  
                matrix[i][j] = matrix[j][i] = 1;  
            }  
        }  
        else  //有向圖  
        {  
            cout << "輸入每條邊的起點和終點:\n";  
            for (int k = 0; k < numE; k++)  
            {  
                cin >> i >> j;  
                while (!check(i, j))  
                {  
                    cout << "輸入的邊不對!重新輸入\n";  
                    cin >> i >> j;  
                }  
                matrix[i][j] = 1;  
            }  
        }  
    }  
    else  //有權圖  
    {  
        if (!isDirected)   //無向圖  
        {  
            cout << "輸入每條邊的起點、終點和權值:\n";  
            for (int k = 0; k < numE; k++)  
            {  
                cin >> i >> j >> w;  
                while (!check(i, j, w))  
                {  
                    cout << "輸入的邊不對!重新輸入\n";  
                    cin >> i >> j >> w;  
                }  
                matrix[i][j] = matrix[j][i] = w;  
            }  
        }  
        else  //有向圖  
        {  
            cout << "輸入每條邊的起點、終點和權值:\n";  
            for (int k = 0; k < numE; k++)  
            {  
                cin >> i >> j >> w;  
                while (!check(i, j, w))  
                {  
                    cout << "輸入的邊不對!重新輸入\n";  
                    cin >> i >> j >> w;  
                }  
                matrix[i][j] = w;  
            }  
        }  
    }  
} 
  • 鄰接表建圖
void Graph::createGraph()  
{  
    //用一個新的變量表示邊數,numE的修改則留到insertedge()中  
    int numEdge = 0;  
    cout << "輸入邊數 ";  
    while (cin >> numEdge && numEdge < 0)  
        cout << "輸入有誤!,重新輸入 ";    
    int i, j, w;  
    if (!isWeighted)  //無權圖  
    {  
        cout << "輸入每條邊的起點和終點:\n";  
        for (int k = 0; k < numEdge; k++)  
        {  
            cin >> i >> j;  
            while (!check(i, j))  
            {  
                cout << "輸入的邊不對!重新輸入\n";  
                cin >> i >> j;  
            }  
            insertEdge(i, j);  
        }  
    }  
    else  //有權圖  
    {  
        cout << "輸入每條邊的起點、終點和權值:\n";  
        for (int k = 0; k < numEdge; k++)  
        {  
            cin >> i >> j >> w;  
            while (!check(i, j, w))  
            {  
                cout << "輸入的邊不對!重新輸入\n";  
                cin >> i >> j >> w;  
            }  
            insertEdge(i, j, w);  
        }  
    }  
}  
void Graph::insertEdge(int vertex, int adjvex, int weight)  
{  
    insertedge(vertex, adjvex, weight);  
    if (!isDirected)  //無向圖  
        insertedge(adjvex, vertex, weight);  
}  
void Graph::insertedge(int vertex, int adjvex, int weight)  
{  
    EdgeNode *p, *q, *r;
    p = q = r = NULL;  
    if (adjList[vertex].next)   //非第一個節點  
    {  
        p = adjList[vertex].next;  
        //移動p到合適位置  
        while (p && (p->adjvex < adjvex))  
        {  
            q = p;  
            p = p->next;  
        }  
        if (p && (p->adjvex == adjvex))  //修改已有邊權值  
            p->weight = weight;  
        else  
        {  
            r = new EdgeNode;  
            r->adjvex = adjvex;  
            r->weight = weight;  
            r->next = p;  
            //當加入的新節點位於表的第一個位置  
            if (adjList[vertex].next == p)  
                adjList[vertex].next = r;  
            else  
                q->next = r;  
            numE++;  
        }  
    }  
    else  
    {  
        p = new EdgeNode;  
        p->adjvex = adjvex;  
        p->weight = weight;  
        p->next = NULL;  
        adjList[vertex].next = p;  
        numE++;  
    }  
}  

【詳細原始碼詳址】

http://blog.csdn.net/zhangxiangdavaid/article/details/38321327

http://blog.csdn.net/zhangxiangdavaid/article/details/38323593

【最後的話】

很明顯的發現,鄰接矩陣和鄰接表一個是以矩陣陣列的形式記錄了圖中邊的關係,一個是以連結串列陣列的形式記錄邊的關係。無它,連結串列肯定比資料更節省空間,但是,查詢運算元組往往比連結串列更快捷。如果,還有興趣可以用STL的 list 實現,這樣將盡收二者之長,鑑於實現非常簡單,此處程式碼就不再給出。

【注】

list,vector是push_back,queue和stack是push 。