網(wǎng)站首頁 編程語言 正文
文章目錄
- 一、圖的介紹
- 二、圖的定義和術(shù)語
- 三、圖的存儲結(jié)構(gòu):
- 鄰接矩陣:
- 鄰接矩陣的優(yōu)點:
- 鄰接矩陣的缺點:
- 鄰接表:
- 鄰接表優(yōu)點:
- 鄰接表缺點:
- 十字鏈表:
- 十字鏈表的優(yōu)點:
- 十字鏈表的缺點:
- 鄰接多重表:
一、圖的介紹
? 圖是一種比較復雜的數(shù)據(jù)結(jié)構(gòu),在線性表中數(shù)據(jù)元素之間僅有線性關(guān)系,每個元素只有一個直接前驅(qū)和直接后繼(元素之間只存在一對一關(guān)系),在樹形結(jié)構(gòu)中元素之間有著明顯的層次關(guān)系,每一層的元素只能和下層的多個元素有關(guān)系(元素之間存在一對多關(guān)系),而在圖形結(jié)構(gòu)中,任意兩個結(jié)點之間都可能有關(guān)系(元素之間存在多對多關(guān)系)。
二、圖的定義和術(shù)語
**頂點:**圖中的數(shù)據(jù)元素被稱為頂點,一般使用V表示圖的頂點的有窮非空集合。
**弧:**兩個頂點之間的關(guān)系記作<v,w>,表示能從頂點v到達頂點w,也就是v能到w,但w不一定能到v,我們稱v為弧尾或初始點,稱w為弧頭或終端點。
**有向圖:**由弧+頂點構(gòu)成的圖叫有向圖,也就是頂點之間是單行道。
**邊:**兩個頂點之間的關(guān)系記錄(v,w),表示既能從v到w,也能從w到v,我們稱v和w之間的關(guān)系是一條邊。
**無向圖:**由邊+頂構(gòu)成的圖有無向圖,頂點之間的雙行道。
**注意:**一般使用G代表圖,V頂點的集合,VR代表弧或邊的集合,n代表頂點的數(shù)目,e代表邊或弧的數(shù)目,我們不討論頂點到自己的邊或弧。
**完全圖:**在無向圖中,e的取值范圍是0 ~ n/2(n-1),如果無向圖的邊的數(shù)量達到最大值這種無向圖稱稱為完全圖。
**有向完全圖:**在有向圖中,e的取值范圍是0 ~ n(n-1),如果有向圖的弧的數(shù)量達到最大值這種有向圖稱稱為有向完全圖。
**稀疏圖和稠密圖:**如果圖中的邊和弧很少,e<nlogn 這種圖被稱為稀疏圖,反之稱為稠密圖。
**權(quán)和網(wǎng):**如果圖中的頂點到另一個頂點需要代價(距離或耗費),那么在表示邊或弧的時候需要附加數(shù)據(jù),附加的數(shù)據(jù)就叫做權(quán),帶權(quán)的圖通常被稱為網(wǎng),這也是互聯(lián)網(wǎng)的由來。
**子圖:**假定有兩個圖G1和G2,如果G1的頂點集合是G2的頂點集合的子集,且G1的邊或弧集合是G2的邊或弧集合的子集,則稱G1是G2的子圖。
**鄰接點:**在無向圖中如果有一條邊(v,w),則v,w兩個頂點互為鄰接點,即v和w相鄰接,邊(v,w)依附于頂點v,w,或者說(v,w)和頂點v、w相關(guān)聯(lián)。
**頂點v的度:**在無向圖中與頂點v相關(guān)聯(lián)的邊的數(shù)量。
**頂點v的入度和出度:**在有向圖中,以頂點v作為弧頭的弧的數(shù)量稱為頂點的入度,以頂點v作為弧尾的弧的數(shù)量稱為頂點的出度。
**路徑:**從頂點v到達頂點w所經(jīng)歷的頂點序叫做路徑,路徑的長度就是邊或弧的數(shù)目。
**回路或環(huán):**起始點和終點相同的路徑稱為回路或環(huán)。
**簡單路徑:**路徑中頂點不重復出現(xiàn)的路徑稱為簡單路徑。
**簡單回路或簡單環(huán):**起始點和終點相同且其余頂點不重復出現(xiàn),被稱為簡單回路或簡單環(huán)。
**連通圖:**在無向圖中,從頂點v到頂點w有路徑,則稱v和w是連通的,如果圖中任意兩個頂點都是連通的,則稱圖為連通圖。
**連通分量:**G1和G2都是連通圖,且G1是G2的子圖,則稱G1是G2的連通分量或極大連通子圖。
強連通圖:在有向圖中,如果任意一對頂點都雙向連通,則稱圖為強連通圖。
強連通分量:G1和G2都是強連通圖,且G1是G2的子圖,則稱G1是G2的強連通分量或極大強連通子圖。
三、圖的存儲結(jié)構(gòu):
鄰接矩陣:
? 使用兩個數(shù)組來存儲數(shù)據(jù)元素(頂點)和數(shù)據(jù)元素之間的關(guān)系(邊或弧)的信息。
? 一維數(shù)組:用于存儲頂點。
? 二維數(shù)組:用于存儲弧或邊。
鄰接矩陣的優(yōu)點:
? 訪問速度快,方便計算結(jié)點的度、入度、出度。
鄰接矩陣的缺點:
? 頂點的容量有限,擴容非常麻煩,只適合存儲稠密圖,存儲稀疏圖時會有大量的內(nèi)存浪費。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 無向圖
typedef struct Grahh
{
size_t cal; // 頂點容量
size_t cnt; // 頂點數(shù)量
char *vertex; // 存儲頂點的一維數(shù)組
char **edge; // 存儲邊的二維數(shù)組
} Graph;
Graph *create_graph(size_t cal)
{
Graph *graph = malloc(sizeof(Graph));
graph->vertex = malloc(sizeof(char) * cal);
graph->cal = cal;
graph->cnt = 0;
graph->edge = malloc(sizeof(char *) * cal);
for (int i = 0; i < cal; i++)
{
graph->edge[i] = calloc(sizeof(char), cal);
}
return graph;
}
bool add_vertex_graph(Graph *graph, char vertex)
{
if (graph->cnt >= graph->cal)
return false;
for (int i = 0; i < graph->cnt; i++)
{
if (graph->vertex[i] == vertex)
return false;
}
graph->vertex[graph->cnt++] = vertex;
return true;
}
bool add_edge_graph(Graph *graph, char v1, char v2)
{
int v1_index = -1, v2_index = -1;
for (int i = 0; i < graph->cnt; i++)
{
if (graph->vertex[i] == v1)
v1_index = i;
if (graph->vertex[i] == v2)
v2_index = i;
}
if (-1 == v1_index || -1 == v2_index || v1_index == v2_index)
return false;
graph->edge[v1_index][v2_index] = 1;
graph->edge[v2_index][v1_index] = 1;
return true;
}
// 查詢頂點在一維數(shù)組中的位置,如果不存在則返回-1
int query_vertex_graph(Graph *graph, char vertex)
{
for (int i = 0; i < graph->cnt; i++)
{
if (vertex == graph->vertex[i])
return i;
}
return -1;
}
// 查詢頂點第一個鄰接點,如果不存在則返回'\0'
char first_vertex_graph(Graph *graph, char vertex)
{
int index = query_vertex_graph(graph, vertex);
if (-1 == index)
return '\0';
for (int i = 0; i < graph->cnt; i++)
{
if (1 == graph->edge[index][i])
return graph->vertex[i];
}
return '\0';
}
// 刪除頂點
bool del_vertex_graph(Graph *graph, char vertex)
{
int index = query_vertex_graph(graph, vertex);
if (-1 == index)
return false;
for (int i = 0; i < graph->cnt; i++)
{
graph->edge[index][i] = 0;
graph->edge[i][index] = 0;
}
return true;
}
void _dfs_graph(Graph *graph, int index, bool *flags)
{
if (!flags[index])
return;
printf("%c\n", graph->vertex[index]);
flags[index] = false;
for (int i = 0; i < graph->cnt; i++)
{
if (1 == graph->edge[index][i])
_dfs_graph(graph, i, flags);
}
}
// 深度優(yōu)先遍歷,與樹的前序遍歷類似
void dfs_graph(Graph *graph)
{
bool flags[graph->cnt];
for (int i = 0; i < graph->cnt; i++)
flags[i] = true;
for (int i = 0; i < graph->cnt; i++)
_dfs_graph(graph, i, flags);
}
// 廣度優(yōu)先遍歷,與樹的層序遍歷一樣,需要隊列結(jié)構(gòu)配合
void bfs_graph(Graph *graph)
{
bool flags[graph->cnt];
for (int i = 0; i < graph->cnt; i++)
flags[i] = true;
int queue[graph->cnt], front = 0, rear = 0;
for (int i = 0; i < graph->cnt; i++)
{
if (flags[i])
{
flags[i] = false;
queue[rear++] = i;
}
while (front != rear)
{
int index = queue[front++];
printf("%c ", graph->vertex[index]);
for (int j = 0; j < graph->cnt; j++)
{
if (1 == graph->edge[index][j] && flags[j])
{
flags[j] = false;
queue[rear++] = j;
}
}
}
}
}
// 銷毀圖
void destroy_graph(Graph *graph)
{
for (int i = 0; i < graph->cnt; i++)
{
free(graph->edge[i]);
}
free(graph->edge);
free(graph->vertex);
free(graph);
}
int main(int argc, const char *argv[])
{
Graph *graph = create_graph(5);
add_vertex_graph(graph, 'A');
add_vertex_graph(graph, 'B');
add_vertex_graph(graph, 'C');
add_vertex_graph(graph, 'D');
add_vertex_graph(graph, 'E');
add_edge_graph(graph, 'A', 'C');
add_edge_graph(graph, 'A', 'D');
add_edge_graph(graph, 'C', 'B');
add_edge_graph(graph, 'B', 'D');
// del_vertex_graph(graph,'C');
printf("------------------------\n");
for (int i = 0; i < graph->cnt; i++)
{
for (int j = 0; j < graph->cnt; j++)
{
printf("%hhd ", graph->edge[i][j]);
}
printf("\n");
}
// destroy_graph(graph);
// printf("%c\n",first_vertex_graph(graph,'D'));
// dfs_graph(graph);
bfs_graph(graph);
return 0;
}
鄰接表:
? 采用一維數(shù)組加單向鏈表的方式存儲存儲。
? 一維數(shù)組:用于存儲頂點和單向鏈表的頭指針。
? 單向鏈表:存儲著從該頂點出發(fā)的弧或邊。
鄰接表優(yōu)點:
? 與鄰接矩陣相比,它可以節(jié)約內(nèi)存,有多少條邊或弧就創(chuàng)建多少個鏈表節(jié)點,比較適合存儲稀疏圖。
鄰接表缺點:
? 計算入度、刪除節(jié)點時比較麻煩。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 弧
typedef struct Bow
{
int dest;
struct Bow *next;
} Bow;
// 頂點
typedef struct Vertex
{
char data;
Bow first; // 單鏈表的空白頭節(jié)點
} Vertex;
// 有向圖
typedef struct Graph
{
Vertex *vertex;
size_t cal;
size_t cnt;
} Graph;
// 創(chuàng)建圖
Graph *create_graph(size_t cal)
{
Graph *graph = malloc(sizeof(Graph));
graph->vertex = malloc(sizeof(Vertex) * cal);
graph->cal = cal;
graph->cnt = 0;
return graph;
}
// 添加頂點
bool add_vertex_graph(Graph *graph, char vertex)
{
if (graph->cnt >= graph->cal)
return false;
// 頂點不能重復
for (int i = 0; i < graph->cnt; i++)
if (vertex == graph->vertex[i].data)
return false;
graph->vertex[graph->cnt].data = vertex;
graph->vertex[graph->cnt++].first.next = NULL;
return true;
}
// 查詢頂點
int query_vertex_graph(Graph *graph, char vertex)
{
for (int i = 0; i < graph->cnt; i++)
{
if (graph->vertex[i].data == vertex)
return i;
}
return -1;
}
// 添加弧
bool add_bow_graph(Graph *graph, char bow_tail, char bow_head)
{
int index_tail = query_vertex_graph(graph, bow_tail);
if (-1 == index_tail)
return false;
int index_head = query_vertex_graph(graph, bow_head);
if (-1 == index_head)
return false;
Bow *bow = malloc(sizeof(Bow));
bow->dest = index_head;
bow->next = graph->vertex[index_tail].first.next;
graph->vertex[index_tail].first.next = bow;
return true;
}
// 刪除頂點
bool del_vertex_graph(Graph *graph, char vertex)
{
int index = query_vertex_graph(graph, vertex);
if (-1 == index)
return false;
if (NULL != graph->vertex[index].first.next)
{
Bow *bow = graph->vertex[index].first.next;
graph->vertex[index].first.next = bow->next;
free(bow);
}
graph->vertex[index].data = '\0';
for (int i = 0; i < graph->cnt; i++)
{
for (Bow *bow = &graph->vertex[i].first; NULL != bow->next; bow = bow->next)
{
if (index == bow->next->dest)
{
Bow *tmp = bow->next;
bow->next = tmp->next;
free(tmp);
}
}
}
return true;
}
// 計算入度,計算出有多個弧的弧頭是某頂點
int indegree_vertex_graph(Graph *graph, char vertex)
{
// 打到頂點,遍歷所有弧,dest等于vertex下的弧有多少條,如果找不到則返回-1
int index = query_vertex_graph(graph, vertex);
if (-1 == index)
return -1;
int indegree = 0;
for (int i = 0; i < graph->cnt; i++)
{
Bow *bow = graph->vertex[i].first.next;
while (NULL != bow)
{
if (index == bow->dest)
indegree++;
bow = bow->next;
}
}
return indegree;
}
// 計算出度
int outdegree_vertex_graph(Graph *graph, char vertex)
{
// 找到頂點,從它出發(fā)的弧有多少條,如果找不到則返回-1
int index = query_vertex_graph(graph, vertex);
if (-1 == index)
return -1;
int outdegree = 0;
Bow *bow = graph->vertex[index].first.next;
while (NULL != bow)
{
outdegree++;
bow = bow->next;
}
return outdegree;
}
// 深度優(yōu)先遍歷
void _dfs_graph(Graph *graph, int index, bool *flags)
{
flags[index] = false;
printf("%c ", graph->vertex[index].data);
Bow *bow = graph->vertex[index].first.next;
while (NULL != bow)
{
if (flags[bow->dest])
_dfs_graph(graph, bow->dest, flags);
bow = bow->next;
}
}
void dfs_graph(Graph *graph)
{
// 參考昨天鄰接矩陣的業(yè)務邏輯
bool flags[graph->cnt];
for (int i = 0; i < graph->cnt; i++)
flags[i] = true;
for (int i = 0; i < graph->cnt; i++)
if (flags[i])
_dfs_graph(graph, i, flags);
printf("\n");
}
// 廣度優(yōu)先遍歷
void bfs_graph(Graph *graph)
{
bool flags[graph->cnt];
for (int i = 0; i < graph->cnt; i++)
flags[i] = true;
int queue[graph->cnt], front = 0, rear = 0;
for (int i = 0; i < graph->cnt; i++)
{
if (flags[i])
{
flags[i] = false;
queue[rear++] = i;
}
while (front != rear)
{
int index = queue[front++];
printf("%c ", graph->vertex[index].data);
Bow *bow = graph->vertex[index].first.next;
while (NULL != bow)
{
if (flags[bow->dest])
{
flags[bow->dest] = false;
queue[rear++] = bow->dest;
}
bow = bow->next;
}
}
}
printf("\n");
}
// 銷毀圖
void destroy_graph(Graph *graph)
{
for (int i = 0; i < graph->cnt; i++)
{
Bow *bow = &graph->vertex[i].first;
while (NULL != bow->next)
{
Bow *tmp = bow->next;
bow->next = tmp->next;
free(tmp);
}
}
free(graph->vertex);
free(graph);
}
int main(int argc, const char *argv[])
{
Graph *graph = create_graph(10);
add_vertex_graph(graph, 'A');
add_vertex_graph(graph, 'B');
add_vertex_graph(graph, 'C');
add_vertex_graph(graph, 'D');
add_vertex_graph(graph, 'E');
add_bow_graph(graph, 'A', 'D');
add_bow_graph(graph, 'A', 'E');
add_bow_graph(graph, 'A', 'C');
add_bow_graph(graph, 'C', 'B');
add_bow_graph(graph, 'B', 'D');
// add_bow_graph(graph,'E','D');
/*
del_vertex_graph(graph,'E');
for(int i=0; i<graph->cnt; i++)
{
printf("%d %c first->%p",i,graph->vertex[i].data,graph->vertex[i].first.next);
for(Bow* bow=graph->vertex[i].first.next; NULL!=bow; bow=bow->next)
{
printf(" %p dest:%d ",bow,bow->dest);
}
printf("\n");
}
printf("%d\n",outdegree_vertex_graph(graph,'B'));
printf("%d\n",indegree_vertex_graph(graph,'A'));
*/
dfs_graph(graph);
bfs_graph(graph);
destroy_graph(graph);
return 0;
}
十字鏈表:
? 采用一維數(shù)組加兩個十字鏈表進行存儲,之所以叫十字鏈表,是因為它的鏈表弧節(jié)點會被兩個鏈表指向,同時弧節(jié)點有兩個指針,指向后續(xù)的弧節(jié)點。
? 一維數(shù)組:存儲了頂點數(shù)據(jù),兩個鏈表頭指針。
? 出度鏈表:指向的是以該結(jié)點作為弧尾的弧節(jié)點。
? 入度鏈表:指向的是以該結(jié)點作為弧頭的弧節(jié)點。
十字鏈表的優(yōu)點:
? 與鄰接矩陣相比,它更節(jié)約內(nèi)存,與鄰接表相比它更方便計算頂點的出度。
十字鏈表的缺點:
? 刪除頂點和刪除弧時比較麻煩,也可以表示與實現(xiàn)無向圖,但更合適表示與實現(xiàn)有向圖。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 弧
typedef struct Bow
{
int tailvex; // 弧尾的頂點下標
int headvex; // 弧頭的頂點下標
struct Bow *tlink; // 指向相同弧尾的弧節(jié)點
struct Bow *hlink; // 指向相同弧頭的弧節(jié)點
} Bow;
// 頂點
typedef struct Vertex
{
char data;
Bow *inlink;
Bow *outlink;
} Vertex;
// 圖
typedef struct Graph
{
Vertex *vertex;
size_t cal;
size_t cnt;
} Graph;
// 創(chuàng)建圖
Graph *create_graph(size_t cal)
{
Graph *graph = malloc(sizeof(Graph));
graph->vertex = malloc(sizeof(Vertex) * cal);
graph->cal = cal;
graph->cnt = 0;
return graph;
}
// 查詢頂點下標
int query_vertex_graph(Graph *graph, char vertex)
{
for (int i = 0; i < graph->cnt; i++)
if (vertex == graph->vertex[i].data)
return i;
return -1;
}
// 添加頂點
bool add_vertex_graph(Graph *graph, char vertex)
{
// 如果頂點已經(jīng)滿,或頂點已經(jīng)存在則返回false
if (graph->cnt >= graph->cal || -1 != query_vertex_graph(graph, vertex))
return false;
graph->vertex[graph->cnt].data = vertex;
graph->vertex[graph->cnt].inlink = NULL;
graph->vertex[graph->cnt++].outlink = NULL;
return true;
}
// 添加弧
bool add_bow_graph(Graph *graph, char tailvex, char headvex)
{
// 如果弧頭或弧尾的頂點不存在則添加失敗
int tailindex = query_vertex_graph(graph, tailvex);
int headindex = query_vertex_graph(graph, headvex);
if (-1 == tailindex || -1 == headindex)
return false;
// 創(chuàng)建一個弧
Bow *bow = malloc(sizeof(Bow));
bow->tailvex = tailindex;
bow->headvex = headindex;
bow->tlink = graph->vertex[tailindex].outlink;
graph->vertex[tailindex].outlink = bow;
bow->hlink = graph->vertex[headindex].inlink;
graph->vertex[headindex].inlink = bow;
return true;
}
// 刪除頂點
bool del_vertex_graph(Graph *graph, char vertex)
{
// 找到頂點的下標,如果找不到則返回false
int index = query_vertex_graph(graph, vertex);
if (-1 == index)
return false;
// 以它作為弧尾的弧要全部斷開
graph->vertex[index].inlink = NULL;
// 以它作為弧頭的弧要全部刪除
for (int i = 0; i < graph->cnt; i++)
{
Bow *out = graph->vertex[i].outlink;
while (NULL != out && NULL != out->tlink)
{
if (out->tlink->headvex == index)
{
Bow *tmp = out->tlink;
out->tlink = tmp->tlink;
free(tmp);
}
out = out->tlink;
}
if (NULL != graph->vertex[i].outlink &&
index == graph->vertex[i].outlink->headvex)
{
Bow *tmp = graph->vertex[i].outlink;
graph->vertex[i].outlink = tmp->tlink;
free(tmp);
}
}
return true;
}
// 刪除弧
bool del_bow_graph(Graph *graph, char tailvex, char headvex)
{
// 找到弧頭、弧尾頂點的下標,如果有一個找不到就返回false
int tailindex = query_vertex_graph(graph, tailvex);
int headindex = query_vertex_graph(graph, headvex);
if (-1 == tailindex || -1 == headindex)
return false;
// 刪除弧,并且要保證兩個鏈表不斷開
Bow *out = graph->vertex[tailindex].outlink;
while (NULL != out && NULL != out->tlink)
{
if (out->tlink->headvex == headindex)
{
out->tlink = out->tlink->tlink;
break;
}
out = out->tlink;
}
if (NULL != graph->vertex[tailindex].outlink &&
headindex == graph->vertex[tailindex].outlink->headvex)
{
graph->vertex[tailindex].outlink = graph->vertex[tailindex].outlink->tlink;
}
Bow *in = graph->vertex[headindex].inlink;
while (NULL != in && NULL != in->hlink)
{
if (in->hlink->tailvex == tailindex)
{
Bow *tmp = in->hlink;
in->hlink = tmp->hlink;
free(tmp);
break;
}
in = in->hlink;
}
if (NULL != graph->vertex[headindex].outlink &&
tailindex == graph->vertex[headindex].outlink->tailvex)
{
Bow *tmp = graph->vertex[headindex].inlink;
graph->vertex[headindex].inlink = tmp->hlink;
free(tmp);
}
return true;
}
// 計算入度
int indegree_vertex_graph(Graph *graph, char vertex)
{
int index = query_vertex_graph(graph, vertex);
if (-1 == index)
return -1;
int indegree = 0;
Bow *in = graph->vertex[index].inlink;
while (NULL != in)
{
indegree++;
in = in->hlink;
}
return indegree;
}
// 計算出度
int outdegree_vertex_graph(Graph *graph, char vertex)
{
int index = query_vertex_graph(graph, vertex);
if (-1 == index)
return -1;
int outdegree = 0;
Bow *out = graph->vertex[index].outlink;
while (NULL != out)
{
outdegree++;
out = out->tlink;
}
return outdegree;
}
// 深度優(yōu)先
void _dfs_graph(Graph *graph, int index, bool *flags)
{
printf("%c ", graph->vertex[index].data);
flags[index] = false;
Bow *out = graph->vertex[index].outlink;
while (NULL != out)
{
if (flags[out->headvex])
_dfs_graph(graph, out->headvex, flags);
out = out->tlink;
}
}
void dfs_graph(Graph *graph)
{
bool flags[graph->cnt];
for (int i = 0; i < graph->cnt; i++)
flags[i] = true;
for (int i = 0; i < graph->cnt; i++)
if (flags[i])
_dfs_graph(graph, i, flags);
printf("\n");
}
// 廣度優(yōu)先
void bfs_graph(Graph *graph)
{
bool flags[graph->cnt];
for (int i = 0; i < graph->cnt; i++)
flags[i] = true;
int queue[graph->cnt], front = 0, rear = 0;
for (int i = 0; i < graph->cnt; i++)
{
if (flags[i])
{
queue[rear++] = i;
flags[i] = false;
}
while (front != rear)
{
int index = queue[front++];
printf("%c ", graph->vertex[index].data);
Bow *out = graph->vertex[index].outlink;
while (NULL != out)
{
if (flags[out->headvex])
{
queue[rear++] = out->headvex;
flags[out->headvex] = false;
}
out = out->tlink;
}
}
}
printf("\n");
}
// 銷毀圖
void destroy_graph(Graph *graph)
{
for (int i = 0; i < graph->cnt; i++)
del_vertex_graph(graph, graph->vertex[i].data);
free(graph->vertex);
free(graph);
}
int main(int argc, const char *argv[])
{
Graph *graph = create_graph(10);
add_vertex_graph(graph, 'A');
add_vertex_graph(graph, 'B');
add_vertex_graph(graph, 'C');
add_vertex_graph(graph, 'D');
add_vertex_graph(graph, 'E');
add_bow_graph(graph, 'A', 'D');
add_bow_graph(graph, 'A', 'E');
add_bow_graph(graph, 'A', 'C');
add_bow_graph(graph, 'C', 'B');
add_bow_graph(graph, 'B', 'D');
add_bow_graph(graph, 'E', 'D');
dfs_graph(graph);
bfs_graph(graph);
destroy_graph(graph);
// del_vertex_graph(graph,'D');
// del_bow_graph(graph,'A','D');
/*
printf("%d\n",indegree_vertex_graph(graph,'B'));
for(int i=0; i<graph->cnt; i++)
{
printf("vex:%c",graph->vertex[i].data);
printf("\n\t");
Bow* out = graph->vertex[i].outlink;
while(NULL != out)
{
printf("%d->%d ",out->tailvex,out->headvex);
out = out->tlink;
}
printf("\n\t");
Bow* in= graph->vertex[i].inlink;
while(NULL != in)
{
printf("%d<-%d ",in->headvex,in->tailvex);
in = in->hlink;
}
printf("\n");
}
*/
return 0;
}
鄰接多重表:
? 是對鄰接表一種擴展,在鄰接表邊的基礎(chǔ)上,增加了訪問標記、組成邊的兩個頂點的下標、指向依附這兩個頂點的下一條邊的指針。
? 使用鄰接表時,它的一條邊的兩個節(jié)點,分別在第i和第j的兩個鏈表中,這給圖的操作帶來不便,而鄰接多重表的鏈表節(jié)點增加各項成員,方便對圖的操作。
A’, ‘C’);
add_bow_graph(graph, ‘C’, ‘B’);
add_bow_graph(graph, ‘B’, ‘D’);
add_bow_graph(graph, ‘E’, ‘D’);
dfs_graph(graph);
bfs_graph(graph);
destroy_graph(graph);
// del_vertex_graph(graph,‘D’);
// del_bow_graph(graph,‘A’,‘D’);
/*
printf(“%d\n”,indegree_vertex_graph(graph,‘B’));
for(int i=0; icnt; i++)
{
printf(“vex:%c”,graph->vertex[i].data);
printf(“\n\t”);
Bow* out = graph->vertex[i].outlink;
while(NULL != out)
{
printf(“%d->%d “,out->tailvex,out->headvex);
out = out->tlink;
}
printf(”\n\t”);
Bow* in= graph->vertex[i].inlink;
while(NULL != in)
{
printf(“%d<-%d “,in->headvex,in->tailvex);
in = in->hlink;
}
printf(”\n”);
}
*/
return 0;
}
#### 鄰接多重表:
? 是對鄰接表一種擴展,在鄰接表邊的基礎(chǔ)上,增加了訪問標記、組成邊的兩個頂點的下標、指向依附這兩個頂點的下一條邊的指針。
? 使用鄰接表時,它的一條邊的兩個節(jié)點,分別在第i和第j的兩個鏈表中,這給圖的操作帶來不便,而鄰接多重表的鏈表節(jié)點增加各項成員,方便對圖的操作。
原文鏈接:https://blog.csdn.net/weixin_52744725/article/details/127041968
相關(guān)推薦
- 2022-09-30 Python中4種實現(xiàn)數(shù)值的交換方式_python
- 2022-09-04 詳解Go語言中數(shù)組,切片和映射的使用_Golang
- 2022-12-08 C語言程序如何求學生總成績和平均成績_C 語言
- 2023-06-13 python調(diào)試過程中多顏色輸出方式_python
- 2022-04-27 使用jQuery實現(xiàn)圖片輪播效果_jquery
- 2022-09-24 Python?tkinter?多選按鈕控件?Checkbutton方法_python
- 2023-03-25 Python?Flask-Login模塊使用案例詳解_python
- 2023-05-20 Golang基于文件魔數(shù)判斷文件類型的案例代碼_Golang
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支