【DSA】圖-鄰接表實現圖(3)

有關鄰接表的含義已經在之前博文中說過了(圖論基礎
本章將使用鄰接表創建graph,給出代碼實現。
爲了更容易看清楚代碼的實現,我這裏將圖論基礎中的圖直接複製過來。

鄰接表示意圖

在這裏插入圖片描述
在這裏插入圖片描述

代碼實現

所有數據結構算法的代碼見github,本文代碼地址

/*
* @Author: jobbofhe
* @Date:   2019-11-01 16:44:27
* @Last Modified by:   Administrator
* @Last Modified time: 2019-11-05 09:45:09
*/

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

#define  IS_LETTER(c)   ( (((c) >= 'a') && ((c) <= 'z')) || (((c) >= 'A') && ((c) <= 'Z')) )
#define  LENGTH(c)      (sizeof(c)/(sizeof(c[0])))

#define MAX_VERTEX (200)

// 鄰接錶鏈表中的節點
typedef struct Node_
{
    int index_vex;
    struct Node_ *next_edge;

}Node, *pNode;

// graph 頂點信息
typedef struct VertexNode_
{
    char data;
    Node *first_edge;

}VertexNode;

// 鄰接表結構體
typedef struct ListListGraph_
{
    int vertex_number;
    int edge_number;
    VertexNode vertex[MAX_VERTEX];

}ListGraph;

int get_position(ListGraph list_graph, char ch)
{
    for (int i = 0; i < list_graph.vertex_number; ++i)
    {
        if (list_graph.vertex[i].data == ch)
        {
            return i;
        }
    }

    return -1;
}

void append_tail(Node *list, Node *node)
{
    Node *p = list;

    while(p->next_edge) 
    {
        p = p->next_edge;
    }
    p->next_edge = node;
}

/*
 * 創建圖(用已提供的矩陣)
 */
ListGraph* create_graph(char *vertex, char edges[][2], int vlen, int elen)
{
    int i, p1, p2;
    Node *node1, *node2;
    ListGraph* pG;
    
    if ((pG=(ListGraph*)malloc(sizeof(ListGraph))) == NULL )
    {
        return NULL;
    }
    memset(pG, 0, sizeof(ListGraph));

    // 初始化"頂點數"和"邊數"
    pG->vertex_number = vlen;
    pG->edge_number = elen;
    printf("頂點數量: %d  邊數 :%d\n", vlen, elen);
    // 初始化"頂點"
    for (i = 0; i < pG->vertex_number; i++)
    {
        pG->vertex[i].data = vertex[i];
        pG->vertex[i].first_edge = NULL;
    }

    // 初始化"邊"
    for (i = 0; i < pG->edge_number; i++)
    {
        // 讀取邊的起始頂點和結束頂點
        p1 = get_position(*pG, edges[i][0]);
        p2 = get_position(*pG, edges[i][1]);

        // A-->B
        node1 = (Node *)malloc(sizeof(Node));
        node1->index_vex = p2;
        // 將node1, 插在鏈表末尾
        if (pG->vertex[p1].first_edge == NULL)
        {
            pG->vertex[p1].first_edge = node1;
        }
        else
        {
            append_tail(pG->vertex[p1].first_edge, node1);
        }

        // B-->A
        node2 = (Node *)malloc(sizeof(Node));
        node2->index_vex = p1;
        if (pG->vertex[p2].first_edge == NULL)
        {
            pG->vertex[p2].first_edge = node2;
        }
        else
        {
            append_tail(pG->vertex[p2].first_edge, node2);
        }
    }

    return pG;
}

void print_graph(ListGraph graph)
{
    printf("頂點數量: %d\n", graph.vertex_number);


    for (int i = 0; i < graph.vertex_number; ++i)
    {
        printf("[%d](%c)", i, graph.vertex[i].data);
        Node *node = graph.vertex[i].first_edge;
        while(node != NULL) 
        {
            printf("-->[%d](%c)", node->index_vex, graph.vertex[node->index_vex].data);
            node = node->next_edge;
        }

        printf("\n");
    }
}

int main(int argc, char const *argv[])
{
    char vertex[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};
    char edges[][2] = {
        {'A', 'C'}, 
        {'A', 'D'}, 
        {'A', 'F'}, 
        {'B', 'C'}, 
        {'C', 'D'}, 
        {'F', 'G'},
        {'G', 'E'},
        {'E', 'H'}}; 

    ListGraph* p_graph_2 = create_graph(vertex, edges, LENGTH(vertex), LENGTH(edges));
    print_graph(*p_graph_2);
    return 0;
}

結果驗證

在這裏插入圖片描述

推廣到有向圖

與無向圖不同的是,有向圖邊的方向是單向的。在代碼中僅需要修改一處即可。

# 修改接口
create_graph(char *vertex, char edges[][2], int vlen, int elen)

# 刪除掉其中以下行即可
 // B-->A
node2 = (Node *)malloc(sizeof(Node));
node2->index_vex = p1;
if (pG->vertex[p2].first_edge == NULL)
{
    pG->vertex[p2].first_edge = node2;
}
else
{
    append_tail(pG->vertex[p2].first_edge, node2);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章