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