#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <climits>
#include <algorithm>
#include <unordered_map>
using namespace std;
// 图的邻接矩阵存储
#define maxint 32767
#define mvnum 100
typedef int vertextype;
typedef int arctype;
typedef struct {
vertextype vexs[mvnum];
arctype arcs[mvnum][mvnum];
int vexnum, arcnum;
}amgraph;
//创建无向网
int createudn(amgraph& G) {
cout << "输入顶点数和边数: ";
cin >> G.vexnum >> G.arcnum;
int i, j,k; vertextype v1, v2; arctype w;
for (i = 0; i < G.vexnum; ++i) {
cout << "输入顶点信息: ";
cin >> G.vexs[i];
}
//初始化邻接矩阵
for (i = 0; i < G.vexnum; ++i) {
for (j = 0; j < G.vexnum; ++j) {
G.arcs[i][j] = maxint;
}
}
//构建邻接矩阵
for (k = 0; k < G.arcnum; ++k) {
cout << "输入边及权重: ";
cin >> v1 >> v2 >> w;
i = locatevex(G, v1);
j = locatevex(G, v2);
G.arcs[i][j] = w;
G.arcs[j][i] = w;
}
return 1;
}
int locatevex(amgraph G, vertextype u) {
int i;
for (int i = 0; i < G.vexnum; ++i) {
if (u == G.vexs[i]) {
return i;
}
}
return -1;
}
//// 图的邻接表存储
typedef struct arcnode {//边表节点
int adjvex;
arctype info;
struct arcnode* nextarc;
}arcnode;
typedef struct vertexnode {//顶点表节点
vertextype data;
arcnode* firstarc;
}vertexnode,adjlist[mvnum];
typedef struct {
adjlist vertices;
int vexnum, arcnum;
}algraph;
void createalgraph(algraph&G){
int i, j, k; vertextype v1, v2;
cout << "输入顶点数和边数: ";
cin >> G.vexnum >> G.arcnum;
for (i = 0; i < G.vexnum; ++i) {
cout << "输入顶点信息: ";
cin >> G.vertices[i].data;//输入顶点信息
G.vertices->firstarc = NULL;
}
cout << "输入边:" << endl;
for (k = 0; k < G.arcnum; ++k) {
cin >> v1 >> v2;//输入一条边依附的两个顶点
i = locatevex(G, v1);
j = locatevex(G, v2);
arcnode* p1 = new arcnode;
p1->adjvex = j;
p1->nextarc = G.vertices[i].firstarc;//头插法
G.vertices[i].firstarc = p1;
arcnode* p2 = new arcnode;
p2->adjvex = i;
p2->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = p2;
}
}
int locatevex(algraph G, vertextype u) {
int i;
for (int i = 0; i < G.vexnum; ++i) {
if (u == G.vertices[i].data) {
return i;
}
}
return -1;
}
//DFS,邻接矩阵
bool visited[mvnum];
void DFSAM(amgraph& G,int i) {
cout << G.vexs[i];
visited[i] = true;
for (int j = 0; j < G.vexnum; ++j) {
if (G.arcs[i][j] != maxint && !visited[i]) {
DFSAM(G, j);
}
}
}
////DFS,邻接表
bool visited2[mvnum];
void DFSAL(algraph G, int i) {
cout << G.vertices[i].data;
visited[i] = true;
arcnode*p = G.vertices[i].firstarc;
while (p) {
if (!visited[p->adjvex])DFSAL(G, p->adjvex);
p = p->nextarc;
}
}
//BFS,邻接矩阵
typedef struct {// 定义队列结构
int items[maxint];
int front;
int rear;
} Queue;
// 队列初始化
void initQueue(Queue* q) {
q->front = -1;
q->rear = -1;
}
//检查队列是否为空
int isEmpty(Queue * q) {
return (q->rear == -1);
}
// 入队操作
void enqueue(Queue* q, int value) {
if (q->rear == maxint - 1) {
cout<<"队列已满\n";
return;
}
if (q->front == -1) {
q->front = 0;
}
q->rear++;
q->items[q->rear] = value;
}
// 出队操作
int dequeue(Queue* q) {
if (isEmpty(q)) {
printf("队列为空\n");
return -1;
}
int item = q->items[q->front];
q->front++;
if (q->front > q->rear) {
q->front = q->rear = -1; // 重置队列
}
return item;
}
void BFSAM(int matrix[maxint][maxint], int n, int startv) {
int visited[maxint] = { 0 };
Queue q;
initQueue(&q);
visited[startv] = 1;
enqueue(&q, startv);
while (!isEmpty(&q)) {
int u= dequeue(&q);
cout << u;
for (int i = 0; i < n; i++) {
if (matrix[u][i] == 1 && !visited[i]) { // 有边且未访问
visited[i] = 1; // 标记为已访问
enqueue(&q, i); // 邻接点入队
}
}
}
}
//BFS,邻接表
void BFSAL(algraph G, int start_index) {
bool visited[mvnum] = {0};
Queue q;
initQueue(&q);
visited[start_index] = true;
enqueue(&q, start_index);
while (!isEmpty(&q)) {
int u = dequeue(&q);
cout << G.vertices[u].data << " "; // 输出顶点数据
arcnode* p = G.vertices[u].firstarc;
while (p != nullptr) {
int v = p->adjvex; // 获取邻接顶点索引
if (!visited[v]) {// 如果邻接点未被访问
visited[v] = true;
enqueue(&q, v);
}
p = p->nextarc;
}
}
cout << endl;
}
//最小生成树,prim,邻接矩阵
struct {//定义辅助数组,记录U到V-U的最小权值边
vertextype adjvex;//V-U到U的最小权值边对应顶点
arctype lowcost;//该最小边的权值
}closedge[mvnum];
int Min() {
arctype min_val = maxint; // 初始化最小值为极大数
int min_index = -1;
for (int i = 0; i < mvnum; i++) {
// 跳过已加入 MST 的顶点 (lowcost=0)
if (closedge[i].lowcost > 0 && closedge[i].lowcost < min_val) {
min_val = closedge[i].lowcost;
min_index = i;
}
}
return min_index; // 返回最小权值边的顶点索引
}
void MSTP(amgraph& G, vertextype u) {
//初始化
int k = locatevex(G, u);//k为出发顶点u的下标
for (int j = 0; j < G.vexnum; ++j) {
if (j != k) {
closedge[j] = { u,G.arcs[k][j] };
}
}
closedge[k].lowcost = 0;
for (int i = 1; i < G.vexnum; ++i) {//循环除了u以外的顶点,生成n-1条边
int m = Min();//找到当前最小权值边的顶点索引
int u0 = closedge[m].adjvex;//最小边所依附的MST中的顶点
int v0 = G.vexs[m];//最小边所依附的V-U中的另一个顶点
cout << u0 << " - " << v0;
closedge[m].lowcost = 0;//第m个顶点并入U
for (int j = 0; j < G.vexnum; ++j) {//更新U到U-V的最小权值的边
if (G.arcs[m][j] < closedge[j].lowcost) {
closedge[j] = { G.vexnum,G.arcs[m][j] };
}
}
}
}
//最小生成树,kruskal,邻接矩阵
struct edge{
int head;//边的起点
int tail;//边的终点
arctype lowcost;//边的权值
};//存储边的信息
// 比较函数(用于sort排序)
bool edgeCompare(const edge& a, const edge& b) {
return a.lowcost < b.lowcost; // 按权值升序排序
}
int vexset[mvnum];//标识各个顶点所属的联通分量
void MSTK(amgraph G) {
//初始化
edge* edges = new edge[G.arcnum];
int edgeCount = 0;
// 遍历邻接矩阵提取边
for (int i = 0; i < G.vexnum; ++i) {
for (int j = i + 1; j < G.vexnum; ++j) {
if (G.arcs[i][j] != maxint) {
edges[edgeCount].head = i;
edges[edgeCount].tail= j;
edges[edgeCount].lowcost = G.arcs[i][j];
edgeCount++;
}
}
}
// 按权值排序边
sort(edges, edges + edgeCount, [](const edge& a, const edge& b) {
return a.lowcost < b.lowcost;
});
for (int i = 0; i < G.vexnum; ++i) {//所有顶点自成一个联通分量
vexset[i] = i;
}
for (int i = 0; i < G.arcnum; ++i) {
int v1 = locatevex(G, edges[i].head);
int v2 = locatevex(G, edges[i].tail);
int vs1 = vexset[v1];
int vs2 = vexset[v2];//确定V1V2所在联通分量
if (vs1 != vs2) {
cout << edges[i].head << edges[i].tail << endl;//输出此边
//合并vs1vs2,找到vs2所有顶点,合并到vs1
for (int j = 0; j < G.vexnum; ++j) {
if (vexset[j] == vs2) {
vexset[j] = vs1;
}
}
}
};
}
//单源最短路径,dijkstra
//定义辅助数组
bool S[mvnum];//记录从源点v0到终点vi是否已被确定最短路径长度
int Path[mvnum];//记录从源点v0到终点vi的当前最短路径长度上vi的直接前驱结点序号
arctype D[mvnum];//记录从源点v0到终点vi的当前最短路径长度
void shortestDIJ(amgraph G, int v0) {
for (int v = 0; v < G.vexnum; ++v) {//初始化
S[v] = false;
D[v] = G.arcs[v0][v];
if (D[v] < maxint)Path[v] = v0;
else Path[v] = -1;
}
S[v0] = true;//v0加入S
D[v0] = 0;//源点到源点的距离为0
//寻找从v0到集合V-S的最短路径的最小值
for (int i = 1; i < G.vexnum; ++i) {//对其余n-1个顶点依次计算最短路径
// 每次求得v0到某个顶点v的最短路径,并加v加入S
int min = maxint;
int v;
for (int w = 0; w < G.vexnum; ++w) {
if (!S[w] && D[w] < min) {
v = w;
min = D[w];//选择一条当前最短路径,终点为v,v属于V-S
}
}
S[v] = true;
//更新从v0出发,经过集合S,到集合V-S中所有顶点的最短路径
for (int w = 0; w < G.vexnum; ++w) {
if (!S[w] && D[v] + G.arcs[v][w] < D[w]) {
D[w] = D[v] + G.arcs[v][w];//新路径:从v0出发,经过v到达w
Path[w] = v;
}
}
}
}
//Floyed,多源最短路径
//定义辅助数组
int D2[mvnum][mvnum];
int Path2[mvnum][mvnum];
void shortestfloyed(amgraph G) {
//初始化
for (int i = 0; i < G.vexnum; ++i) {
for (int j = 0; j < G.vexnum; ++j) {
D2[i][j] = G.arcs[i][j];
if (D2[i][j] < maxint && i != j)Path2[i][j] = i;
else Path2[i][j] = -1;
}
}
for (int k = 0; k < G.vexnum; ++k) {
for (int i = 0; i < G.vexnum; ++i) {
for (int j = 0; j < G.vexnum; ++j) {
if (D2[i][j] > D2[i][k] + D2[k][j]) {
D2[i][j] = D2[i][k] + D2[k][j];
Path2[i][j] = Path2[k][j];
}
}
}
}
}
//无权图,Dijkstra
void dijuw(amgraph G, int v0) {
//初始化
for (int v = 0; v < G.vexnum; ++v) {
S[v] = false;
D[v] = (G.arcs[v0][v] == maxint) ? maxint : 1;
if (D[v] < maxint) Path[v] = v0;
else Path[v] = -1;
}
S[v0] = true;
D[v0] = 0;
for (int i = 1; i < G.vexnum; ++i) {
int min = maxint;
int v;
for (int w = 0; w < G.vexnum; ++w) {
if (!S[w] && D[w] < min) {
v = w;
min = D[w];
}
}
S[v] = true;
for (int w = 0; w < G.vexnum; ++w) {
if (!S[w] && G.arcs[v][w] < maxint) {
if (D[v] + 1 < D[w]) {
D[w] = D[v] + 1;
Path[w] = v;
}
}
接着这段代码用
BFS 求解无权图的单源最短路径问题。
最新发布