日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網(wǎng)站首頁 編程語言 正文

數(shù)據(jù)結(jié)構(gòu)---圖、十字鏈表及其代碼實現(xiàn)

作者:愛吃焦糖布丁 更新時間: 2022-09-26 編程語言

文章目錄

      • 一、圖的介紹
      • 二、圖的定義和術(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

欄目分類
最近更新