圖的鄰接表(adjacency list)存儲

圖的鄰接表存儲是一種鏈式存儲與順序存儲相結合的存儲結構。鄰接表存儲法既能保留鄰接矩陣存儲法的優點,又能很好地解決矩陣存儲的缺點。這是因爲,這種結構爲圖中的每一個頂點創建一個鏈表,鏈表中的結點爲這個頂點的鄰接點,這個結點稱作表結點或者邊結點。同時爲每一個頂點的鏈表設置一個頭結點,爲了實現隨機訪問,通常將這些頭結點以順序結構的形式存儲。鄰接表存儲在矩陣存儲的基礎上實現了存儲空間的有效利用。

參考:https://book.itheima.net/course/223/1276707762369208322/1276709410189615108

#include <stdio.h>
#include <stdlib.h>

// C語言實現
// 鄰接表(adjacency list)存儲法相關結構定義

//圖的頂點的個數
#define MAX_VERTEX_NUM 100

//邊結構
typedef struct EdgeNode
{
    int adjvex;             //鄰接點域,存儲該頂點對應編號
    int weight;                //info數據域,存儲權值,非網圖可省略
    struct EdgeNode* next;    //nextarc指針域,指向下一個鄰接點
}EdgeNode; //表結點

// 鄰接表頂點的鏈表
typedef struct VertexNode
{
    int data;                //頂點域,存儲頂點信息
    EdgeNode* firstedge;    //指針域,指向頂點鏈表
}VertexNode,AdjList[MAX_VERTEX_NUM];    //頭結點

// 圖的鄰接表結構
typedef struct
{
    AdjList adjList;
    int n;                //圖中頂點的數目
    int e;                //圖中邊的數目
}GraphAdjList;            //鄰接表存儲結構定義

// 創建有向圖的鄰接表
void CreateDirectAdjacencyList(GraphAdjList* G)
{
    int i, j, k, w;
    EdgeNode *e;
    printf("請輸入有向圖的頂點與邊的數:");    
    scanf("%d,%d", &G->n, &G->e);                    //輸入頂點與邊的數目

    //初始化鄰接表頭結點
    for (i = 0; i < G->n; ++i)
    {
        scanf("%d", &G->adjList[i].data);            //輸入頂點信息
        G->adjList[i].firstedge = NULL;                //將頂點鏈表的邊置爲空
    }
    
    //給鄰接表結每個頂點(鏈表)添加相應的出邊
    for (k = 0; k < G->e; ++k)                        //建立出邊表
    {    
        printf("輸入有向圖邊和權重值:eg:\nedge1,edge2,weight\n");        
        scanf("%d,%d,%d", &i, &j, &w);                 //輸入邊
        e = (EdgeNode *)malloc(sizeof(EdgeNode));    //爲表結點開闢空間
        if(!e)
        {    
            printf("[%s@%d]alloc EdgeNode failed!\n", __FILE__, __LINE__);
            exit(-1);
        }
        
        //表結點i的鄰結點j賦值,並將i->j的邊加入到節點i的鏈表頭中
        //表結點賦值
        e->adjvex = j;                                //鄰接點序號
        e->weight = w;                                //i->j 出邊的權值
        e->next = G->adjList[i].firstedge;            //頭插法插入結點j
        G->adjList[i].firstedge = e;
    }
}

//創建無向圖的鄰接表
void CreateUndirectAdjacencyList(GraphAdjList* G)
{
    int i, j, k, w;
    EdgeNode *e;
    printf("請輸入無向圖的頂點與邊的數:");
    scanf("%d,%d", &G->n, &G->e);                    //輸入頂點與邊的數目

    //初始化鄰接表頭結點
    for (i = 0; i < G->n; ++i)
    {
        scanf("%d",&G->adjList[i].data);            //輸入頂點信息
        G->adjList[i].firstedge = NULL;                //將頂點鏈表置爲空
    }
    
    //給鄰接表結每個頂點(鏈表)添加相應的邊    
    for (k = 0; k < G->e; ++k)                        //建立邊表
    {    
        printf("輸入無向圖的邊和權重值:eg:\nedge1,edge2,weight\n");
        scanf("%d,%d,%d", &i, &j, &w);              //輸入邊和權值
        
        e = (EdgeNode *)malloc(sizeof(EdgeNode));    //爲表結點的邊開闢空間
        if(!e)
        {
            printf("[%s@%d]alloc EdgeNode failed!\n", __FILE__, __LINE__);
            exit(-1);
        }
        
        //表結點i的鄰結點j賦值,並將i->j的邊加入到節點i的鏈表頭中
        e->adjvex = j;                                //鄰接點序號
        e->weight = w;                                //i->j 邊的權值
        e->next = G->adjList[i].firstedge;            //頭插法插入結點j
        G->adjList[i].firstedge = e;
        
        //頭插法插入結點i
        e = (EdgeNode *)malloc(sizeof(EdgeNode));    //爲表結點的邊開闢空間
        if(!e)
        {
            printf("[%s@%d]alloc EdgeNode failed!\n", __FILE__, __LINE__);
            exit(-1);
        }

        //表結點j的鄰結點i賦值,並將j->i的邊加入到節點j的鏈表頭中
        e->adjvex = i;
        e->weight = w;                                //j->i 邊的權值,無向圖中與i->j的邊的權值相等
        e->next = G->adjList[j].firstedge;
        G->adjList[j].firstedge = e;
    }
}

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