图是一种非线性的数据结构,由节点(顶点)和连接节点的边组成。图可以用来表示各种各样的关系,比如社交网络中的用户之间的关系、地图上的城市之间的道路等。
图可以分为有向图和无向图。有向图中的边有方向,表示从一个节点到另一个节点的单向关系;无向图中的边没有方向,表示两个节点之间的双向关系。
图的节点可以包含附加信息,比如在社交网络中的用户节点可以包含用户的个人信息。边可以有权重,表示节点之间的关系的强度或成本。
图的常用操作包括添加节点、添加边、删除节点、删除边、查找节点、查找边等。
图的遍历是一种常用的操作,可以按照某种规则依次访问图中的所有节点。深度优先搜索(DFS)和广度优先搜索(BFS)是两种常用的图遍历算法。
图的应用非常广泛,包括网络路由、社交网络分析、图像处理、推荐系统等领域。在算法和数据结构中,图也是许多经典问题的基础,比如最短路径问题、最小生成树问题等。
以下是图的基本操作和实现代码:
在创建一个图之前,需要先定义点和边的数据结构。通常使用邻接表或邻接矩阵来表示图。
邻接表实现:
//定义点和边的结构体
struct EdgeNode
{
int vertex; //边所连接的点
int weight; //边的权重
EdgeNode* next; //指向下一条边的指针
};
struct Graph
{
int numV; //图中点的数量
bool isDirected; //是否为有向图
EdgeNode** adjList; //邻接表
};
//创建一个点的邻接表
EdgeNode* createEdgeNode(int vertex, int weight)
{
EdgeNode* node = new EdgeNode;
node->vertex = vertex;
node->weight = weight;
node->next = NULL;
return node;
}
//创建一个有向图的邻接表
Graph* createDirectedGraph(int numV)
{
Graph* graph = new Graph;
graph->numV = numV;
graph->isDirected = true;
graph->adjList = new EdgeNode*[numV];
for (int i = 0; i < numV; i++)
graph->adjList[i] = NULL;
return graph;
}
//创建一个无向图的邻接表
Graph* createUndirectedGraph(int numV)
{
Graph* graph = new Graph;
graph->numV = numV;
graph->isDirected = false;
graph->adjList = new EdgeNode*[numV];
for (int i = 0; i < numV; i++)
graph->adjList[i] = NULL;
return graph;
}
邻接矩阵实现:
//定义点和边的结构体
struct Graph
{
int numV; //图中点的数量
bool isDirected; //是否为有向图
int** matrix; //邻接矩阵
};
//创建一个有向图的邻接矩阵
Graph* createDirectedGraph(int numV)
{
Graph* graph = new Graph;
graph->numV = numV;
graph->isDirected = true;
graph->matrix = new int*[numV];
for (int i = 0; i < numV; i++)
{
graph->matrix[i] = new int[numV];
for (int j = 0; j < numV; j++)
graph->matrix[i][j] = 0;
}
return graph;
}
//创建一个无向图的邻接矩阵
Graph* createUndirectedGraph(int numV)
{
Graph* graph = new Graph;
graph->numV = numV;
graph->isDirected = false;
graph->matrix = new int*[numV];
for (int i = 0; i < numV; i++)
{
graph->matrix[i] = new int[numV];
for (int j = 0; j < numV; j++)
graph->matrix[i][j] = 0;
}
return graph;
}
邻接表实现:
//向有向图中添加一条边
void addDirectedEdge(Graph* graph, int src, int dest, int weight)
{
EdgeNode* node = createEdgeNode(dest, weight);
node->next = graph->adjList[src];
graph->adjList[src] = node;
}
//向无向图中添加一条边
void addUndirectedEdge(Graph* graph, int src, int dest, int weight)
{
EdgeNode* node1 = createEdgeNode(dest, weight);
EdgeNode* node2 = createEdgeNode(src, weight);
node1->next = graph->adjList[src];
graph->adjList[src] = node1;
node2->next = graph->adjList[dest];
graph->adjList[dest] = node2;
}
邻接矩阵实现:
//向有向图中添加一条边
void addDirectedEdge(Graph* graph, int src, int dest, int weight)
{
graph->matrix[src][dest] = weight;
}
//向无向图中添加一条边
void addUndirectedEdge(Graph* graph, int src, int dest, int weight)
{
graph->matrix[src][dest] = weight;
graph->matrix[dest][src] = weight;
}
邻接表实现:
//从有向图中删除一条边
void removeDirectedEdge(Graph* graph, int src, int dest)
{
EdgeNode* current = graph->adjList[src];
EdgeNode* prev = NULL;
while (current)
{
if (current->vertex == dest)
{
if (prev)
prev->next = current->next;
else
graph->adjList[src] = current->next;
delete current;
break;
}
prev = current;
current = current->next;
}
}
//从无向图中删除一条边
void removeUndirectedEdge(Graph* graph, int src, int dest)
{
EdgeNode* current = graph->adjList[src];
EdgeNode* prev = NULL;
while (current)
{
if (current->vertex == dest)
{
if (prev)
prev->next = current->next;
else
graph->adjList[src] = current->next;
delete current;
break;
}
prev = current;
current = current->next;
}
current = graph->adjList[dest];
prev = NULL;
while (current)
{
if (current->vertex == src)
{
if (prev)
prev->next = current->next;
else
graph->adjList[dest] = current->next;
delete current;
break;
}
prev = current;
current = current->next;
}
}
邻接矩阵实现:
//从有向图中删除一条边
void removeDirectedEdge(Graph* graph, int src, int dest)
{
graph->matrix[src][dest] = 0;
}
//从无向图中删除一条边
void removeUndirectedEdge(Graph* graph, int src, int dest)
{
graph->matrix[src][dest] = 0;
graph->matrix[dest][src] = 0;
}
邻接表实现:
//递归函数,用于深度优先遍历
void dfsHelper(Graph* graph, int vertex, bool* visited)
{
visited[vertex] = true;
cout << vertex << " ";
EdgeNode* current = graph->adjList[vertex];
while (current)
{
if (!visited[current->vertex])
dfsHelper(graph, current->vertex, visited);
current = current->next;
}
}
//深度优先遍历
void dfs(Graph* graph, int startVertex)
{
bool* visited = new bool[graph->numV];
for (int i = 0; i < graph->numV; i++)
visited[i] = false;
dfsHelper(graph, startVertex, visited);
delete[] visited;
}
邻接矩阵实现:
//递归函数,用于深度优先遍历
void dfsHelper(Graph* graph, int vertex, bool* visited)
{
visited[vertex] = true;
cout << vertex << " ";
for (int i = 0; i < graph->numV; i++)
{
if (graph->matrix[vertex][i] != 0 && !visited[i])
dfsHelper(graph, i, visited);
}
}
//深度优先遍历
void dfs(Graph* graph, int startVertex)
{
bool* visited = new bool[graph->numV];
for (int i = 0; i < graph->numV; i++)
visited[i] = false;
dfsHelper(graph, startVertex, visited);
delete[] visited;
}
邻接表实现:
//广度优先遍历
void bfs(Graph* graph, int startVertex)
{
bool* visited = new bool[graph->numV];
for (int i = 0; i < graph->numV; i++)
visited[i] = false;
queue q;
visited[startVertex] = true;
q.push(startVertex);
while (!q.empty())
{
int vertex = q.front();
q.pop();
cout << vertex << " ";