From de75f73c162a005825d9f7bf87e1f6d4cd1427c5 Mon Sep 17 00:00:00 2001 From: Ruvikm <1092045998@qq.com> Date: Fri, 19 Feb 2021 21:58:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=BE=E7=9A=84=E9=81=8D=E5=8E=86=E5=B0=8F?= =?UTF-8?q?=E8=8A=82=E5=AE=8C=E7=BB=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 图的应用好像没有代码题,貌似图完结了.... --- 图/图的遍历/P232.2.cpp | 176 ++++++++++++++++++++++++++++++++++++++++ 图/图的遍历/P232.3.cpp | 157 ++++++++++++++++++++++++++++++++++++ 图/图的遍历/P233.4.cpp | 178 +++++++++++++++++++++++++++++++++++++++++ 图/图的遍历/P233.5.cpp | 168 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 679 insertions(+) create mode 100644 图/图的遍历/P232.2.cpp create mode 100644 图/图的遍历/P232.3.cpp create mode 100644 图/图的遍历/P233.4.cpp create mode 100644 图/图的遍历/P233.5.cpp diff --git a/图/图的遍历/P232.2.cpp b/图/图的遍历/P232.2.cpp new file mode 100644 index 0000000..8ca6718 --- /dev/null +++ b/图/图的遍历/P232.2.cpp @@ -0,0 +1,176 @@ +#include + +using namespace std; + +#pragma region 创建邻接表存储的无向图 + +#define MaxVertexNum 10 //图中顶点数目最大值 +#define VertexType char +#define _for(i,a,b) for(int i=(a);i<(b);i++) + +typedef struct ArcNode { //边表结点 + int adjvex; //该弧所指向的顶点的位置 + ArcNode* next; //指向下一条弧的指针 +}ArcNode; + +typedef struct VNode { //顶点表结点 + VertexType data; //顶点信息 + ArcNode* first; //指向第一条依附该顶点的弧的指针 +}VNode, AdjList[MaxVertexNum]; + +typedef struct { + AdjList vertices; //领接表 + int vexnum, arcnum; //图的顶点数和弧数 +}ALGraph; //ALGraph是以邻接表存储的图类型 + + +int LocateVex(ALGraph& G, VertexType x) { + + _for(i, 0, G.vexnum) { + if (G.vertices[i].data == x) + return i; + } + return -1; +} + +void CreateALGraph(ALGraph& G) { + + cout << "输入顶点数和边数" << endl; + cin >> G.vexnum >> G.arcnum; + _for(i, 0, G.vexnum) { + cout << "输入第" << i + 1 << "个顶点的信息" << endl; + cin >> G.vertices[i].data; + G.vertices[i].first = NULL; + } + _for(k, 0, G.arcnum) { + VertexType e1, e2; + cout << "输入第" << k + 1 << "条边的顶点:" << endl; + cin >> e1 >> e2; + ArcNode* e = new ArcNode; + if (!e) { + cout << "内存申请失败!" << endl; + exit(0); + } + + int vi = LocateVex(G, e1); + int vj = LocateVex(G, e2); + + e->adjvex = vj; //这三步,类似于单链表的头插法 + e->next = G.vertices[vi].first; + G.vertices[vi].first = e; + + e = new ArcNode; + if (!e) { + cout << "内存申请失败!" << endl; + exit(0); + } + e->adjvex = vi; + e->next = G.vertices[vj].first; + G.vertices[vj].first = e; + } +} + +bool visited[MaxVertexNum]; + +void DFS(ALGraph G, int i) { //邻接表的深度优先递归 + + ArcNode* p; + visited[i] = true; //访问过了该顶点,标记为TRUE + cout << G.vertices[i].data << " "; + p = G.vertices[i].first; //让p指向边表第一个结点 + while (p) { //在边表内遍历 + if (!visited[p->adjvex]) //对未访问的邻接顶点递归调用 + DFS(G, p->adjvex); + p = p->next; + } +} + +void DFSTraverse(ALGraph G) { //邻接表的深度遍历操作 + _for(i, 0, G.vexnum) + visited[i] = false; //初始设置为未访问  + _for(i, 0, G.vexnum) + if (!visited[i]) + DFS(G, i); //对未访问的顶点调用DFS,若是连通图只会执行一次  +} + +#pragma endregion + +//P232.2 +//试设计一个算法, 判断一个无向图G是否为一棵树。若是一棵树, 则算法返回true +//否则返回false + +bool visit[MaxVertexNum]; +int Enum = 0, Vnum = 0; + +void DFS_2(ALGraph G, int i) { //邻接表的深度优先递归 + + ArcNode* p; + visit[i] = true; //访问过了该顶点,标记为TRUE + Vnum++; + p = G.vertices[i].first; //让p指向边表第一个结点 + while (p) { //在边表内遍历 + Enum++; + if (!visit[p->adjvex]) //对未访问的邻接顶点递归调用 + DFS_2(G, p->adjvex); + p = p->next; + } +} + +bool isTree(ALGraph G) { + + memset(visit, false, sizeof(visit)); + DFS_2(G, 1); + if (G.vexnum == Vnum && Enum == 2 * (G.vexnum - 1)) + return true; + else + return false; +} + +int main() +{ + ALGraph G; + CreateALGraph(G); + cout << endl; + cout << "DFS:" << endl; + DFSTraverse(G); + cout << endl; + if (isTree(G)) + cout << "图G是一棵树" << endl; + else + cout << "图G不是一棵树" << endl; + return 0; +} + +/* +input: + +5 7 +a b c d e +a b +a e +b c +b d +b e +c d +d e + + +生成图的链接:https://s3.ax1x.com/2021/02/18/yW59vF.png + +普通的树: + +7 6 +a b c d e f g +a b +a c +a d +b e +b f +d g + + + a + b c d + e f g + +*/ \ No newline at end of file diff --git a/图/图的遍历/P232.3.cpp b/图/图的遍历/P232.3.cpp new file mode 100644 index 0000000..30435aa --- /dev/null +++ b/图/图的遍历/P232.3.cpp @@ -0,0 +1,157 @@ +#include +#include + +using namespace std; + +#pragma region 创建邻接表存储的无向图 + +#define MaxVertexNum 10 //图中顶点数目最大值 +#define VertexType char +#define _for(i,a,b) for(int i=(a);i<(b);i++) + +typedef struct ArcNode { //边表结点 + int adjvex; //该弧所指向的顶点的位置 + ArcNode* next; //指向下一条弧的指针 +}ArcNode; + +typedef struct VNode { //顶点表结点 + VertexType data; //顶点信息 + ArcNode* first; //指向第一条依附该顶点的弧的指针 +}VNode, AdjList[MaxVertexNum]; + +typedef struct { + AdjList vertices; //领接表 + int vexnum, arcnum; //图的顶点数和弧数 +}ALGraph; //ALGraph是以邻接表存储的图类型 + + +int LocateVex(ALGraph& G, VertexType x) { + + _for(i, 0, G.vexnum) { + if (G.vertices[i].data == x) + return i; + } + return -1; +} + +void CreateALGraph(ALGraph& G) { + + cout << "输入顶点数和边数" << endl; + cin >> G.vexnum >> G.arcnum; + _for(i, 0, G.vexnum) { + cout << "输入第" << i + 1 << "个顶点的信息" << endl; + cin >> G.vertices[i].data; + G.vertices[i].first = NULL; + } + _for(k, 0, G.arcnum) { + VertexType e1, e2; + cout << "输入第" << k + 1 << "条边的顶点:" << endl; + cin >> e1 >> e2; + ArcNode* e = new ArcNode; + if (!e) { + cout << "内存申请失败!" << endl; + exit(0); + } + + int vi = LocateVex(G, e1); + int vj = LocateVex(G, e2); + + e->adjvex = vj; //这三步,类似于单链表的头插法 + e->next = G.vertices[vi].first; + G.vertices[vi].first = e; + + e = new ArcNode; + if (!e) { + cout << "内存申请失败!" << endl; + exit(0); + } + e->adjvex = vi; + e->next = G.vertices[vj].first; + G.vertices[vj].first = e; + } +} + +bool visited[MaxVertexNum]; + +void DFS(ALGraph G, int i) { //邻接表的深度优先递归 + + ArcNode* p; + visited[i] = true; //访问过了该顶点,标记为TRUE + cout << G.vertices[i].data << " "; + p = G.vertices[i].first; //让p指向边表第一个结点 + while (p) { //在边表内遍历 + if (!visited[p->adjvex]) //对未访问的邻接顶点递归调用 + DFS(G, p->adjvex); + p = p->next; + } +} + +void DFSTraverse(ALGraph G) { //邻接表的深度遍历操作 + _for(i, 0, G.vexnum) + visited[i] = false; //初始设置为未访问  + _for(i, 0, G.vexnum) + if (!visited[i]) + DFS(G, i); //对未访问的顶点调用DFS,若是连通图只会执行一次  +} + +#pragma endregion + +//P232.3 +//写出图的深度优先搜索DFS算法的非递归算法(图采用邻接表形式)。 + +bool visit[MaxVertexNum]; + +void DFS_Non_RC(ALGraph& G, int v) { + + memset(visit, false, sizeof(visit)); + stack s; + s.push(v); + visit[v] = true; + while (!s.empty()) { + ArcNode* p = G.vertices[s.top()].first; + cout << G.vertices[s.top()].data << " "; + s.pop(); + while (p) { + if (!visit[p->adjvex]) { + s.push(p->adjvex); + visit[p->adjvex] = true; + } + p = p->next; + } + } +} + +int main() +{ + ALGraph G; + CreateALGraph(G); + cout << endl; + cout << "DFS:" << endl; + DFSTraverse(G); + cout << endl; + DFS_Non_RC(G, 0); + return 0; +} + +/* + +PS: +答案是对的,至于为什么两个DFS顺序不一样 +是因为非递归DFS遍历用头插法插入的边表(逆置的)时 +存入栈中正好把顺序给正过来了。 + +input: + +5 7 +a b c d e +a b +a e +b c +b d +b e +c d +d e + +生成图的链接:https://s3.ax1x.com/2021/02/18/yW59vF.png + +*/ \ No newline at end of file diff --git a/图/图的遍历/P233.4.cpp b/图/图的遍历/P233.4.cpp new file mode 100644 index 0000000..945856c --- /dev/null +++ b/图/图的遍历/P233.4.cpp @@ -0,0 +1,178 @@ +#include +#include +#include + +using namespace std; + +#pragma region 创建邻接表存储的有向图 + +#define MaxVertexNum 10 //图中顶点数目最大值 +#define VertexType char +#define _for(i,a,b) for(int i=(a);i<(b);i++) + +typedef struct ArcNode { //边表结点 + int adjvex; //该弧所指向的顶点的位置 + ArcNode* next; //指向下一条弧的指针 +}ArcNode; + +typedef struct VNode { //顶点表结点 + VertexType data; //顶点信息 + ArcNode* first; //指向第一条依附该顶点的弧的指针 +}VNode, AdjList[MaxVertexNum]; + +typedef struct { + AdjList vertices; //领接表 + int vexnum, arcnum; //图的顶点数和弧数 +}ALGraph; //ALGraph是以邻接表存储的图类型 + + +int LocateVex(ALGraph& G, VertexType x) { + + _for(i, 0, G.vexnum) { + if (G.vertices[i].data == x) + return i; + } + return -1; +} + +void CreateALGraph(ALGraph& G) { + + cout << "输入顶点数和边数" << endl; + cin >> G.vexnum >> G.arcnum; + _for(i, 0, G.vexnum) { + cout << "输入第" << i + 1 << "个顶点的信息" << endl; + cin >> G.vertices[i].data; + G.vertices[i].first = NULL; + } + _for(k, 0, G.arcnum) { + VertexType e1, e2; + cout << "输入第" << k + 1 << "条边(v1 -> v2)的顶点:" << endl; + cin >> e1 >> e2; + ArcNode* e = new ArcNode; + if (!e) { + cout << "内存申请失败!" << endl; + exit(0); + } + + int vi = LocateVex(G, e1); + int vj = LocateVex(G, e2); + + e->adjvex = vj; //这三步,类似于单链表的头插法 + e->next = G.vertices[vi].first; + G.vertices[vi].first = e; + } +} + +bool visited[MaxVertexNum]; + +void DFS(ALGraph G, int i) { //邻接表的深度优先递归 + + ArcNode* p; + visited[i] = true; //访问过了该顶点,标记为TRUE + cout << G.vertices[i].data << " "; + p = G.vertices[i].first; //让p指向边表第一个结点 + while (p) { //在边表内遍历 + if (!visited[p->adjvex]) //对未访问的邻接顶点递归调用 + DFS(G, p->adjvex); + p = p->next; + } +} + +void DFSTraverse(ALGraph G) { //邻接表的深度遍历操作 + _for(i, 0, G.vexnum) + visited[i] = false; //初始设置为未访问  + _for(i, 0, G.vexnum) + if (!visited[i]) + DFS(G, i); //对未访问的顶点调用DFS,若是连通图只会执行一次  +} + +#pragma endregion + +//P233.4 +//分别采用基于深度优先遍历和广度优先遍历算法判别以邻接表方式存储的有向图中是否 +//存在由顶点vi到顶点vj的路径(i≠j)。注意, 算法中涉及的图的基本操作必须在此存储 +//结构上实现 + +bool visit1[MaxVertexNum] = { false }; + +bool ExistPath_DFS(ALGraph G,int i,int j) { + + if (i == j) + return true; + else { + visit1[i] = true; + ArcNode* p = G.vertices[i].first; //让p指向边表第一个结点 + while (p) { //在边表内遍历 + if (!visit1[p->adjvex] && ExistPath_DFS(G, p->adjvex, j)) //对未访问的邻接顶点递归调用 + return true; + p = p->next; + } + return false; + } +} + +bool visit2[MaxVertexNum] = { false }; + +bool ExistPath_BFS(ALGraph G, int i, int j) { + queue q; + q.push(i); + while (!q.empty()) { + visit2[q.front()] = true; + ArcNode* p = G.vertices[q.front()].first; + q.pop(); + while (p) { + if (p->adjvex == j) + return true; + if (!visit2[p->adjvex]) + q.push(p->adjvex); + p = p->next; + } + } + return false; +} + +int main() +{ + ALGraph G; + CreateALGraph(G); + + cout << endl; + cout << "DFS:" << endl; + + DFSTraverse(G); + + cout << endl; + cout << endl; + cout << "使用DFS判别:" << endl; + if (ExistPath_DFS(G, 0, 4)) + cout << "路径存在" << endl; + else + cout << "路径不存在" << endl; + + cout << endl; + cout << endl; + cout << "使用BFS判别:" << endl; + if (ExistPath_BFS(G, 0, 4)) + cout << "路径存在" << endl; + else + cout << "路径不存在" << endl; + return 0; +} + +/* +input: + +6 8 +a b c d e f +a b +a d +b e +c e +c f +d b +e d +f f + +有向图链接:https://s3.ax1x.com/2021/02/19/yhqBOx.png + +*/ \ No newline at end of file diff --git a/图/图的遍历/P233.5.cpp b/图/图的遍历/P233.5.cpp new file mode 100644 index 0000000..415a560 --- /dev/null +++ b/图/图的遍历/P233.5.cpp @@ -0,0 +1,168 @@ +#include +#include +#include +#include + +using namespace std; + +#pragma region 创建邻接表存储的有向图 + +#define MaxVertexNum 10 //图中顶点数目最大值 +#define VertexType char +#define _for(i,a,b) for(int i=(a);i<(b);i++) + +typedef struct ArcNode { //边表结点 + int adjvex; //该弧所指向的顶点的位置 + ArcNode* next; //指向下一条弧的指针 +}ArcNode; + +typedef struct VNode { //顶点表结点 + VertexType data; //顶点信息 + ArcNode* first; //指向第一条依附该顶点的弧的指针 +}VNode, AdjList[MaxVertexNum]; + +typedef struct { + AdjList vertices; //领接表 + int vexnum, arcnum; //图的顶点数和弧数 +}ALGraph; //ALGraph是以邻接表存储的图类型 + + +int LocateVex(ALGraph& G, VertexType x) { + + _for(i, 0, G.vexnum) { + if (G.vertices[i].data == x) + return i; + } + return -1; +} + +void CreateALGraph(ALGraph& G) { + + cout << "输入顶点数和边数" << endl; + cin >> G.vexnum >> G.arcnum; + _for(i, 0, G.vexnum) { + cout << "输入第" << i + 1 << "个顶点的信息" << endl; + cin >> G.vertices[i].data; + G.vertices[i].first = NULL; + } + _for(k, 0, G.arcnum) { + VertexType e1, e2; + cout << "输入第" << k + 1 << "条边(v1 -> v2)的顶点:" << endl; + cin >> e1 >> e2; + ArcNode* e = new ArcNode; + if (!e) { + cout << "内存申请失败!" << endl; + exit(0); + } + + int vi = LocateVex(G, e1); + int vj = LocateVex(G, e2); + + e->adjvex = vj; //这三步,类似于单链表的头插法 + e->next = G.vertices[vi].first; + G.vertices[vi].first = e; + } +} + +bool visited[MaxVertexNum]; + +void DFS(ALGraph G, int i) { //邻接表的深度优先递归 + + ArcNode* p; + visited[i] = true; //访问过了该顶点,标记为TRUE + cout << G.vertices[i].data << " "; + p = G.vertices[i].first; //让p指向边表第一个结点 + while (p) { //在边表内遍历 + if (!visited[p->adjvex]) //对未访问的邻接顶点递归调用 + DFS(G, p->adjvex); + p = p->next; + } +} + +void DFSTraverse(ALGraph G) { //邻接表的深度遍历操作 + _for(i, 0, G.vexnum) + visited[i] = false; //初始设置为未访问  + _for(i, 0, G.vexnum) + if (!visited[i]) + DFS(G, i); //对未访问的顶点调用DFS,若是连通图只会执行一次  +} + +#pragma endregion + +//P233.5 +//假设图用邻接表表示, 设计一个算法, 输出从顶点Vi到顶点Vj的所有简单路径 + +bool visit[MaxVertexNum] = { false }; +vector path; +bool flag = false; + +void FindPath(ALGraph G,int i,int j) { + + path.push_back(i); + if (i == j) { + _for(i, 0, path.size()) { + if (i < path.size() - 1) + cout << G.vertices[path[i]].data << "->"; + else + cout << G.vertices[path[i]].data << endl; + } + flag = true; + exit(0); //return还会多输出一次路径 + } + else { + visit[i] = true; + ArcNode* p = G.vertices[i].first; + while (p) { + if (!visit[p->adjvex]) { + FindPath(G, p->adjvex, j); + } + p = p->next; + } + visit[i] = false; + path.pop_back(); + } +} + +void PrintPath(ALGraph G, VertexType vi, VertexType vj) { + + FindPath(G, LocateVex(G, vi), LocateVex(G, vj)); +} + +int main() +{ + ALGraph G; + CreateALGraph(G); + + cout << endl; + cout << "DFS:" << endl; + + DFSTraverse(G); + + cout << endl; + cout << endl; + cout << "路径如下:" << endl; + PrintPath(G, 'c', 'd'); + if (!flag) { + cout << "路径不存在!" << endl; + } + return 0; +} + +/* +input: + + +6 8 +a b c d e f +a b +a d +b e +c e +c f +d b +e d +f f + +有向图链接:https://s3.ax1x.com/2021/02/19/yhqBOx.png + +*/ \ No newline at end of file