前言
总结整理不易,希望大家点赞收藏。
给大家整理了一下数据结构与算法中图的全部代码,以供大家期末复习和考研复习的时候使用。
参考资料是耿国华的数据结构与算法。
即插即用
邻接表
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<stack>
#include<queue>
#define MAX 20
#define INFINITY 65535//代表正无穷
typedef char VertexData;//顶点数据类型
typedef int EdgeData;//带权图上的权值数据类型
typedef int MatrixAdjType;
using namespace std;
//图的存储结构//邻接表法
typedef struct ArcNode {//弧节点int adjvex;//该弧指向的顶点位置struct ArcNode* nextarc;//指向下一个弧的指针//EDGETYPE info;//权值int weight;
}ArcNode;
typedef struct VertexNode {VertexData data;//顶点数据ArcNode* firstarc;//指向该顶点的第一条弧的指针
}VertexNode;
typedef struct {VertexNode vertexlist[MAX];int vexnum, arcnum;
}AdjList;//求顶点位置函数
int LocateVertex(AdjList* G, VertexData v) {for (int i = 0; i < G->vexnum; i++) {if (G->vertexlist[i].data == v) {return i;}}
}
//创建邻接表
void CreateAdjList(AdjList* g) {int i, j, k, weight;char vi, vj;printf("请输入顶点数和边数:\n");scanf("%d,%d", &g->vexnum, &g->arcnum);for (i = 0; i < g->vexnum; i++) {g->vertexlist[i].data = 'A' + i;g->vertexlist[i].firstarc = NULL;}printf("请输入弧的起点,终点和权值:\n");for (k = 0; k < g->arcnum; k++) {scanf(" %c ,%c,%d", &vi, &vj, &weight);ArcNode* p = (ArcNode*)malloc(sizeof(ArcNode));p->adjvex = LocateVertex(g, vj);p->weight = weight;ArcNode* tmp = g->vertexlist[LocateVertex(g, vi)].firstarc;if (tmp == NULL) {g->vertexlist[LocateVertex(g, vi)].firstarc = p;p->nextarc = NULL;}else {while (tmp->nextarc != NULL) {tmp = tmp->nextarc;}p->nextarc = tmp->nextarc;tmp->nextarc = p;}//无向图有
#if 1ArcNode* s = (ArcNode*)malloc(sizeof(ArcNode));s->adjvex = LocateVertex(g, vi);s->weight = weight;ArcNode* tmp2 = g->vertexlist[LocateVertex(g, vj)].firstarc;if (tmp2 == NULL) {s->nextarc = g->vertexlist[LocateVertex(g, vj)].firstarc;g->vertexlist[LocateVertex(g, vj)].firstarc = s;}else {while (tmp2->nextarc != NULL) {tmp2 = tmp2->nextarc;}s->nextarc = tmp2->nextarc;tmp2->nextarc = s;}
#endif}
}
/*深度优先遍历递归通式
//深度优先遍历v0所在子图
void DepthFirstSearch(Graph g, int v0) {visit(v0);visited[v0] = 1;int w = FirstAdjVertex(g, v0);while (w != -1) {if (!visited[w]) {DepthFirstSearch(g, w);w = NextAdjVertex(g, v0, w);}}
}
//深度优先遍历图
int visited[MAX];
void TraverseGraph(Graph g) {for (int vi = 0; vi < g.vexnum; vi++) {visited[vi] = 0;}for (int vi = 0; vi < g.vexnum; vi++) {if (!visited[vi]) {DepthFirstSearch(g, vi);}}
}
*///邻接表递归实现DFS
int visited[MAX];
void DepthFirstSearch(AdjList g, int v0) {printf("%c ", g.vertexlist[v0].data);visited[v0] = 1;ArcNode* p = g.vertexlist[v0].firstarc;/*while (p != NULL) {if (!visited[p->adjvex]) {DepthFirstSearch(g, p->adjvex);}p = p->nextarc;}*/for (p; p != NULL; p = p->nextarc) {if (!visited[p->adjvex]) {DepthFirstSearch(g, p->adjvex);}}
}
void TraverseGraph(AdjList g) {for (int vi = 0; vi < g.vexnum; vi++) {visited[vi] = 0;}for (int vi = 0; vi < g.vexnum; vi++) {if (!visited[vi]) {DepthFirstSearch(g, vi);}}
}//邻接表非递归实现DFS
void NoReDepthFirstSearch(AdjList g, int v0) {printf("%c ", g.vertexlist[v0].data);//visit(v0);visited[v0] = 1;stack<int>S;S.push(v0);while (!S.empty()) {int top = S.top();ArcNode* p = g.vertexlist[top].firstarc;/*while (p != NULL) {if (!visited[p->adjvex]) {printf("%c ", g.vertexlist[p->adjvex].data);//visit(p->adjvex);visited[p->adjvex] = 1;S.push(p->adjvex);p = p->nextarc;break;}p = p->nextarc;}*/for (p; p != NULL; p = p->nextarc) {if (!visited[p->adjvex]) {printf("%c ", g.vertexlist[p->adjvex].data);//visit(p->adjvex);visited[p->adjvex] = 1;S.push(p->adjvex);break;}}if (p == NULL) {S.pop();}}
}
void NoReTraverseGraph(AdjList g) {for (int vi = 0; vi < g.vexnum; vi++) {visited[vi] = 0;}for (int vi = 0; vi < g.vexnum; vi++) {if (!visited[vi]) {NoReDepthFirstSearch(g, vi);}}
}//邻接表非递归实现BFS
void NoReBroadFirstSearch(AdjList g, int v) {printf("%c ", g.vertexlist[v].data);visited[v] = 1;queue<int>Q;Q.push(v);while (!Q.empty()) {int front = Q.front();ArcNode* p = g.vertexlist[front].firstarc;for (p; p != NULL; p = p->nextarc) {if (!visited[p->adjvex]) {printf("%c ", g.vertexlist[p->adjvex].data);visited[p->adjvex] = 1;Q.push(p->adjvex);}}if (p == NULL) {Q.pop();}}
}
void NoReTraverseGrap(AdjList g) {for (int vi = 0; vi < g.vexnum; vi++) {visited[vi] = 0;}for (int vi = 0; vi < g.vexnum; vi++) {if (!visited[vi]) {NoReBroadFirstSearch(g, vi);}}
}//深度优先找出顶点u和顶点v的简单路径
void FindPath(AdjList g, int vi, int vj, int* path, int d) {visited[vi] = 1;d++;path[d] = vi;if (vi == vj) {int i;for (i = 0; i <= d; i++) {printf("%c ", g.vertexlist[path[i]].data);if (i != 0) {visited[path[i]] = 0;}}printf("\n");return;}ArcNode* p = g.vertexlist[vi].firstarc;while (p != NULL) {for (int len = d; len >= 0; len--) {visited[path[len]] = 1;}if (!visited[p->adjvex]) {FindPath(g, p->adjvex, vj, path, d);}p = p->nextarc;}if (p == NULL) {visited[vi] = 0;d--;}
}//计算入度
void CountIndegree(AdjList g, int* indegree, ArcNode* p) {for (p; p != NULL; p = p->nextarc) {indegree[p->adjvex]++;}return;
}//拓扑排序
bool TopoSort(AdjList g, int* indegree) {for (int i = 0; i < g.vexnum; i++) {indegree[i] = 0;}for (int i = 0; i < g.vexnum; i++) {ArcNode* p = g.vertexlist[i].firstarc;for (p; p != NULL; p = p->nextarc) {indegree[p->adjvex]++;}}stack<int>S;for (int i = 0; i < g.vexnum; i++) {if (indegree[i] == 0) {S.push(i);}}int count = 0;while (!S.empty()) {int top = S.top();printf("%c ", g.vertexlist[top].data);S.pop();count++;ArcNode* p = g.vertexlist[top].firstarc;for (p; p != NULL; p = p->nextarc) {int i = p->adjvex;if (--indegree[i] == 0) {S.push(i);}}}if (count == g.vexnum) {return true;}return false;
}//单源最短路径-迪杰斯特拉算法(带权值)
void ShortestPath(AdjList g, int vi, int* path, int* dist) {int* final = (int*)malloc(sizeof(int) * g.vexnum);for (int i = 0; i < g.vexnum; i++) {path[i] = -1;final[i] = 0;dist[i] = INFINITY;}ArcNode* p = g.vertexlist[vi].firstarc;for (p; p != NULL; p = p->nextarc) {dist[p->adjvex] = p->weight;path[p->adjvex] = vi;}dist[vi] = 0;final[vi] = 1;int k = 0;for (int v = 0; v < g.vexnum - 1; v++) {int min = INFINITY;for (int w = 0; w < g.vexnum; w++) {if (!final[w] && dist[w] < min) {k = w;min = dist[w];}}final[k] = 1;ArcNode* p = g.vertexlist[k].firstarc;for (p; p != NULL; p = p->nextarc) {if (!final[p->adjvex] && (p->weight + min) < dist[p->adjvex]) {dist[p->adjvex] = min + p->weight;path[p->adjvex] = k;}}}for (int i = 0; i < g.vexnum; i++) {if (i != vi) {printf("%c到%c的最短距离为:%d\n", g.vertexlist[vi].data, g.vertexlist[i].data, dist[i]);}}free(final);
}//BFS算法求单源最短路径(不带权值)
void BFS_MIN_Distance(AdjList g, int v) {int* dist = (int*)malloc(sizeof(int) * g.vexnum);for (int i = 0; i < g.vexnum; i++) {visited[i] = 0;}for (int i = 0; i < g.vexnum; i++) {dist[i] = -1;}visited[v] = 1;dist[v] = 0;queue<int>Q;Q.push(v);while (!Q.empty()) {int front = Q.front();ArcNode* p = g.vertexlist[front].firstarc;for (p; p != NULL; p = p->nextarc) {if (!visited[p->adjvex]) {visited[p->adjvex] = 1;dist[p->adjvex] = dist[front] + 1;Q.push(p->adjvex);}}if (p == NULL) {Q.pop();}}for (int i = 0; i < g.vexnum; i++) {if (i != v) {if (dist[i] != -1) {printf("%c到%c的最短路径为%d\n", g.vertexlist[v].data, g.vertexlist[i].data, dist[i]);}}}
}//求距离顶点v0的最短路径长度为K的所有顶点
void FindNodeSetLenPath(AdjList g, int v0, int len) {queue<int>QNode;queue<int>QLevel;for (int i = 0; i < g.vexnum; i++) {visited[i] = 0;}visited[v0] = 1;int level = 0;QNode.push(v0);QLevel.push(level);while (!QNode.empty() && level <= len) {int curnode = QNode.front();level = QLevel.front();if (level == len) {while (!QNode.empty()) {int front = QNode.front();printf("%c ", g.vertexlist[front].data);QNode.pop();}return;}QNode.pop();QLevel.pop();ArcNode* p = g.vertexlist[curnode].firstarc;for (p; p != NULL; p = p->nextarc) {if (!visited[p->adjvex]) {visited[p->adjvex] = 1;QNode.push(p->adjvex);QLevel.push(level + 1);}}}
}void test() {AdjList G;CreateAdjList(&G);printf("递归DFS\n");TraverseGraph(G);printf("\n");printf("非递归DFS\n");NoReTraverseGraph(G);printf("\n");printf("非递归BFS\n");NoReTraverseGrap(G);printf("\n");//输出所有路径
#if 0int* path = (int*)malloc(sizeof(int) * G.vexnum);printf("输入要查询的两个节点,英文逗号隔开\n");char ci, cj;scanf(" %c, %c", &ci, &cj);int vi = LocateVertex(&G, ci);int vj = LocateVertex(&G, cj);for (int i = 0; i < MAX; i++) {visited[i] = 0;}FindPath(G, vi, vj, path, -1);free(path);printf("\n");
#endif//拓朴排序
#if 1//计算入度int* indegree = (int*)malloc(sizeof(int) * G.vexnum);//打印入度for (int i = 0; i < G.vexnum; i++) {indegree[i] = 0;}for (int i = 0; i < G.vexnum; i++) {ArcNode* p = G.vertexlist[i].firstarc;CountIndegree(G, indegree, p);}for (int i = 0; i < G.vexnum; i++) {printf("%c 的入度是 %d\n", G.vertexlist[i].data, indegree[i]);}int ret = TopoSort(G, indegree);printf("\n");if (ret == 1) {printf("拓扑排序成功,为有向无环图\n");}else {printf("拓扑排序失败,图中有环\n");}
#endif//最短路径
#if 0int* path = (int*)malloc(sizeof(G.vexnum));int* dist = (int*)malloc(sizeof(G.vexnum));printf("输入要查询的节点的最短路径\n");char c;scanf(" %c", &c);printf("=======================迪杰斯特拉最短路径算法=====================\n");int vi = LocateVertex(&G, c);ShortestPath(G, 0, path, dist);printf("================================================================\n");
#endif//BFS最短路径
#if 0printf("输入要查询的节点的最短路径\n");char c1;scanf(" %c", &c1);printf("=======================BFS最短路径最短路径算法=====================\n");int vi1 = LocateVertex(&G, c1);BFS_MIN_Distance(G, vi1);printf("================================================================\n");
#endif//求指定距离的所有顶点
#if 0char SetNode = 0;int Setlen = 0;printf("输入起点和距离\n");scanf(" %c", &SetNode);scanf("%d", &Setlen);int SetnodeNum = LocateVertex(&G, SetNode);FindNodeSetLenPath(G, SetnodeNum, Setlen);
#endifreturn;
}int main() {test();return 0;
}
邻接矩阵
这里只放出简单算法,其他的算法参照邻接表,邻接表是重点
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>
#include<stdlib.h>
#include<stack>
#include<queue>#define MAX 20
#define ZHENGWUQIONG 65535//代表正无穷
#define INFINITY 65535
using namespace std;//邻接矩阵存储结构
typedef char VertexData;//顶点数据类型
typedef int AdjType;//无向图中1/0表示是否相邻,有向图中表示权值
typedef struct ArcNode {AdjType adj;
}ArcNode;
typedef struct {VertexData vertex[MAX];//顶点表ArcNode arcs[MAX][MAX];//边表int vexnum, arcnum;
}AdjMatrix;//求顶点位置函数
int LocateVertex(AdjMatrix* G, VertexData v) {int j, k;for (k = 0; k < G->vexnum; k++) {if (G->vertex[k] == v) {j = k;break;}}return j;
}//建立网图的邻接矩阵表示
void CreateAdjMatrix(AdjMatrix* G) {int i, j, k, weight;VertexData v1, v2;printf("输入顶点数和边数\n");scanf("%d,%d", &G->vexnum, &G->arcnum);//G->vexnum = 8;//G->arcnum = 9;//对边表初始化for (i = 0; i < G->vexnum; i++) {for (j = 0; j < G->vexnum; j++) {G->arcs[i][j].adj = ZHENGWUQIONG;}}//输入顶点表for (i = 0; i < G->vexnum; i++) {G->vertex[i] = 'A' + i;}printf("输入边表及其权值\n");for (k = 0; k < G->arcnum; k++) {scanf(" %c, %c,%d", &v1, &v2, &weight);i = LocateVertex(G, v1);j = LocateVertex(G, v2);G->arcs[i][j].adj = weight;//加上下面这行这就创建无向图。G->arcs[j][i].adj = G->arcs[i][j].adj;}
}int visited[MAX];
//邻接矩阵递归实现DFS
void DepthFirstSearch(AdjMatrix g, int v0) {printf("%c ", g.vertex[v0]);//visit(v0);visited[v0] = 1;for (int vj = 0; vj < g.vexnum; vj++) {if (!visited[vj] && g.arcs[v0][vj].adj != ZHENGWUQIONG) {DepthFirstSearch(g, vj);}}
}
void TraverseGraph(AdjMatrix g) {for (int vi = 0; vi < g.vexnum; vi++) {visited[vi] = 0;}for (int vi = 0; vi < g.vexnum; vi++) {if (!visited[vi]) {DepthFirstSearch(g, vi);}}
}//邻接矩阵非递归实现DFS
void NoReDepthFirstSearch(AdjMatrix g, int v0) {printf("%c ", g.vertex[v0]);//visit(v0);visited[v0] = 1;stack<int>S;S.push(v0);while (!S.empty()) {int top = S.top();int w = 0;for (w = 0; w < g.vexnum; w++) {if (!visited[w] && g.arcs[top][w].adj != ZHENGWUQIONG) {printf("%c ", g.vertex[w]);//visit(w);visited[w] = 1;S.push(w);break;}}if (w == g.vexnum) {S.pop();}}
}
void NoReTraverseGraph(AdjMatrix g) {for (int vi = 0; vi < g.vexnum; vi++) {visited[vi] = 0;}for (int vi = 0; vi < g.vexnum; vi++) {if (!visited[vi]) {NoReDepthFirstSearch(g, vi);}}
}//邻接矩阵非递归实现BFS
void NoReBroadFirstSearch(AdjMatrix g, int v) {printf("%c ", g.vertex[v]);visited[v] = 1;queue<int>Q;Q.push(v);while (!Q.empty()) {int front = Q.front();int i;for (i = 0; i < g.vexnum; i++) {if (!visited[i] && g.arcs[front][i].adj != ZHENGWUQIONG) {printf("%c ", g.vertex[i]);visited[i] = 1;Q.push(i);}}if (i == g.vexnum) {Q.pop();}}
}
void NoReTraverseGrap(AdjMatrix g) {for (int vi = 0; vi < g.vexnum; vi++) {visited[vi] = 0;}for (int vi = 0; vi < g.vexnum; vi++) {if (!visited[vi]) {NoReBroadFirstSearch(g, vi);}}
}//深度优先找出顶点u和顶点v的简单路径
void FindPath(AdjMatrix g, int vi, int vj, int* path, int d) {//d为栈顶元素下标初始为-1;int i;++d;//把vi放到path数组中path[d] = vi;//设置vi为已访问visited[vi] = 1;//如果找到vjif (vi == vj) {int len = d;//弹空path数组for (int j = 0; j <= len; j++) {printf("%c ", g.vertex[path[j]]);if (j != 0) {visited[path[j]] = 0;}}printf("\n");}for (i = 0; i < g.vexnum; i++) {for (int len = d; len >= 0; len--) {visited[path[len]] = 1;}if (!visited[i] && g.arcs[vi][i].adj != ZHENGWUQIONG) {FindPath(g, i, vj, path, d);}}//如果循环完了还没找到就退栈并且设置没访问过。等于走了个死胡同然后退出。if (i == g.vexnum) {visited[vi] = 0;}
}//优化版本
void FindPath2(AdjMatrix g, int vi, int vj, int* path, int d) {//d为栈顶元素下标初始为-1;int i;++d;//把vi放到path数组中path[d] = vi;//设置vi为已访问visited[vi] = 1;//如果找到vjif (vi == vj) {int len = d;//弹空path数组for (int j = 0; j <= len; j++) {printf("%c ", g.vertex[path[j]]);if (j != 0) {visited[path[j]] = 0;}}printf("\n");}for (i = 0; i < g.vexnum; i++) {for (int len = d; len >= 0; len--) {visited[path[len]] = 1;}if (!visited[i] && g.arcs[vi][i].adj != ZHENGWUQIONG) {FindPath(g, i, vj, path, d);}}//如果循环完了还没找到就退栈并且设置没访问过。等于走了个死胡同然后退出。if (i == g.vexnum) {visited[vi] = 0;}
}//普利姆算法(加点法)
struct {int adjvex;int lowcost;
}closedge[MAX];
void PrimMiniSpanTree(AdjMatrix g, int v0) {closedge[v0].lowcost = 0;for (int i = 0; i < g.vexnum; i++) {if (i != v0) {closedge[i].adjvex = v0;closedge[i].lowcost = g.arcs[v0][i].adj;}}for (int i = 0; i < g.vexnum - 1; i++) {int mindist = INFINITY;int minnode = 0;for (int j = 0; j < g.vexnum; j++) {if (closedge[j].lowcost != 0 && closedge[j].lowcost < mindist) {mindist = closedge[j].lowcost;minnode = j;}}printf("(%c,%c) ", g.vertex[closedge[minnode].adjvex], g.vertex[minnode]);closedge[minnode].lowcost = 0;for (int j = 0; j < g.vexnum; j++) {if (closedge[j].lowcost != 0 && g.arcs[minnode][j].adj < closedge[j].lowcost) {closedge[j].lowcost = g.arcs[minnode][j].adj;closedge[j].adjvex = minnode;}}}
}void test() {AdjMatrix G;CreateAdjMatrix(&G);//深度优先遍历printf("深度优先遍历:\n");printf("递归:\n");TraverseGraph(G);printf("\n");printf("非递归:\n");NoReTraverseGraph(G);printf("\n");//广度优先遍历printf("广度优先遍历:\n");NoReTraverseGrap(G);printf("\n");int* path = (int*)malloc(sizeof(int) * G.vexnum);printf("输入要查询的两个节点,英文逗号隔开\n");char ci, cj;scanf(" %c, %c", &ci, &cj);int vi = LocateVertex(&G, ci);int vj = LocateVertex(&G, cj);for (int i = 0; i < MAX; i++) {visited[i] = 0;}FindPath(G, vi, vj, path, -1);free(path);
}
void test01() {AdjMatrix G;CreateAdjMatrix(&G);//深度优先遍历printf("深度优先遍历:\n");printf("递归:\n");TraverseGraph(G);printf("\n");printf("非递归:\n");NoReTraverseGraph(G);printf("\n");printf("输入普利姆算法的顶点\n");int v0 = 0;char c0 = 0;scanf(" %c", &c0);v0 = LocateVertex(&G, c0);PrimMiniSpanTree(G, v0);
}
int main() {test();//test01();return 0;
}