#include <iostream>
#include "Stack.h"
#include "Queue.h"
#define INFINITY 2147483647
#define MaxVertexNum 15
typedef struct VertexType {
char value;
} VertexType;
typedef struct ArcNode {
int adjvex; // 边/弧指向哪个顶点
struct ArcNode *next;//指向下一条弧的指针
int weight;//权值
} ArcNode, *Arc;
typedef struct VNode {
VertexType data;//顶点信息
ArcNode *first;//第一条边/弧信息
} VNode, AdjList[MaxVertexNum];
//用邻接表存储的图
typedef struct {
AdjList vertices;
int vexnum, arcnum;//图的顶点数和边数
int type;//图的类型 0为无向图 1为有向图
} ALGraph;
//初始化一个具有一个顶点的图
void InitALGraph(ALGraph &G, int type) {
for (int i = 0; i < MaxVertexNum; ++i) {
G.vertices[i].first = NULL;
G.vertices[i].data = {};
}
G.vexnum = 0;
VNode &vNode = G.vertices[G.vexnum];
vNode.data = {'A'};
vNode.first = NULL;
G.vexnum++;
G.arcnum = 0;
G.type = type;
}
//在图G中插入顶点x
void InsertVertex(ALGraph &G, char x) {
VNode &vNode = G.vertices[G.vexnum];
vNode.data = {x};
vNode.first = NULL;
G.vexnum++;
}
//判断是否是顶点
bool isVertex(ALGraph G, int x) {
return (x >= 0) && (x < G.vexnum);
}
//无向边(x,y) 或 有向边<x,y>不存在,则向图G中添加该边
void AddEdge(ALGraph &G, int x, int y) {
if (!isVertex(G, x) || !isVertex(G, y)) {
return;
}
ArcNode *p = (ArcNode *) malloc(sizeof(ArcNode));
if (p == NULL) return;
p->next = NULL;
p->weight = 0;
p->adjvex = y;
if (G.vertices[x].first == NULL) {
G.vertices[x].first = p;
} else {
ArcNode *s = G.vertices[x].first;
while (s->next != NULL) {
s = s->next;
}
Arc &arc = s;
arc->next = p;
}
if (G.type == 0) {//无向图
ArcNode *q = (ArcNode *) malloc(sizeof(ArcNode));
if (q == NULL) return;
q->next = NULL;
q->weight = 0;
q->adjvex = x;
if (G.vertices[y].first == NULL) {
G.vertices[y].first = q;
} else {
ArcNode *s = G.vertices[y].first;
while (s->next != NULL) {
s = s->next;
}
Arc &arc = s;
arc->next = q;
}
}
G.arcnum++;
}
//判断图G是否存在边<x,y>或(x,y)
bool Adjacent(ALGraph G, int x, int y) {
if (!isVertex(G, x) || !isVertex(G, y)) {
return false;
}
ArcNode *p = G.vertices[x].first;
while (p != NULL) {
if (p->adjvex == y) {
return true;
}
p = p->next;
}
return false;
}
//在图G中删除顶点x
void DeleteVertex(ALGraph &G, int x) {
if (!isVertex(G, x)) {
return;
}
ArcNode *p = G.vertices[x].first;
if (p == NULL) {
//x不存在出边
if (G.type == 0) {//无向图直接删除
G.vertices[x].data = {};
G.vexnum--;
return;
}
} else {
//先删除x的链表
while (p != NULL) {
ArcNode *q = p;
p = p->next;
free(q);
}
G.vertices[x].first = NULL;
G.vertices[x].data = {};
G.vexnum--;
}
//删除入边,包含两种情况
//1)有向图不存在出边,但是可能有入边
//2)无向图已经删除了入边,要找到所有出边删除
for (int i = 0; i < G.vexnum + 1; ++i) {
if (x == i) continue;
ArcNode *q = G.vertices[i].first;
if (q == NULL) {
continue;
}
if (q != NULL && q->adjvex == x) {
G.vertices[i].first = q->next;
}
while (q->next != NULL && q->next->adjvex != x) {
q = q->next;
}
if (q->next != NULL && q->next->adjvex == x) {
ArcNode *s = q->next;
q->next = q->next->next;
free(s);
}
}
}
//无向边(x,y) 或 有向边<x,y>存在,则删除该边
void RemoveEdge(ALGraph &G, int x, int y) {
if (!isVertex(G, x) || !isVertex(G, y)) {
return;
}
ArcNode *p = G.vertices[x].first;
if (p == NULL) {
if (G.type == 0) {
printf("边/弧 %c%c不存在\n", G.vertices[x].data.value, G.vertices[y].data.value);
return;
}
} else {
if (p->adjvex == y) {//如果第一个结点是y
G.vertices[x].first = p->next;
free(p);
G.arcnum--;
} else {
while (p->next != NULL && p->next->adjvex != y) {
p = p->next;
}
if (p->next == NULL) {//没找到边
printf("边/弧 %c%c不存在\n", G.vertices[x].data.value, G.vertices[y].data.value);
return;
}
G.arcnum--;
ArcNode *s = p->next;
p->next = p->next->next;
free(s);
}
if (G.type == 0) {//如果删除的是无向图,这时候已经找到并删除了xy,这时候需要找到yx删除
ArcNode *q = G.vertices[y].first;//边一定存在
if (q->adjvex == x) {//第一个就是
G.vertices[y].first = q->next;
free(q);
} else {//不是第一个
while (q->next->adjvex != x) {
q = q->next;
}
ArcNode *s = q->next;
q->next = q->next->next;
free(s);
}
}
}
}
//求图G中顶点x的第一个邻接点,若有返回顶点号。若x没有邻接点或图中不存在x,返回-1
int FirstNeighbor(ALGraph G, int x) {
if (!isVertex(G, x)) return -1;
ArcNode *p = G.vertices[x].first;
if (p == NULL) {
if (G.type == 0) {
return -1;
}
} else {
return p->adjvex;
}
return -1;//找不到
}
//假设图G中顶点y是x的一个邻接点,返回除了y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,返回-1
int NextNeighbor(ALGraph G, int x, int y) {
if (!isVertex(G, x) || !isVertex(G, y)) {
return -1;
}
ArcNode *p = G.vertices[x].first;
bool yExist = false;
if (p == NULL) {
if (G.type == 0) {
return -1;
}
} else {
while (p != NULL && p->adjvex != y) {
p = p->next;
}
if (p == NULL || p->next == NULL) {//没找到y或者 y是出边最后一个顶点
if (G.type == 0) { // 如果是无向图
return -1;
}
if (p != NULL && p->next == NULL) {
//如果y是出边的最后一个结点
yExist = true;
}
} else {
return p->next->adjvex;
}
}
return -1;//没找到
}
//列出图G中与顶点x临界的边
void Neighbors(ALGraph G, int x) {
printf("与顶点%c临界的边有:", G.vertices[x].data.value);
if (!isVertex(G, x)) {
return;
}
ArcNode *p = G.vertices[x].first;
if (p == NULL) {
if (G.type == 0) {//如果是无向图
printf("不存在与顶点x临界的边\n");
return;
}
} else {
ArcNode *p = G.vertices[x].first;
while (p != NULL) {
printf("%c%c ", G.vertices[x].data.value, G.vertices[p->adjvex].data.value);
p = p->next;
}
}
if (G.type == 0) {
printf("\n");
return;
}
//如果是有向图,寻找x的所有入边
for (int i = 0; i < G.vexnum; ++i) {
ArcNode *q = G.vertices[i].first;
while (q != NULL) {
if (q->adjvex == x) {//找到了一条x的入边
printf("%c%c ", G.vertices[i].data.value, G.vertices[x].data.value);
}
q = q->next;
}
}
printf("\n");
}
//获取图G中边<x,y>或(x,y)对应的权值
int Get_edge_value(ALGraph G, int x, int y) {
if (!isVertex(G, x) || !isVertex(G, y)) {
return -1;
}
ArcNode *p = G.vertices[x].first;
while (p != NULL) {
if (p->adjvex == y) {
return p->weight;
}
p = p->next;
}
return -1;//没找到xy的边
}
//设置图G中边<x,y>或(x,y)对应的权值为v
void Set_edge_value(ALGraph &G, int x, int y, int v) {
if (!isVertex(G, x) || !isVertex(G, y)) {
return;
}
ArcNode *p = G.vertices[x].first;
while (p != NULL) {
if (p->adjvex == y) {
ArcNode &arc = *p;
arc.weight = v;
}
p = p->next;
}
if (G.type == 0) {
ArcNode *q = G.vertices[y].first;
while (q != NULL) {
if (q->adjvex == x) {
ArcNode &arc = *q;
q->weight = v;
}
q = q->next;
}
}
}
//访问顶点v
void visit(ALGraph G, int v) {
printf("%c ", G.vertices[v].data.value);
}
LinkQueue Q;//队列用于存放顺序访问的结点
int visited[MaxVertexNum];//存放每个结点的访问情况
//广度优先遍历
void BFS(ALGraph G, int v) { //从顶点 v 出发
visit(G, v);
visited[v] = true;
EnQueue(Q, v);
while (!QueueEmpty(Q)) {
int x;
DeQueue(Q, x);
int y = FirstNeighbor(G, x);//找到第一个邻接点
while (y != -1) {
if (!visited[y]) {//如果未被访问过
visited[y] = true;//访问该邻接点
visit(G, y);
EnQueue(Q, y);//入队
}
y = NextNeighbor(G, x, y);//访问下一个邻接点
}
}
}
void BFSTraverse(ALGraph G) {
printf("广度优先遍历序列: ");
for (int i = 0; i < G.vexnum; ++i) {
visited[i] = false;
}
InitQueue(Q);
for (int i = 0; i < G.vexnum; ++i) {
if (!visited[i]) { //如果当前结点没有被访问
BFS(G, i);
}
}
printf("\n");
}
//深度优先遍历
void DFS(ALGraph G, int v) {
visited[v] = true;
visit(G, v);
for (int w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)) {
if (!visited[w])
DFS(G, w);
}
}
void DFSTraverse(ALGraph G) {
printf("深度优先遍历序列: ");
for (int i = 0; i < G.vexnum; ++i) {
visited[i] = false;
}
for (int i = 0; i < G.vexnum; ++i) {
if (!visited[i]) { //非联通图无法一次访问完成
DFS(G, i);
}
}
printf("\n");
}
bool isJoin[MaxVertexNum];//标记各结点是否加入树
int lowCast[MaxVertexNum];//各结点加入树的最低代价
//Prim算法求最小代价生成树
void Prim(ALGraph G) {
printf("\nPrim算法求最小代价生成树: ");
isJoin[0] = true;//将第一个结点加入树
for (int i = 1; i < G.vexnum; ++i) {
isJoin[i] = false;
}
lowCast[0] = 0;
for (int j = 1; j < G.vexnum; ++j) {
int w = Get_edge_value(G, 0, j);//获取余该顶点关联的边/弧的权值
if (w != -1) {
lowCast[G.vertices[j].data.value] = w;
} else {
lowCast[G.vertices[j].data.value] = INFINITY;
}
}
int minWeight = -1, minIndex = -1;
while (true) {
minIndex = -1, minWeight = -1;//如果代价表中不存在未被访问的结点,则为minIndex未更新
for (int k = 0; k < G.vexnum; ++k) {
//获取代价表中未被访问结点到最小值
if (!isJoin[k] && lowCast[k] != INFINITY) {
if (minIndex == -1) {
minWeight = lowCast[k];
minIndex = k;
} else {
if (lowCast[k] < minWeight) {
minWeight = lowCast[k];
minIndex = k;
}
}
}
}
if (minIndex == -1)
break;
isJoin[minIndex] = true;//访问顶点
for (int j = 1; j < G.vexnum; ++j) {
if (!isJoin[j]) {//如果该顶点未加入生成树
int w = Get_edge_value(G, minIndex, j);//获取顶点相关的边的权值
if (w != -1) {//如果边存在
if (w < lowCast[j]) { //较小,则更新代价表
lowCast[j] = w;
}
}
}
}
}
int value = 0;
for (int i = 0; i < G.vexnum; ++i) {
value += lowCast[i];
}
printf("最小代价:%d", value);
printf("\n");
}
typedef struct {
int vertex1;
int vertex2;
int weight;
} WeightOrderEdge;//存储按照权值排序的边
typedef struct Node {
int data;
int parent;
} Node;
typedef struct {
Node sets[MaxVertexNum];
int n;
} UFSets;
//初始化集合
void InitUFSets(UFSets &S, int size) {
for (int i = 0; i < size; ++i) {
S.sets[i].data = {i};
S.sets[i].parent = -1;
}
S.n = size;
}
//查找某个元素的属于哪个集合
int Find(UFSets S, int i) {
if (S.sets[i].parent == -1)
return i;
while (S.sets[i].parent != -1) {
i = S.sets[i].parent;
}
return i;
}
//合并两个集合
void Union(UFSets &S, int index1, int index2) {
Node &root1 = S.sets[index1];
Node &root2 = S.sets[index2];
if (root1.parent >= 0 ||
root2.parent >= 0) {//不是集合
return;
}
root2.parent = index1;
}
//Kruskal算法求最小代价生成树
void Kruskal(ALGraph G) {
printf("\nKruskal算法求最小代价生成树: ");
WeightOrderEdge E[G.arcnum]; //存储按照权值排序的边信息
for (int i = 0; i < G.arcnum; ++i) {
E[i].weight = INFINITY;
E[i].vertex1 = -1;
E[i].vertex2 = -1;
}
int k = 0;
//将各条边按照权值排序
for (int i = 0; i < G.vexnum; ++i) {
for (int j = 0; j < G.vexnum; ++j) {
if (i <= j) {
int w = Get_edge_value(G, i, j);
if (w != -1) {
E[k].vertex1 = i;
E[k].vertex2 = j;
E[k].weight = w;
k++;
}
}
}
}
for (int i = 0; i < G.arcnum - 1; ++i) {
int min = i;
for (int j = i + 1; j < G.arcnum; ++j) {
if (E[j].weight < E[min].weight) {
min = j;
}
}
if (min != i) {
int minVertex1 = E[min].vertex1, minVertex2 = E[min].vertex2, minWeight = E[min].weight;
int iVertex1 = E[i].vertex1, iVertex2 = E[i].vertex2, iWeight = E[i].weight;
E[min].vertex1 = iVertex1;
E[min].vertex2 = iVertex2;
E[min].weight = iWeight;
E[i].vertex1 = minVertex1;
E[i].vertex2 = minVertex2;
E[i].weight = minWeight;
}
}
UFSets S;
InitUFSets(S, G.arcnum);//初始化集合
int value = 0;//统计最小代价(权值之和)
for (int i = 0; i < G.arcnum; ++i) {
//检查两个顶点是否属于同一集合
int vertex1 = E[i].vertex1;
int vertex2 = E[i].vertex2;
int set1 = Find(S, vertex1);
int set2 = Find(S, vertex2);
if (set1 == set2) {//说明已经联通
continue;
} else {//不是一个集合,合并
Union(S, set1, set2);
value += E[i].weight;
}
}
printf("最小代价:%d\n", value);
}
int d[MaxVertexNum];//路径长度
int path[MaxVertexNum];//路径从哪个顶点过来
//广度优先搜索算法求顶点 v 到其他顶点的最短路径 用于(无权图、权值为1的图)
void BFS_MIN_DISTANCE(ALGraph G, int v) { //从顶点 v 出发
printf("\nBFS求顶点 %d 到其他各顶点之间的最短路径: ", v);
for (int i = 0; i < G.vexnum; ++i) {
visited[i] = false;
}
InitQueue(Q);
for (int i = 0; i < G.vexnum; ++i) {
d[i] = INFINITY;
path[i] = -1;
}
d[v] = 0;//顶点v到顶点v的距离为0
visited[v] = true;
EnQueue(Q, v);
while (!QueueEmpty(Q)) {
int x;
DeQueue(Q, x);
int y = FirstNeighbor(G, x);//找到第一个邻接点
while (y != -1) {
if (!visited[y]) {//如果未被访问过
d[y] = d[x] + 1;//路径长度 +1
path[y] = x;//最短路径应从x到y
visited[y] = true;//访问该邻接点
EnQueue(Q, y);//入队
}
y = NextNeighbor(G, x, y);//访问下一个邻接点
}
}
printf("\n");
}
bool final[MaxVertexNum];//标记各个顶点是否已找到最短路径
int dist[MaxVertexNum];//最短路径长度
//int path[MaxVertexNum];//路径上的直接前驱
//Dijkstra求单源点最短路径问题(带权图、无权图) 不适合带负权值的图
void Dijkstra(ALGraph G, int v) {
printf("\nDijkstra算法求顶点 %d 到其他各顶点之间的最短路径: ", v);
for (int i = 0; i < G.vexnum; ++i) {
final[i] = false;//标记其他结点还没有找到最短路径
dist[i] = INFINITY;
path[i] = -1;
}
path[v] = -1;
dist[v] = 0;
final[v] = true;
for (int j = 0; j < G.vexnum; ++j) {
if (j != v) {
int w = Get_edge_value(G, v, j);
if (w != -1) {
dist[j] = w;
path[j] = v;
}
}
}
int min;
while (true) {
min = -1;
for (int i = 0; i < G.vexnum; ++i) {
if (!final[i]) {
if (min == -1) {
min = i;
} else {
if (dist[i] < dist[min]) {
min = i;
}
}
}
}
if (min == -1) {
break;
}
final[min] = true;
for (int j = 0; j < G.vexnum; ++j) {
if (!final[j]) {
int w = Get_edge_value(G, min, j);
if (w != -1) {
int d = w + dist[min];
if (d < dist[j]) {
dist[j] = d;
path[j] = min;
}
}
}
}
}
printf("\n");
}
int paths[MaxVertexNum][MaxVertexNum];//各个顶点之间的中转点
int A[MaxVertexNum][MaxVertexNum];//各个顶点之间的最短路径长度
LinkStack S;
void getPaths(ALGraph G, int i, int j) {
if (paths[i][j] == -1) {
printf("->%d", j);
return;
}
if (A[i][j] != INFINITY) {
int k = paths[i][j];
getPaths(G, i, k);
getPaths(G, k, j);
}
}
// Floyd 算法求各顶点之间的最短路径
void Floyd(ALGraph G) {
printf("Floyd算法求各顶点之间的最短路径:\n");
//初始化
for (int i = 0; i < G.vexnum; ++i) {
for (int j = 0; j < G.vexnum; ++j) {
paths[i][j] = -1;
if (i == j) {
A[i][j] = 0;
continue;
}
int w = Get_edge_value(G, i, j);
if (w != -1) {
A[i][j] = w;
} else {
A[i][j] = INFINITY;
}
}
}
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 (A[i][k] == INFINITY || A[k][j] == INFINITY) {
continue;
}
if (A[i][j] > A[i][k] + A[k][j]) {
A[i][j] = A[i][k] + A[k][j];
paths[i][j] = k;
}
}
}
}
InitStack(S);
for (int i = 0; i < G.vexnum; ++i) {
printf("顶点%d到其他顶点 最短路径: \n", G.vertices[i].data.value);
for (int j = 0; j < G.vexnum; ++j) {
if (A[i][j] != INFINITY) {
printf("%d到%d: ", i, j);
printf("%d", i);
getPaths(G, i, j);
printf("\n");
}
}
}
printf("\n");
}
int indegree[MaxVertexNum];//记录当前顶点入度
int print[MaxVertexNum];//记录拓扑序列
//拓扑排序
bool TopologicalSort(ALGraph G) {
//初始化
for (int i = 0; i < G.vexnum; ++i) {
indegree[i] = 0;
}
//获取每个顶点的入度
for (int i = 0; i < G.vexnum; ++i) {
for (int j = 0; j < G.vexnum; ++j) {
if (Adjacent(G, i, j)) {
indegree[j]++;
}
}
}
InitStack(S);
for (int i = 0; i < G.vexnum; ++i) {
if (indegree[i] == 0) {//将所有入度为0的顶点进栈
Push(S, i);
}
}
int v;
int count = 0;//记录当前输出的顶点
while (!StackEmpty(S)) {
Pop(S, v);
print[count++] = v;
//检查入度为当前顶点的顶点
for (int i = 0; i < G.vexnum; ++i) {
if (Adjacent(G, v, i)) {
//检查入度为当前顶点的顶点
if (--indegree[i] == 0) {
Push(S, i);
}
}
}
}
if (count < G.vexnum) {
return false;//拓扑排序失败,有向图中存在回路
} else {
return true;
}
}
int outdegree[MaxVertexNum];//记录当前结点的出度
//逆拓扑排序实现
bool ReverseTopologicalSort(ALGraph G) {
//初始化
for (int i = 0; i < G.vexnum; ++i) {
outdegree[i] = 0;
}
//获取每个顶点的出度
for (int i = 0; i < G.vexnum; ++i) {
for (int j = 0; j < G.vexnum; ++j) {
if (Adjacent(G, i, j)) {
outdegree[i]++;
}
}
}
InitStack(S);
for (int i = 0; i < G.vexnum; ++i) {
if (outdegree[i] == 0) {//将所有出度为0的顶点进栈
Push(S, i);
}
}
int v;
int count = 0;//记录当前输出的顶点
while (!StackEmpty(S)) {
Pop(S, v);
print[count++] = v;
//检查出度为当前顶点的顶点
for (int i = 0; i < G.vexnum; ++i) {
if (Adjacent(G, i, v)) {
if(--outdegree[i]==0) {
Push(S,i);
}
}
}
}
if (count < G.vexnum) {
return false;//逆拓扑排序失败,有向图中存在回路
} else {
return true;
}
}
//深度优先遍历
void DFSTopo(ALGraph G, int v) {
visited[v] = true;
// visit(G, v);
for (int w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)) {
if (!visited[w])
DFSTopo(G, w);
}
printf("%d ",v);
}
void DFSTraverseTopo(ALGraph G) {
printf("使用深度优先遍历算法得到逆拓扑序列: \n");
for (int i = 0; i < G.vexnum; ++i) {
visited[i] = false;
}
for (int i = 0; i < G.vexnum; ++i) {
if (!visited[i]) { //非联通图无法一次访问完成
DFSTopo(G, i);
}
}
printf("\n");
}
int main() {
setbuf(stdout, NULL);
//测试 图的基本操作
ALGraph G;
int type = 0;
InitALGraph(G, type);
// InsertVertex(G, 'G');
InsertVertex(G, 'B');
InsertVertex(G, 'C');
InsertVertex(G, 'D');
InsertVertex(G, 'E');
InsertVertex(G, 'F');
AddEdge(G, 0, 1);//A-B
AddEdge(G, 0, 2);//A-C
AddEdge(G, 0, 3);//A-D
// AddEdge(G, 1, 4);//B-E
AddEdge(G, 1, 5);//B-F
AddEdge(G, 2, 4);//C-E
AddEdge(G, 3, 5);//D-F
BFSTraverse(G);
DFSTraverse(G);
int x, y;
x = 0, y = 1;
for (int i = 0; i < G.vexnum; ++i) {
x = i;
if (type == 0) {
printf("顶点%c存在的边: ", G.vertices[x].data.value);
} else {
printf("顶点%c存在的弧: ", G.vertices[x].data.value);
}
for (int j = 0; j < 6; ++j) {
y = j;
if (Adjacent(G, x, y)) {
printf("%c%c ", G.vertices[x].data.value, G.vertices[y].data.value);
}
}
printf("\n");
}
for (int i = 0; i < G.vexnum; ++i) {
x = i;
y = FirstNeighbor(G, x);
if (y != -1) {
printf("顶点%c的邻接点有: %c ", G.vertices[x].data.value, G.vertices[y].data.value);
y = (NextNeighbor(G, x, y));
while (y != -1) {
printf("%c ", G.vertices[y].data.value);
y = (NextNeighbor(G, x, y));
}
printf("\n");
} else {
printf("顶点%c不存在或没有邻接点\n", G.vertices[x]);
}
}
for (int i = 0; i < 6; ++i) {
Neighbors(G, i);
}
x = 0, y = 1;
int v = 12;
Set_edge_value(G, x, y, v);
for (int i = 0; i < G.vexnum; ++i) {
x = i;
printf("与顶点%c相邻的边的权值: ", G.vertices[x].data.value);
for (int j = 0; j < 6; ++j) {
y = j;
int w = Get_edge_value(G, x, y);
if (w != -1) {
printf("%c%c: %d ", G.vertices[x].data.value, G.vertices[y].data.value, w);
}
}
printf("\n");
}
// RemoveEdge(G, 0, 3);//删除边AD
// printf("删除边/弧 AD\n");
// printf("删除边/弧 AD\n");
// RemoveEdge(G, 0, 3);//删除边AD
// printf("删除边/弧 AB\n");
// RemoveEdge(G, 0, 1);//删除边AB
//
// printf("删除边/弧 AC\n");
// RemoveEdge(G, 0, 2);//删除边AC
// DeleteVertex(G,1);
//测试 广度优先搜索算法 求无权图单源点最短路径
InitStack(S);
for (int i = 0; i < G.vexnum; ++i) {
BFS_MIN_DISTANCE(G, i);
printf("顶点%c到其他顶点 最短路径: \n", G.vertices[i]);
for (int j = 0; j < G.vexnum; ++j) {
int k = path[j];
printf("%c到%c: %d ", G.vertices[i].data.value, G.vertices[j].data.value, d[j]);
while (k != -1) {
Push(S, G.vertices[k].data.value);
k = path[k];
}
while (!StackEmpty(S)) {
int e;
Pop(S, e);
printf("%c->", e);
}
printf("%c\n", G.vertices[j].data.value);
}
printf("\n");
}
//测试 求最小代价生成树 Prim 算法 和 Kruskal 算法
InitALGraph(G, type);
// InsertVertex(G,'0');
G.vertices[0].data.value = 0;
InsertVertex(G, 1);
InsertVertex(G, 2);
InsertVertex(G, 3);
InsertVertex(G, 4);
InsertVertex(G, 5);
// InsertVertex(G,6);
AddEdge(G, 0, 1);
Set_edge_value(G, 0, 1, 6);
AddEdge(G, 0, 2);
Set_edge_value(G, 0, 2, 5);
AddEdge(G, 0, 3);
Set_edge_value(G, 0, 3, 1);
AddEdge(G, 1, 3);
Set_edge_value(G, 1, 3, 5);
AddEdge(G, 1, 4);
Set_edge_value(G, 1, 4, 3);
AddEdge(G, 2, 3);
Set_edge_value(G, 2, 3, 4);
AddEdge(G, 2, 5);
Set_edge_value(G, 2, 5, 2);
AddEdge(G, 3, 4);
Set_edge_value(G, 3, 4, 6);
AddEdge(G, 3, 5);
Set_edge_value(G, 3, 5, 4);
AddEdge(G, 4, 5);
Set_edge_value(G, 4, 5, 6);
for (int i = 0; i < 6; ++i) {
x = i;
printf("与顶点%d相邻的边的权值: ", G.vertices[x].data.value);
for (int j = 0; j < 6; ++j) {
y = j;
int w = Get_edge_value(G, x, y);
if (w != -1) {
printf("%d%d: %d ", G.vertices[x].data.value, G.vertices[y].data.value, w);
}
}
printf("\n");
}
Prim(G);
Kruskal(G);
//测试 Dijkstra算法
type = 1;
InitALGraph(G, type);
G.vertices[0].data.value = 0;
InsertVertex(G, 1);
InsertVertex(G, 2);
InsertVertex(G, 3);
InsertVertex(G, 4);
AddEdge(G, 0, 1);
Set_edge_value(G, 0, 1, 10);
AddEdge(G, 0, 4);
Set_edge_value(G, 0, 4, 5);
AddEdge(G, 1, 2);
Set_edge_value(G, 1, 2, 1);
AddEdge(G, 1, 4);
Set_edge_value(G, 1, 4, 2);
AddEdge(G, 2, 3);
Set_edge_value(G, 2, 3, 4);
AddEdge(G, 3, 0);
Set_edge_value(G, 3, 0, 7);
AddEdge(G, 3, 2);
Set_edge_value(G, 3, 2, 6);
AddEdge(G, 4, 1);
Set_edge_value(G, 4, 1, 3);
AddEdge(G, 4, 2);
Set_edge_value(G, 4, 2, 9);
AddEdge(G, 4, 3);
Set_edge_value(G, 4, 3, 2);
for (int i = 0; i < G.vexnum; ++i) {
Dijkstra(G, i);
printf("顶点%d到其他顶点 最短路径: \n", G.vertices[i].data.value);
for (int j = 0; j < G.vexnum; ++j) {
int k = path[j];
printf("%d到%d: %d ", G.vertices[i].data.value, G.vertices[j].data.value, dist[j]);
while (k != -1) {
Push(S, G.vertices[k].data.value);
k = path[k];
}
while (!StackEmpty(S)) {
int e;
Pop(S, e);
printf("%d->", e);
}
printf("%d\n", G.vertices[j].data.value);
}
printf("\n");
}
//测试 Floyd 算法求各顶点之间的最短路径
//
// //测试 三个顶点
// InitALGraph(G, type);
// G.vertices[0].data.value = 0;
//
// InsertVertex(G, 1);
// InsertVertex(G, 2);
//
// AddEdge(G,0,1);
// Set_edge_value(G,0,1,6);
//
// AddEdge(G,1,0);
// Set_edge_value(G,1,0,10);
//
// AddEdge(G,0,2);
// Set_edge_value(G,0,2,13);
// AddEdge(G,2,0);
// Set_edge_value(G,2,0,5);
//
// AddEdge(G,1,2);
// Set_edge_value(G,1,2,4);
//
// Floyd(G);
//测试 五个顶点
type = 1;
InitALGraph(G, type);
G.vertices[0].data.value = 0;
InsertVertex(G, 1);
InsertVertex(G, 2);
InsertVertex(G, 3);
InsertVertex(G, 4);
AddEdge(G, 0, 2);
Set_edge_value(G, 0, 2, 1);
AddEdge(G, 0, 4);
Set_edge_value(G, 0, 4, 10);
AddEdge(G, 1, 3);
Set_edge_value(G, 1, 3, 1);
AddEdge(G, 1, 4);
Set_edge_value(G, 1, 4, 5);
AddEdge(G, 2, 1);
Set_edge_value(G, 2, 1, 1);
AddEdge(G, 2, 4);
Set_edge_value(G, 2, 4, 7);
AddEdge(G, 3, 4);
Set_edge_value(G, 3, 4, 1);
Floyd(G);
InitALGraph(G, type);
G.vertices[0].data.value = 0;
InsertVertex(G, 1);
InsertVertex(G, 2);
InsertVertex(G, 3);
InsertVertex(G, 4);
AddEdge(G, 0, 1);
AddEdge(G, 1, 3);
AddEdge(G, 3, 4);
AddEdge(G, 2, 3);
AddEdge(G, 2, 4);
// AddEdge(G, 4, 2);
if (TopologicalSort(G)) {
printf("拓扑排序成功,拓扑序列为:\n");
for (int i = 0; i < G.vexnum; ++i) {
printf("%d ", print[i]);
}
printf("\n");
} else {
printf("拓扑排序失败\n");
}
if (ReverseTopologicalSort(G)) {
printf("逆拓扑排序成功,逆拓扑序列为:\n");
for (int i = 0; i < G.vexnum; ++i) {
printf("%d ", print[i]);
}
printf("\n");
} else {
printf("逆拓扑排序失败\n");
}
DFSTraverseTopo(G);
return 0;
}
数据结构复习:图的基本操作、应用(邻接表实现)
最新推荐文章于 2023-11-21 16:03:10 发布