图的基本概念
- 度的概念
- 路径
- 连通图
- 权与网
- 子图
- 连通分量
邻接矩阵
- 无向图的邻接矩阵
- 有向图的邻接矩阵
- 有向网
- 邻接矩阵的优点是实现简单,如果图是稠密的,使用邻接矩阵最合适存储方法
- 如果图是稀疏的,这种表示代价就太大,最好的方法是采用邻接表存储
邻矩阵创建无向网
#include <iostream>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
#define MAXSIZE 100
#define MAXINT 32767
typedef struct
{
/* data */
char Vexs[MAXSIZE]; // 图的顶点
int Arcs[MAXSIZE][MAXSIZE]; // 图的邻接矩阵
int vexnum, arcnum; // 图的总顶点数和总边数
} Graph;
// 图中查找顶点 存在则返回表中的下标
int LocateVex(Graph &G, char &vex)
{
for (int i = 0; i < G.vexnum; i++)
{
if (G.Vexs[i] == vex)
{
return i;
}
}
return -1;
}
// 创建无向网
void CreatUDN(Graph &G)
{
cout << "输入无向图的顶点数目:" << endl;
cin >> G.vexnum >> G.arcnum;
cout << "输入结点名称:" << endl;
for (int i = 0; i < G.vexnum; i++)
{
cin >> G.Vexs[i];
}
// 初始化邻接矩阵 边的权值均置为极大值
for (int i = 0; i < G.vexnum; i++)
{
for (int j = 0; j < G.vexnum; j++)
{
G.Arcs[i][j] = MAXINT;
}
}
// 输入顶点之间关系对应的权值
for (int k = 0; k < G.arcnum; k++)
{
char v1, v2;
int weight, i, j;
cin >> v1 >> v2 >> weight;
i = LocateVex(G, v1);
j = LocateVex(G, v2);
G.Arcs[i][j] = G.Arcs[j][i] = weight; // 边v1 v2的权值置为weight
}
}
邻接表
邻接表表示(链式)
- 无向图邻接表表示
- 有向图邻接表表示
图的邻接表存储表示
- 顶点结构定义
- 边结构定义
- 图结构定义
- 邻接表赋值操作示例
- 图的邻接表表示法
#include <iostream>
#include <queue>
#include <vector>
#include <stack>
#define MAXSIZE 100
using namespace std;
// 边表的定义
struct ArcNode
{
/* data */
int adjvec; // 保存顶点下标
int weight; // 保存边的权重
ArcNode *nextarc; // 指向下一个邻接点的指针域
};
// 顶点表的定义
struct VNode
{
/* data */
char vertex; // 顶点域
ArcNode *firstarc; // 指针域,用于保存邻接表
};
// 图的定义
struct ALGraph
{
/* data */
VNode vexs[MAXSIZE]; // 邻接表
int vexnum, arcnum; // 当前图的顶点数和边条数
};
int LocateVex(ALGraph &G, char &vex)
{
for (int i = 0; i < G.vexnum; i++)
{
if (G.vexs[i].vertex == vex)
{
return i;
}
}
return -1;
}
void CreateUDG(ALGraph &G)
{
cin >> G.vexnum >> G.arcnum;
// 给各顶点赋值
for (int i = 0; i < G.vexnum; i++)
{
cin >> G.vexs[i].vertex;
G.vexs[i].firstarc = nullptr;
}
// 给每个顶点所含的边赋值
for (int k = 0; k < G.arcnum; k++)
{
char a, b;
// 输入边依附的两个顶点
cin >> a >> b;
int i = LocateVex(G, a);
int j = LocateVex(G, b);
ArcNode *p1 = new ArcNode;
// 两个顶点 b->e
// b的下标为i,e的下标为j
p1->adjvec = j; // 将e添加到b后
p1->nextarc = G.vexs[i].firstarc; // b顶点下一个指针域指向e的下一个指针域
G.vexs[i].firstarc = p1; // 新节点插入边表头部
ArcNode *p2 = new ArcNode;
// e -> b
p2 = new ArcNode;
p2->adjvec = i;
p2->nextarc = G.vexs[j].firstarc;
G.vexs[j].firstarc = p2;
}
}
- 图的存储结构
图常用的遍历
- 邻接矩阵深度优先搜索
// 邻接矩阵深度优先遍历算法DFS
// 定义辅助数组visited[] 表示已访问过的结点
int visited[MAXSIZE] = {};
void DFS_G(Graph &G, int vex)
{
// vex 起始顶点
cout << G.Vexs[vex];
visited[vex] = 1;
// 从邻接矩阵的某一行的第1个元素开始-遍历到该行第n个元素
for (int w = 0; w < G.vexnum; w++)
{
// 如果找到一个相连的顶点,并且该顶点还没有被访问过,进入递归函数
if ((G.Arcs[vex][w] != 0) && (!visited[w]))
{
DFS_G(G, w);
}
}
}
- 邻接矩阵广度优先搜索
// 广度优先遍历算法BFS
void BFS_G(Graph &G)
{
for (int i = 0; i < G.vexnum; i++)
{
for (int j = 0; j < G.vexnum; j++)
{
if ((G.Arcs[i][j]) != 0 && visited[j] == 0)
{
cout << G.Vexs[j];
visited[j] = 1;
}
}
}
}