天天看點

圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)

一、鄰接矩陣

圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)

有向圖的鄰接矩陣:

圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)

無向圖的鄰接矩陣:

圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)

網的鄰接矩陣:

圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)
圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)
#include <iostream>
using namespace std;

#define INFINITY  65535 /* 表示權值的無窮*/
typedef int EdgeType;//邊上的權值類型
typedef char VertexType;//頂點類型
const int MaxSize=100;//圖中最多頂點個數
class MGraph
{
    public:
        MGraph(){vertexNum=0;edgeNum=0;}
        MGraph(VertexType a[],int n);//構造函數,初始化具有n個頂點的零圖
        void InsertEdge(int i,int j);//插入頂點為i和j的一條邊
        int W(int i,int j);//取得邊(i,j)上的值(對賦權圖)
        VertexType vex(int i);//傳回頂點i的資訊
        void CreateMGraph(MGraph *Gp);//建立無向網圖的鄰接矩陣
    public:
        int vertexNum,edgeNum;//頂點數和邊數
        EdgeType adj[MaxSize][MaxSize];//鄰接矩陣
        VertexType vertex[MaxSize];//頂點表
};
//構造函數,初始化具有n個頂點的零圖
MGraph::MGraph(VertexType a[],int n)
{
    vertexNum=n;edgeNum=0;
    for(int i=0;i<n;i++) vertex[i]=a[i];
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            adj[i][j]=0;
}
//插入頂點為i和j的一條邊
void MGraph::InsertEdge(int i,int j)
{
    if(i<0||i>=vertexNum||j<0||j>=vertexNum)
        throw "位置出錯";
    adj[i][j]=1;//頂點i到頂點j的邊存在
    edgeNum++;//邊數目加1
}
//取得邊(i,j)上的值(對賦權圖)
int MGraph::W(int i,int j)
{//對非賦權圖,則取得鄰接矩陣上的鄰接資訊,1表示鄰接,0表示不鄰接
    if(i<0||i>=vertexNum||j<0||j>=vertexNum)
        throw "位置出錯";
    return adj[i][j];
}
//傳回頂點i的資訊
VertexType MGraph::vex(int i)
{
    if(i>=0&&i<vertexNum)
        return vertex[i];//傳回頂點i
    else throw "位置出錯";
}
/* 建立無向網圖的鄰接矩陣表示 */
void MGraph::CreateMGraph(MGraph *Gp)
{
    int i, j, k, w;
    cout << "請輸入頂點數和邊數(空格分隔):" << endl;
    cin >> Gp->vertexNum >> Gp->edgeNum;
    cout << "請輸入頂點資訊(空格分隔):" << endl;
    for (i = 0; i < Gp->vertexNum; i++)
        cin >> Gp->vertex[i];
    for (i = 0; i < Gp->vertexNum; i++)
    {
        for (j = 0; j < Gp->vertexNum; j++)
        {
            if (i == j)
                Gp->adj[i][j] = 0;/* 頂點沒有到自己的邊*/
            else
                Gp->adj[i][j] = INFINITY;/* 鄰接矩陣初始化 */
        }
    }
    for (k = 0; k < Gp->edgeNum; k++)
    {
        cout << "請輸入邊(vi, vj)的上标i,下标j和權值w(空格分隔):" << endl;
        cin >> i >> j >> w;
        Gp->adj[i][j] = w;
        Gp->adj[j][i] = Gp->adj[i][j];/* 因為是無向圖,矩陣對稱 */
    }
}

int main()
{
    MGraph grph;
    grph.CreateMGraph(&grph);
    for(int i=0;i<grph.vertexNum;i++)
    {
        for(int j=0;j<grph.vertexNum;j++)
            {cout<<grph.adj[i][j];cout.width(7);}
        cout<<endl;
    }
    return 0;
}
           
圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)

二、邊數組

用一個包括兩個端點及其上的權值的三元組(vi,vj,wij)來表示圖中的一條邊或弧,圖的所有邊火狐構成的這種三元組的集合都稱為圖的邊集表示。

邊集數組由兩個一維數組構成:

1.) 一個存儲頂點資訊。

2.) 一個存儲邊的資訊,這個邊數組每個資料元素由一條邊的起點下标(begin)、終點下标(end)、和權(weight)組成。

圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)
圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)

邊集數組關注的是邊的集合,在邊集數組中要查找一個頂點的度需要掃描整個邊數組,效率并不高。是以它更适合對邊依次進行處理的操作,而不适合對頂點相關的操作。

三、鄰接表

1、無向圖的鄰接表

邊表結點:

         鄰接點域             鍊域

adjvex next

表頭結點:

   頂點資訊域      始結點針織域

vertex firstedge
圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)
#include <iostream>
using namespace std;
typedef char VertexType;//頂點類型
const int MaxSize=100;
//邊表結點結構
struct EdgeNode
{
    int adjvex;//鄰接點域
    EdgeNode *next;//指向下一個邊結點的指針
};
//表頭結點結構
struct VexNode
{
    int vertex;//頂點
    EdgeNode *firstedge;//邊表的頭指針
};
class ALGraph
{
    public:
        ALGraph()//無參構造函數
        {
            vertexNum=0;
            edgeNum=0;
            for(int i=0;i<MaxSize;i++)
                adjlist[i].firstedge=NULL;
        }
        ALGraph(VertexType a[],int n);//有參構造函數
    private:
        VexNode adjlist[MaxSize];//存放頂點表的數組
        int vertexNum,edgeNum;//圖的頂點數和邊數
};
//有參構造函數
ALGraph::ALGraph(VertexType a[],int n)
{
    vertexNum=n;
    edgeNum=0;
    for(int i=0;i<vertexNum;i++)
    {
        adjlist[i].vertex=a[i];
        adjlist[i].firstedge=NULL;
    }
}
           

2、有向圖的鄰接表

表結點(出弧結點):

adjvex next

adjvex存放弧頭結點的在頂點數組中的位置(一般用下标表示),next指向下一表結點的指針域。

表頭結點:

vertex firstarc

vertex存放頂點,firstarc存放指向由出弧結點構成的連結清單的開始結點的指針(頭指針)

圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)

計算一個頂點的出度時,隻需順着該頂點結點的指針域周遊一下其所指向的單連結清單,計算下該連結清單上的結點數。

//表結點結構
struct ArcNode
{
    int adjvex;//鄰接點域
    ArcNode *next;//指向下一個邊結點的指針
};
//表頭結點結構
struct VexNode
{
    int vertex;//頂點
    ArcNode *firstarc;//指向第一個結點的指針,即出弧表的頭指針
};
           

3、有向圖的逆鄰接表

圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)

四、十字連結清單 1、弧結點

tailvex headvex hlink tlink

i----->j

tailvex:存放i,表示i為該弧引出,i為弧尾; headvex:存放j,表示該弧進入j,j為弧頭; hlink:指向下一條進入頂點j的弧的弧結點; tlink:指向下一條從i引出的弧的弧結點;

struct ArcNode//弧結點結構
{
    int tailvex,headvex;
    ArcNode *hlink,*tlink;
};
           

2、頂點結點

data firstin firstout

data:存儲和頂點相關的資訊 firstin:指向以該頂點為弧頭的第一個弧結點的指針 firstout:指向以該頂點為弧尾的第一個弧結點的指針

struct VexNode
{
    int data;
    ArcNode *firstin,*firstout;
};
           
圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)
圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)

五、鄰接多重表 針對無向圖的鍊式存儲結構。 邊結點結構:

mark ivex ilink jvex jlink info

mark:标志域,标記該邊是否被搜多過,0未被通路,1已被通路 ivex,jvex:該邊依附的兩個頂點在圖中的位置 ilink:指向下一條依附于頂點ivex的邊 jlink:指向下一條依附于頂點jvex的邊 info:邊上的資訊或指向與邊相關的資訊資料的指針域

頂點結點結構:

vertex firstedge

vertex:存儲和該頂點相關的資訊 firstedge:訓示第一條依附于該頂點的邊

鄰接多重表建立方法: (1)一條邊對應建立一個邊結點 (2)由于一個邊的兩個端點的次序可随意,是以,每建立一個邊結點,都要按其中的兩個端點的序号,分别将該邊結點鍊入兩個不同的連結清單中

圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)
圖的存儲結構(鄰接矩陣、邊數組、鄰接表、十字連結清單、鄰接多重表)

繼續閱讀