Data Structure Study Notes - Figure

1. Introduction to the picture

​Graph is a relatively complex data structure. There is only a linear relationship between data elements in a linear table. Each element has only one direct predecessor and direct successor (there is only one-to-one relationship between elements). In the tree structure There is an obvious hierarchical relationship between the elements in the middle, and the elements of each layer can only have a relationship with multiple elements in the lower layer (there is a one-to-many relationship between the elements), while in the graph structure, there is a relationship between any two nodes. There may be relationships (a many-to-many relationship between elements).

2. Definition and Terminology of Graph

**Vertices:** The data elements in the graph are called vertices, and V is generally used to represent the finite non-empty collection of vertices of the graph.

**Arc:** The relationship between two vertices is denoted as <v, w>, which means that v can reach vertex w, that is, v can reach w, but w may not reach v, we call v an arc The tail or the initial point, w is called the arc head or terminal point.

**Directed graph:** A graph composed of arcs + vertices is called a directed graph, that is, there is a one-way street between vertices.

**Edge:** The relationship record between two vertices (v, w), which means that it can go from v to w or from w to v. We call the relationship between v and w an edge.

**Undirected graph: **The graph composed of edges + vertices has an undirected graph, a two-way street between vertices.

**Note:** Generally use G to represent a graph, V to represent a collection of vertices, VR to represent a collection of arcs or edges, n to represent the number of vertices, e to represent the number of edges or arcs, and we do not discuss vertices to their own edges or arcs.

**Complete graph:** In an undirected graph, the value range of e is 0 ~ n/2(n-1). If the number of edges of the undirected graph reaches the maximum value, the undirected graph is called complete. picture.

**Directed complete graph:**In a directed graph, the value range of e is 0 ~ n(n-1). If the number of arcs in the directed graph reaches the maximum value, this directed graph is called a directed graph. towards the complete graph.

**Sparse graph and dense graph:** If there are few edges and arcs in the graph, e<nlogn such a graph is called a sparse graph, otherwise it is called a dense graph.

**Weight and network:** If a vertex in the graph needs a cost (distance or cost) to go to another vertex, then additional data is required when representing an edge or arc. The additional data is called weight, and a weighted graph is usually called It is called the net, which is also the origin of the Internet.

**Subgraph:** Assume that there are two graphs G1 and G2, if the vertex set of G1 is a subset of the vertex set of G2, and the edge or arc set of G1 is a subset of the edge or arc set of G2, then it is called G1 is a subgraph of G2.

**Adjacency point:** If there is an edge (v, w) in an undirected graph, then the two vertices of v and w are adjacent points to each other, that is, v and w are adjacent to each other, and the edge (v, w) is attached to Vertex v, w, or (v, w) is associated with vertices v, w.

**Degree of vertex v:** The number of edges associated with vertex v in the undirected graph.

**In-degree and out-degree of vertex v:** In a directed graph, the number of arcs with vertex v as the arc head is called the in-degree of the vertex, and the number of arcs with vertex v as the arc tail is called the vertex’s Out degree.

**Path:** The sequence of vertices experienced from vertex v to vertex w is called a path, and the length of the path is the number of edges or arcs.

**Circuit or Ring:** A path whose starting point and end point are the same is called a loop or ring.

**Simple path: **A path whose vertices do not appear repeatedly in the path is called a simple path.

**Simple circuit or simple ring: **The start point and end point are the same and the rest of the vertices do not appear repeatedly, which is called a simple circuit or simple ring.

**Connected graph:** In an undirected graph, if there is a path from vertex v to vertex w, then v and w are said to be connected. If any two vertices in the graph are connected, the graph is called a connected graph.

**Connected component: **G1 and G2 are both connected graphs, and G1 is a subgraph of G2, then G1 is said to be a connected component or maximally connected subgraph of G2.

Strongly Connected Graph: In a directed graph, if any pair of vertices are bidirectionally connected, the graph is called a strongly connected graph.

Strongly connected component: G1 and G2 are both strongly connected graphs, and G1 is a subgraph of G2, then G1 is said to be a strongly connected component or extremely strongly connected subgraph of G2.

3. The storage structure of the graph:

Adjacency matrix:

Use two arrays to store information about data elements (vertices) and relationships (edges or arcs) between data elements.

​ One-dimensional array: used to store vertices.

​ Two-dimensional array: used to store arcs or edges.

Advantages of adjacency matrix:

​ The access speed is fast, and it is convenient to calculate the degree, in-degree, and out-degree of nodes.

Disadvantages of adjacency matrix:

​ The capacity of vertices is limited, and expansion is very troublesome. It is only suitable for storing dense graphs, and there will be a lot of memory waste when storing sparse graphs.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// 无向图
typedef struct Grahh
{
    
    
	size_t cal;	  // 顶点容量
	size_t cnt;	  // 顶点数量
	char *vertex; // 存储顶点的一维数组
	char **edge;  // 存储边的二维数组
} 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;
}

// 查询顶点在一维数组中的位置,如果不存在则返回-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);
	}
}

// 深度优先遍历,与树的前序遍历类似
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);
}

// 广度优先遍历,与树的层序遍历一样,需要队列结构配合
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;
}

Adjacency list:

​ Use a one-dimensional array plus a one-way linked list to store and store.

​ One-dimensional array: used to store the head pointer of the vertex and the one-way linked list.

​ One-way linked list: stores the arc or edge starting from the vertex.

Advantages of adjacency list:

​ Compared with the adjacency matrix, it can save memory and create as many linked list nodes as there are edges or arcs, which is more suitable for storing sparse graphs.

Adjacency list disadvantages:

​ It is troublesome to calculate in-degree and delete nodes.

#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; // 单链表的空白头节点
} Vertex;

// 有向图
typedef struct Graph
{
    
    
	Vertex *vertex;
	size_t cal;
	size_t cnt;
} Graph;

// 创建图
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)
{
    
    
	// 找到顶点,从它出发的弧有多少条,如果找不到则返回-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;
}

// 深度优先遍历
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)
{
    
    
	// 参考昨天邻接矩阵的业务逻辑
	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");
}

// 广度优先遍历
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;
}

Cross list:

​A one-dimensional array plus two cross-linked lists is used for storage. The reason why it is called a cross-linked list is that its linked list arc node will be pointed to by two linked lists, and the arc node has two pointers, pointing to subsequent arc nodes.

​ One-dimensional array: store vertex data, two linked list head pointers.

​ Out-degree linked list: points to the arc node with the node as the end of the arc.

​ In-degree linked list: points to the arc node with this node as the arc head.

Advantages of Cross Linked List:

Compared with the adjacency matrix, it is more memory-efficient, and it is more convenient to calculate the out-degree of vertices than the adjacency list.

Disadvantages of Cross Linked List:

​ It is more troublesome to delete vertices and delete arcs. It can also represent and realize undirected graphs, but it is more suitable to represent and realize directed graphs.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// 弧
typedef struct Bow
{
    
    
	int tailvex;	   // 弧尾的顶点下标
	int headvex;	   // 弧头的顶点下标
	struct Bow *tlink; // 指向相同弧尾的弧节点
	struct Bow *hlink; // 指向相同弧头的弧节点
} Bow;

// 顶点
typedef struct Vertex
{
    
    
	char data;
	Bow *inlink;
	Bow *outlink;
} Vertex;

// 图
typedef struct Graph
{
    
    
	Vertex *vertex;
	size_t cal;
	size_t cnt;
} Graph;

// 创建图
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)
{
    
    
	// 如果顶点已经满,或顶点已经存在则返回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;

	// 创建一个弧
	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;
}

// 深度优先
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");
}

// 广度优先
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;
}

Adjacency multitable:

​ is an extension to the adjacency list. On the basis of the adjacency list edge, an access tag, the subscripts of the two vertices that make up the edge, and a pointer to the next edge attached to the two vertices are added.

​ When using the adjacency list, the two nodes of one of its edges are in the i-th and j-th linked lists respectively, which brings inconvenience to the operation of the graph, and the linked list nodes adjacent to the multi-table add various members, which is convenient operations on graphs.

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;

}


#### 邻接多重表:

​	是对邻接表一种扩展,在邻接表边的基础上,增加了访问标记、组成边的两个顶点的下标、指向依附这两个顶点的下一条边的指针。

​	使用邻接表时,它的一条边的两个节点,分别在第i和第j的两个链表中,这给图的操作带来不便,而邻接多重表的链表节点增加各项成员,方便对图的操作。















Guess you like

Origin blog.csdn.net/m0_62480610/article/details/126459521