14:39:22 2019-09-01
学习
图的两种遍历方法:
①DFS 深度优先搜索(Depth First Search)
②BFS 广度优先搜索(Breadth First Search) //利用队列实现广度优先
//邻接表实现 及 利用 邻接表 实现 深度优先搜索(DFS)
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<malloc.h> 4 //表示图的两种方法 5 //邻接矩阵 G[N][N] N个顶点从0到N-1编号 6 //邻接表 表示 7 /*Graph Create(); //建立并返回空图 8 Graph InsertVertex(Graph G, Vertex v); //将v插入G 9 Graph InsertEdge(Graph G, Edge e); //将e插入G 10 void DFS(Graph G, Vertex v); //从顶点v出发深度优先遍历图G 11 void BFS(Graph G, Vertex v); //从顶点v出发宽度优先遍历图G 12 void ShortestPath(Graph G, Vertex v, int Dist[]); //计算图G中顶点v到任意其它顶点的最短距离 13 void MST(Graph G); //计算图G的最小生成树*/ 14 15 //图的邻接表表示法 16 #define MaxVerterNum 100 //最大顶点数 17 #define INFINITY 65535 // 18 typedef int Vertex; //顶点下标表示顶点 19 typedef int WeightType; //边的权值 20 typedef char DataType; //顶点存储的数据类型 21 22 //边的定义 23 typedef struct ENode* PtrToENode; 24 typedef PtrToENode Edge; 25 struct ENode 26 { 27 Vertex V1, V2; //有向边<V1,V2> 28 WeightType Weight; //权重 29 }; 30 31 //邻接点的定义 32 typedef struct AdjVNode* PtrToAdjVNode; 33 struct AdjVNode 34 { 35 Vertex AdjV; //邻接点下标 36 WeightType Weight; //边权重 37 PtrToAdjVNode Next; //指向下一个邻接点的指针 38 }; 39 40 //顶点表头节点的定义 41 typedef struct Vnode 42 { 43 PtrToAdjVNode FirstEdge; //边表头指针 44 DataType Data; //存顶点的数据 45 }AdjList[MaxVerterNum]; //AdjList是邻接表类型 46 47 //图节点的定义 48 typedef struct GNode* PtrToGNode; 49 typedef PtrToGNode LGraph; 50 struct GNode 51 { 52 int Nv; //顶点数 53 int Ne; //边数 54 AdjList G; //邻接表 55 }; 56 57 LGraph CreateGraph(int VertexNum) 58 {//初始化一个有VertexNum个顶点但没有边的图 59 Vertex V; 60 LGraph Graph; 61 62 Graph = (LGraph)malloc(sizeof(struct GNode)); //建立图 63 Graph->Nv = VertexNum; 64 Graph->Ne = 0; 65 //初始化邻接表头指针 66 for (V = 0; V < Graph->Nv; V++) 67 Graph->G[V].FirstEdge = NULL; 68 return Graph; 69 } 70 71 void InsertEdge(LGraph Graph, Edge E) 72 { 73 PtrToAdjVNode NewNode; 74 //插入边<V1,V2> 75 NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode)); 76 NewNode->AdjV = E->V2; 77 NewNode->Weight = E->Weight; 78 NewNode->Next = Graph->G[E->V1].FirstEdge; 79 Graph->G[E->V1].FirstEdge = NewNode; 80 81 //若是无向图 还要插入边<V2,V1> 82 NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode)); 83 NewNode->AdjV = E->V1; 84 NewNode->Weight = E->Weight; 85 NewNode->Next = Graph->G[E->V2].FirstEdge; 86 Graph->G[E->V2].FirstEdge = NewNode; 87 } 88 89 LGraph BuildGraph() 90 { 91 LGraph Graph; 92 Edge E; 93 Vertex V; 94 int Nv, i; 95 96 scanf("%d", &Nv); /* 读入顶点个数 */ 97 Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */ 98 scanf("%d", &(Graph->Ne)); //读入边数 99 if (Graph->Ne != 0) 100 { 101 E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */ 102 /* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */ 103 for (i = 0; i < Graph->Ne; i++) 104 { 105 scanf("%d %d %d", &E->V1, &E->V2, &E->Weight); 106 InsertEdge(Graph, E); 107 } 108 } 109 /* 如果顶点有数据的话,读入数据 */ 110 for (V = 0; V < Graph->Nv; V++) 111 scanf(" %c", &(Graph->G[V].Data)); 112 return Graph; 113 } 114 115 //DFS 利用邻接表存储的图 实现 深度优先搜索 116 int visited[100]; 117 void Visit(Vertex V) 118 { 119 printf("访问顶点%d\n", V); 120 } 121 122 // visited[]是全局变量 初始化为0 123 void DFS(LGraph Graph, Vertex V) //以V为出发点访对邻接表存储的图进行DFS访问 124 { 125 Visit(V); 126 visited[V] = 1; 127 128 PtrToAdjVNode W; //用来从某个点 出发访问 129 for (W = Graph->G[V].FirstEdge; W; W = W->Next) 130 { 131 if (!visited[W->AdjV]) //若 W->Adjv未被访问 则递归访问 132 DFS(Graph, W->AdjV); 133 } 134 }
//邻接矩阵实现 及 利用 邻接矩阵 实现 广度优先搜索(BFS)
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<malloc.h> 4 //表示图的两种方法 5 //邻接矩阵 G[N][N] N个顶点从0到N-1编号 6 //邻接表 表示 7 /*Graph Create(); //建立并返回空图 8 Graph InsertVertex(Graph G, Vertex v); //将v插入G 9 Graph InsertEdge(Graph G, Edge e); //将e插入G 10 void DFS(Graph G, Vertex v); //从顶点v出发深度优先遍历图G 11 void BFS(Graph G, Vertex v); //从顶点v出发宽度优先遍历图G 12 void ShortestPath(Graph G, Vertex v, int Dist[]); //计算图G中顶点v到任意其它顶点的最短距离 13 void MST(Graph G); //计算图G的最小生成树*/ 14 15 //图的邻接矩阵表示法 16 #define MaxVerterNum 100 //最大顶点数 17 #define INFINITY 65535 // 18 typedef int Vertex; //顶点下标表示顶点 19 typedef int WeightType; //边的权值 20 typedef char DataType; //顶点存储的数据类型 21 22 //边的定义 23 typedef struct ENode* PtrToENode; 24 typedef PtrToENode Edge; 25 struct ENode 26 { 27 Vertex V1, V2; //有向边<V1,V2> 28 WeightType Weight; //权重 29 }; 30 31 //图节点的定义 32 typedef struct GNode* PtrToGNode; 33 typedef PtrToGNode MGraph; //以邻接矩阵存储的图类型 34 struct GNode 35 { 36 int Nv; //顶点数 37 int Ne; //边数 38 WeightType G[MaxVerterNum][MaxVerterNum]; //邻接矩阵 39 DataType Data[MaxVerterNum]; //存顶点的数据 40 }; 41 42 MGraph CreateGraph(int VertexNum) 43 {//初始化一个有VerterNum个顶点但没有边的图 44 Vertex V, W; 45 MGraph Graph; 46 47 Graph = (MGraph)malloc(sizeof(struct GNode)); //建立图 48 Graph->Nv = VertexNum; 49 Graph->Ne = 0; 50 //初始化邻接矩阵 51 for (V = 0; V < Graph->Nv; V++) 52 for (W = 0; W < Graph->Nv; W++) 53 Graph->G[V][W] = INFINITY; 54 return Graph; 55 } 56 57 void InsertEdge(MGraph Graph, Edge E) 58 { 59 //插入边<V1,V2> 60 Graph->G[E->V1][E->V2] = E->Weight; 61 //如果是无向图 还要插入边<V2,V1> 62 Graph->G[E->V2][E->V1] = E->Weight; 63 } 64 65 MGraph BuildGraph() 66 { 67 MGraph Graph; 68 Edge E; 69 Vertex V; 70 int Nv, i; 71 72 scanf("%d", &Nv); //读入顶点个数 73 Graph = CreateGraph(Nv); //初始化有Nv个顶点但没有边的图 74 75 scanf("%d", &(Graph->Ne)); //读入边数 76 if (Graph->Ne != 0) //如果有边 77 { 78 E = (Edge)malloc(sizeof(struct ENode)); //建立边节点 79 //读入边 格式为 起点 终点 权重 插入邻接矩阵 80 for (int i = 0; i < Graph->Ne; i++) 81 { 82 scanf("%d %d %d", &(E->V1), &(E->V2), &(E->Weight)); 83 InsertEdge(Graph, E); 84 } 85 } 86 //若顶点有数据 读入数据 87 for (V = 0; V < Graph->Nv; V++) 88 scanf("%c", &(Graph->Data[V])); 89 return Graph; 90 } 91 92 //邻接矩阵 实现广度优先搜索 BFS 利用队列 93 #define Size 50 94 int Queue[Size]; 95 int Front=1; 96 int Rear=0; 97 int size; 98 99 int Succ(int Value) 100 { 101 if (Value < Size) 102 return Value; 103 else 104 return 0; 105 } 106 107 int IsEmpty() 108 { 109 return (size == 0) ? 1 : 0; 110 } 111 int IsFull() 112 { 113 return (size == Size) ? 1 : 0; 114 } 115 void EnQueue(int Element) 116 { 117 Rear = Succ(Rear+1); 118 Queue[Rear] = Element; 119 size++; 120 } 121 int DeQueue() 122 { 123 int Element = Queue[Front]; 124 Front = Succ(Front+1); 125 size--; 126 return Element; 127 } 128 129 //利用队列 与树的层序遍历相似 130 int visited[50]; 131 int IsEdge(MGraph Graph, int V, int W) //IsEdge 检查<V,W>是否是图Graph中的一条边 132 { 133 return (Graph->G[V][W] < INFINITY) ? 1 : 0; 134 } 135 void Visit(Vertex V) 136 { 137 printf("访问节点%d\n", V); 138 } 139 void BFS(MGraph Graph, Vertex S) //从节点S出发对以邻接矩阵存储的图Graph进行BFS搜索 140 { 141 EnQueue(S); 142 Visit(S); 143 visited[S] = 1; 144 145 while (!IsEmpty()) 146 { 147 Vertex V=DeQueue(); 148 for (int W = 0; W < Graph->Nv; W++) 149 if (!visited[W] && IsEdge(Graph, V, W)) 150 { 151 EnQueue(W); 152 Visit(W); 153 visited[W] = 1; 154 } 155 } 156 }
PTA第15题 利用 邻接矩阵实现 图 并 用 深度优先搜索(DFS) 和 广度优先搜索(BFS) 输出数据
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<malloc.h> 4 #define True 1 5 #define False 0 6 typedef struct ENode* Edge; 7 struct ENode 8 { 9 int V1, V2; 10 }; 11 12 typedef struct Graph* MGraph; 13 struct Graph 14 { 15 int Nv; 16 int Ne; 17 int G[10][10]; 18 }; 19 20 MGraph CreateGraph(int MaxVertex) //初始化一个没有边的图 21 { 22 MGraph Graph = (MGraph)malloc(sizeof(struct Graph)); 23 Graph->Nv = MaxVertex; 24 Graph->Ne = 0; 25 for (int i = 0; i < Graph->Nv; i++) 26 for (int j = 0; j < Graph->Nv; j++) 27 Graph->G[i][j] =False; 28 return Graph; 29 } 30 31 void Insert(MGraph Graph, Edge E) 32 { //插入一个无向图 33 Graph->G[E->V1][E->V2] = 1; 34 Graph->G[E->V2][E->V1] = 1; 35 } 36 37 MGraph BuildGraph() 38 { 39 MGraph Graph; 40 Edge E; 41 int V; 42 int Nv; 43 scanf("%d", &Nv); 44 Graph = CreateGraph(Nv); 45 scanf("%d\n", &(Graph->Ne)); 46 if (Graph->Ne) 47 { 48 E = (Edge)malloc((sizeof(struct ENode))); 49 for (int i = 0; i < Graph->Ne; i++) 50 { 51 scanf("%d %d\n", &(E->V1), &(E->V2)); 52 Insert(Graph, E); 53 } 54 } 55 return Graph; 56 } 57 //DFS 深度优先遍历 58 int visited1[11]; 59 int IsEdge(MGraph Graph,int V, int W) 60 { 61 return (Graph->G[V][W]==True)? 1 : 0; 62 } 63 void Visit(int V) 64 { 65 printf("%d ", V); 66 } 67 void DFS(MGraph Graph, int V) //默认从编号最小的点出发 即从V=0出发 68 { 69 Visit(V); 70 visited1[V] = 1; 71 for (int i = 0; i < Graph->Nv; i++) 72 { 73 if (!visited1[i] && IsEdge(Graph, V, i)) 74 DFS(Graph, i); 75 } 76 } 77 void ListComponetsForDFS(MGraph Graph) //解决图不连通的问题 78 { 79 for (int i = 0; i < Graph->Nv; i++) 80 { 81 if (!visited1[i]) 82 { 83 printf("{ "); 84 DFS(Graph, i); 85 printf("}\n"); 86 } 87 } 88 } 89 90 //BFS 广度优先遍历 91 #define Size 11 92 int visited2[11]; 93 int Queue[11]; 94 int Front = 1; 95 int Rear = 0; 96 int size = 0; 97 int IsEmpty() 98 { 99 return (size == 0) ? 1 : 0; 100 } 101 int Succ(int Value) 102 { 103 if (Value < Size) 104 return Value; 105 else 106 return 0; 107 } 108 void EnQueue(int V) 109 { 110 Rear = Succ(Rear + 1); 111 Queue[Rear] = V; 112 size++; 113 } 114 int DeQueue() 115 { 116 int V = Queue[Front]; 117 Front = Succ(Front + 1); 118 size--; 119 return V; 120 } 121 void BFS(MGraph Graph, int V) 122 { 123 EnQueue(V); 124 Visit(V); 125 visited2[V] = 1; 126 while (!IsEmpty()) 127 { 128 int W=DeQueue(); 129 for (int i = 0; i < Graph->Nv; i++) 130 { 131 if (!visited2[i] && IsEdge(Graph, W, i)) 132 { 133 EnQueue(i); 134 Visit(i); 135 visited2[i] = 1; 136 } 137 } 138 } 139 } 140 void ListComponetsForBFS(MGraph Graph) 141 { 142 for (int i = 0; i < Graph->Nv; i++) 143 { 144 if (!visited2[i]) 145 { 146 printf("{ "); 147 BFS(Graph, i); 148 printf("}\n"); 149 } 150 } 151 } 152 int main() 153 { 154 MGraph Graph = BuildGraph(); 155 ListComponetsForDFS(Graph); 156 ListComponetsForBFS(Graph); 157 return 0; 158 }
(os:稍微吐槽一句 我现在才认识什么是深度优先搜索和广度优先搜索 上学期就学的人是大佬)
PTA第16题 007逃生问题 其实也是建图 然后利用图的 深度优先搜索(DFS) 当然广度优先搜索也可以
要计算节点之间的路径 我是新建了一个 存坐标的结构体 利用 元素在图里下标 和在 结构体下标一样 来进行计算
(os:最后找了快一小时bug 最后发现是因为我对递归的理解不过关 以后要抽空写写递归)
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<malloc.h> 4 #include<math.h> 5 #define True 1 6 #define False 0 7 #define SizeOfPosition 100 8 float Length; //跳跃长度 9 struct Position 10 { 11 int x; 12 int y; 13 }Positions[SizeOfPosition]; 14 15 float Distance(float x1, float y1, float x2, float y2) 16 { 17 return sqrt(((y2 - y1) * (y2 - y1)) + ((x2 - x1) * (x2 - x1))); 18 } 19 20 typedef struct ENode* Edge; 21 struct ENode 22 { 23 int V1; 24 int V2; 25 }; 26 27 typedef struct Graph* MGraph; 28 struct Graph 29 { 30 int Nv; 31 int Ne; 32 int G[100][100]; 33 }; 34 35 MGraph CreateGraph(int MaxVertex) 36 { 37 MGraph Graph = (MGraph)malloc(sizeof(struct Graph)); 38 Graph->Nv = MaxVertex; 39 Graph->Ne = 0; 40 for (int i = 0; i < Graph->Nv; i++) 41 for (int j = 0; j < Graph->Nv; j++) 42 Graph->G[i][j] = 0; 43 return Graph; 44 } 45 46 void Insert(MGraph Graph, Edge E) 47 { 48 Graph->G[E->V1][E->V2] = 1; 49 Graph->G[E->V2][E->V1] = 1; 50 } 51 52 MGraph BuildGraph() 53 { 54 MGraph Graph; 55 Edge E; 56 int Nv; 57 scanf("%d %f\n", &Nv, &Length); 58 Graph = CreateGraph(Nv); 59 for (int i = 0; i < Graph->Nv; i++) 60 { 61 int x, y; 62 scanf("%d %d\n", &x, &y); 63 Positions[i].x = x; 64 Positions[i].y = y; 65 } 66 for(int i=0;i<Graph->Nv;i++) 67 for (int j =i+1; j < Graph->Nv; j++) 68 { 69 float dis = Distance(Positions[i].x, Positions[i].y, Positions[j].x, Positions[j].y); 70 if (dis <=Length) 71 { 72 E = (Edge)malloc(sizeof(struct ENode)); 73 E->V1 = i; 74 E->V2 = j; 75 Insert(Graph, E); 76 } 77 } 78 return Graph; 79 } 80 int visited[100]; 81 int IsEdge(MGraph Graph,int V,int W) 82 { 83 return (Graph->G[V][W] == 1) ? 1 : 0; 84 } 85 int Judget(MGraph Graph,int V,float Length) //深度优先遍历 86 { 87 visited[V] = 1; 88 if (Distance(0, 50, Positions[V].x, Positions[V].y) <= Length|| Distance(0, -50, Positions[V].x, Positions[V].y) <= Length 89 || Distance(50,0, Positions[V].x, Positions[V].y) <= Length || Distance(-50, 0, Positions[V].x, Positions[V].y) <= Length) 90 return 1; 91 for (int i = 0; i < Graph->Nv; i++) 92 { 93 if (!visited[i] && IsEdge(Graph, V, i)) 94 if (Judget(Graph, i, Length)) 95 return 1; 96 } 97 return 0; 98 } 99 int ListComponets(MGraph Graph) 100 { 101 for (int i = 0; i < Graph->Nv; i++) 102 { 103 if (!visited[i] && (Length+7.5)>=Distance(0, 0, Positions[i].x, Positions[i].y)) 104 if (Judget(Graph, i, Length)) 105 return 1; 106 } 107 return 0; 108 } 109 int main() 110 { 111 MGraph Graph; 112 Graph = BuildGraph(); 113 if (ListComponets(Graph)) 114 printf("Yes"); 115 else 116 printf("No"); 117 return 0; 118 }