數據結構與算法--圖的存儲方式

1. 圖的定義

  • 定義:圖是由頂點的有窮非空結合和頂點之間的集合組成,數據元素(頂點)之間具有任意關係,圖中任意兩個數據元素之間都可能相關

  • 各種圖:

無向圖(頂點到頂點之間的邊沒有方向,則稱這條邊爲無向邊)

有向圖(若從頂點 到頂點 的邊有方向,則稱這條邊爲有向邊,也稱爲弧)

頂點A頂點D的邊就是弧,用<A, D>表示弧,注意不能寫成<D, A>
上圖可以表示爲G= (V2,{E2}),其中頂點集合V2={A,E,C,D}, 弧集合E2={<A,D>,<A,E>,<A,C>,<E,D>}

無向完全圖

有向完全圖

有些圖的邊具有與它相關的數字,這種與圖的邊或弧相關的數叫做。這些權可以表示從一個頂點到另一個頂點的距離或耗費。

這種帶權的圖通常稱爲。如下圖就是一張帶權的圖,即標識中國四大城市的直線距離的網,此圖中的權就是兩地的距離。

廣度優先搜索算法:數據結構是隊列。通過將頂點存入隊列中,最先入隊列的頂點先被探索。

深度優先搜索算法:數據結構是棧。通過將頂點存入棧中,沿着路徑探索頂點,存在新的相鄰頂點就去訪問

2. 圖的存儲

2.1. 圖的存儲介紹

圖用 鄰接矩陣存儲方式 來存儲

  1. 一個一維數組存儲圖中頂點信息

  2. 一個二維數組(稱爲鄰接矩陣)存儲圖中的邊或弧的信息。

圖Gn個頂點,則鄰接矩陣是一個nxn的方陣,定義爲:

如下無向圖:

如下有向圖

我們知道,每條邊上帶有權值叫做,那麼在存儲的時候,可以採用權值代替矩陣中的0、1,權值不存在的元素之間用表示,如下圖,左圖是一個有向網圖,右圖就是它的鄰接矩陣。

2.2. 鄰接矩陣

定義一個數組,存儲頂點,定義一個鄰接矩陣(二維數組)

#define OK    1
#define ERROR 0
#define TRUE  1
#define FALSE 0
#define MAXVEX 100 // 最大頂點數
#define INFINITYC 0

typedef int  Status;
typedef char VertexType;  // 頂點類型
typedef int  EdgeType;    // 邊的權值的類型

// 定義圖的結構
typedef struct {
    VertexType vers[MAXVEX];       // 頂點表
    EdgeType   arc[MAXVEX][MAXVEX];// 鄰接矩陣
    int        numNodes;           // 頂點數
    int        numEdges;           // 邊數
}MGraph;

圖的存儲方法:

void CreateMGraph(MGraph *G){
    int i, j, k, m;
    // 1.輸入頂點數
    printf("輸入頂點數:");
    scanf("%d", &G->numNodes);
    // 2.輸入邊數
    printf("輸入邊數:");
    scanf("%d", &G->numEdges);
    
    printf("頂點數:%d,邊數:%d\n",G->numNodes,G->numEdges);
    
    // 3.輸入頂點表
    printf("輸入頂點:");
    for (i = 0; i <= G->numNodes; i++) {
        scanf("%c", &G->vers[i]);
    }
    // 4.初始化鄰接矩陣
    for (i = 0; i < G->numNodes; i++) {
        for (j = 0; j < G->numNodes; j++) {
            G->arc[i][j] = INFINITY;
        }
    }
    // 5.輸入邊信息
    for (k = 0; k < G->numEdges; k++) {
        printf("輸入邊(vi,vj)上的下標i,下標j,權w(逗號分隔)\n");
        scanf("%d,%d,%d", &i, &j, &m);
        
        G->arc[i][j] = m;
        //如果無向圖,矩陣對稱;
        //G->arc[j][i] = G->arc[i][j];
        
    }
    
    // 6.打印
    for (int i = 0; i < G->numNodes; i++) {
        printf("\n");
        for (int j = 0; j < G->numNodes; j++) {
            printf("%d ",G->arc[i][j]);
        }
    }
    printf("\n");
}

2.3. 鄰接表

#define M 100    //頂點最大個數
#define TRUE 1
#define FALSE 0

typedef char Element;

// 定義鄰接表節點
typedef struct Node {
    int      adj_vex_index;    // 弧頭下標
    Element  data;             // 權重
    struct Node *next;         // 邊指針
}EdgeNode;

// 定義頂點表結構
typedef struct vNode {
    Element     data;        // 權重
    EdgeNode    * firstedge; // 頂點的下一個
}VertexNode,Adjlist[M];

// 定義圖結構
typedef struct Graph{
    Adjlist adjlist;      // 頂點表
    int     arc_num;      // 邊數
    int     node_num;     // 頂點數
    int    is_directed;  // 是否是有向圖
}Graph, *GraphLink;

圖的存儲(鄰接表)

void creatGraph(GraphLink *g){
    
    int i, j, k;
    EdgeNode *p;
    
    // 輸入邊數,頂點數,是否有向
    printf("輸入頂點數目,邊數和有向?:\n");
    scanf("%d %d %d", &(*g)->node_num, &(*g)->arc_num, &(*g)->is_directed);
    
    // 輸入頂點信息
    for (i = 0; i < (*g)->node_num; i++) {
        getchar();
        scanf("%c", &(*g)->adjlist[i].data);
        (*g)->adjlist[i].firstedge = NULL;
    }
    printf("輸入邊信息:\n");
    for (k = 0; k < (*g)->arc_num; k++) {
        getchar();
        scanf("%d %d", &i, &j);
        
        // 創建新節點
        p = (EdgeNode *)malloc(sizeof(EdgeNode));
        // 弧頭的下標
        p->adj_vex_index = j;
        // 頭插法
        p->next = (*g)->adjlist[i].firstedge;
        // 將頂點數組[i].firstedge 設置爲p
        (*g)->adjlist[i].firstedge = p;
        
        // 判斷是否是有向
        if (!(*g)->is_directed) {
            // 創建新節點
            p = (EdgeNode *)malloc(sizeof(EdgeNode));
            // 弧頭的下標
            p->adj_vex_index = i;
            // 頭插法
            p->next = (*g)->adjlist[j].firstedge;
            // 將頂點數組[i].firstedge 設置爲p
            (*g)->adjlist[j].firstedge = p;
        }
    }
}

void putGraph(GraphLink g){
    int i;
    printf("鄰接表中存儲信息:\n");
    //遍歷一遍頂點座標,每個再進去走一次
    for (i = 0; i < g->node_num; i++) {
        EdgeNode * p = g->adjlist[i].firstedge;
        while (p) {
            printf("%c->%c ", g->adjlist[i].data, g->adjlist[p->adj_vex_index].data);
            p = p->next;
        }
        printf("\n");
    }
}

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