有關鄰接表的含義已經在之前博文中說過了(圖論基礎)
本章將使用鄰接表創建graph,給出代碼實現。
爲了更容易看清楚代碼的實現,我這裏將圖論基礎中的圖直接複製過來。
鄰接表示意圖
代碼實現
/*
* @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);
}