1. 程式人生 > >資料結構之圖的兩種儲存方式

資料結構之圖的兩種儲存方式

第一種:鄰接矩陣
鄰接矩陣可以表示頂點之間的相鄰關係的矩陣,是一個n階方陣,可以用一個一維陣列來表示頂點資訊,用一個二維陣列來表示頂點之間的邊的聯絡以及權重
具體的程式碼如下:

#include <stdio.h>
#include <conio.h>

// 建立鄰接矩陣
void createAdjacentMatrix(AdjacentMatrix *graph) {
    int i, j, k, iWeight = 0;
    // 邊的開頭和結尾頂點
    char cEdgeStart, cEdgeEnd;
    printf("輸入各個頂點的資訊:\n"
); for (i = 0; i < graph->iVertexNum; i++) { // 輸入頂點 printf("第%d個頂點:", i + 1); fflush(stdin); // 將輸入的資訊儲存到頂點陣列中 scanf("%c", &(graph->Vertex[i])); } printf("請輸入構成每個邊的兩個頂點和權值(用逗號隔開):\n"); for (j = 0; j < graph->iEdgeNum; ++j) { // 輸入邊的資訊
printf("第%d條邊:", j + 1); fflush(stdin); scanf("%c,%c,%d", &cEdgeStart, &cEdgeEnd, &iWeight); // 在已有的頂點中查詢開始點 for (i = 0; cEdgeStart != graph->Vertex[i]; ++i); // 在已有頂點中查詢終點 for (k = 0; cEdgeEnd != graph->Vertex[k]; ++k); // 在邊的對應位置儲存權重
graph->Edges[i][k] = iWeight; // 如果是無向圖,則相反的位置也要儲存 if (graph->iGraphType == 0) graph->Edges[k][i] = iWeight; } } // 輸出鄰接矩陣 void showAdjacentMatrix(AdjacentMatrix *graph) { // 頂點資訊 for (int i = 0; i < graph->iVertexNum; ++i) { printf("\t%c", graph->Vertex[i]); } printf("\n"); for (int i = 0; i < graph->iVertexNum; ++i) { printf("%c", graph->Vertex[i]); for (int j = 0; j < graph->iVertexNum; ++j) { // 權值為最大值 if (graph->Edges[i][j] == MAX_VALUE) printf("\t∞"); else printf("\t%d", graph->Edges[i][j]); } printf("\n"); } } int main() { AdjacentMatrix G; //定義儲存鄰接矩陣結構的圖 int i, j; printf("輸入生成圖的型別(0:無向圖,1:有向圖):"); scanf("%d", &G.iGraphType); //圖的種類 printf("輸入圖的頂點數量和邊數量:"); scanf("%d,%d", &G.iVertexNum, &G.iEdgeNum); //輸入圖頂點數和邊數 for (i = 0; i < G.iVertexNum; i++) //清空矩陣 for (j = 0; j < G.iVertexNum; j++) G.Edges[i][j] = MAX_VALUE; //設定矩陣中各元素的值為最大值 createAdjacentMatrix(&G); //建立用鄰接表儲存的圖 printf("鄰接矩陣資料如下:\n"); showAdjacentMatrix(&G); getch(); return 0; }

執行結果
這裡寫圖片描述
這裡寫圖片描述

優點:簡單,易於實現
缺點:除了完全圖以外,鄰接矩陣會有很多的零元素,所以當n特別大時,鄰接矩陣會非常的稀疏,浪費大量的儲存空間

第二種:鄰接表
有鄰接矩陣改造而來,只考慮非零元素,每一行都有一個線性連結表,表頭對應著該行的頂點,連結串列中的每一個節點對應著鄰接矩陣的一個非零元素
實現程式碼如下:

#include <stdio.h>
#include <malloc.h>
#include <conio.h>

#define VERTEX_MAX 20   //圖的最大頂點數
typedef struct edgeNode {
    int iVertex; //頂點資訊(序號或字母) 
    int iWeight; //權值
    struct edgeNode *next; //指向下一個頂點指標 (當前頂點和指向的下一頂點構成一條邊) 
} EdgeNode; //鄰接表邊結構 

typedef struct {
    EdgeNode *AdjList[VERTEX_MAX]; //指向每個頂點的指標
    int iVertexNum, iEdgeNum; //圖的頂點的數量和邊的數量  
    int iGraphType; //圖的型別(0:無向圖,1:有向圖)
} ListGraph;  //圖的結構

void createAdjacentList(ListGraph *graph); //生成圖的鄰接表   
void showAdjacentList(ListGraph *graph); //輸出鄰接表

void createAdjacentList(ListGraph *graph)  //構造鄰接表結構圖
{
    int i, iWeight;
    int start, end;
    EdgeNode *edgeNode;
    for (i = 1; i <= graph->iVertexNum; i++)//將圖中各頂點指標清空 
        graph->AdjList[i] = NULL;
    printf("請輸入構成每個邊的兩個頂點和權值(用逗號隔開):\n");
    for (i = 1; i <= graph->iEdgeNum; i++) //輸入各邊的兩個頂點 
    {
        getchar();
        printf("第%d條邊:", i);
        scanf("%d,%d,%d", &start, &end, &iWeight); //輸入邊的起點和終點
        edgeNode = (EdgeNode *) malloc(sizeof(EdgeNode)); //申請儲存一個頂點的記憶體 
        edgeNode->next = graph->AdjList[start]; //插入到鄰接表中 
        edgeNode->iVertex = end; //儲存終點編號
        edgeNode->iWeight = iWeight; //儲存權值 
        graph->AdjList[start] = edgeNode; //鄰接表對應頂點指向該點 
        if (graph->iGraphType == 0) //若是無向圖,再插入到終點的邊鏈中
        {
            edgeNode = (EdgeNode *) malloc(sizeof(EdgeNode)); //申請儲存一個頂點的記憶體 
            edgeNode->next = graph->AdjList[end];
            edgeNode->iVertex = start;
            edgeNode->iWeight = iWeight;
            graph->AdjList[end] = edgeNode;
        }
    }
}

void showAdjacentList(ListGraph *graph) {
    int i;
    EdgeNode *edgeNode;
    for (i = 1; i <= graph->iVertexNum; i++) {
        printf("頂點%d", i);
        edgeNode = graph->AdjList[i];
        while (edgeNode) {
            printf("->%d(%d)", edgeNode->iVertex, edgeNode->iWeight);
            edgeNode = edgeNode->next;
        }
        printf("\n");
    }
}


int main() {
    ListGraph graph; //定義儲存鄰接表結構的圖
    printf("輸入生成圖的型別(0:無向圖,1:有向圖):");
    scanf("%d", &graph.iGraphType); //圖的種類
    printf("輸入圖的頂點數量和邊數量:");
    scanf("%d,%d", &graph.iVertexNum, &graph.iEdgeNum); //輸入圖頂點數和邊數
    printf("輸入構成各邊的兩個頂點及權值(用逗號分隔):\n");
    createAdjacentList(&graph); //生成鄰接表結構的圖
    printf("輸出圖的鄰接表:\n");
    showAdjacentList(&graph);
    getch();
    return 0;
}

執行結果
這裡寫圖片描述