資料結構之圖的兩種儲存方式
阿新 • • 發佈:2019-01-22
第一種:鄰接矩陣
鄰接矩陣可以表示頂點之間的相鄰關係的矩陣,是一個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;
}
執行結果