数据结构学习第十八天
14:07:40 2019-09-02
学习
PTA第17题 六度空间理论
可以在结构体中 加上一个属性来表示层数
我是利用一个整型变量 Level和 一个数组LevelSize来记录每层数量多少
需要注意要处理 最远距离小于6的情况
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<malloc.h> 4 5 int NumberOfConnect[1001]; 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[1001][1001]; 18 }; 19 20 MGraph CreateMGraph(int MaxVertex) 21 { 22 MGraph Graph; 23 Graph = (MGraph)malloc(sizeof(struct Graph)); 24 Graph->Nv = MaxVertex; 25 Graph->Ne = 0; 26 for (int i = 1; i <=Graph->Nv; i++) 27 for (int j = 1; j <=Graph->Nv; j++) 28 Graph->G[i][j] = 0; 29 return Graph; 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 MGraph BuildGraph() 37 { 38 MGraph Graph; 39 Edge E; 40 int Nv; 41 scanf("%d", &Nv); 42 Graph = CreateMGraph(Nv); 43 scanf("%d\n", &(Graph->Ne)); 44 for (int i = 0; i < Graph->Ne; i++) 45 { 46 E = (Edge)malloc(sizeof(struct ENode)); 47 scanf("%d %d\n", &(E->V1), &(E->V2)); 48 Insert(Graph, E); 49 } 50 return Graph; 51 } 52 53 int IsEdge(MGraph Graph,int V, int W) 54 { 55 return (Graph->G[V][W] == 1) ? 1 : 0; 56 } 57 58 //利用广度优先搜索 59 #define Size 1001 60 int Queue[Size]; 61 int Front = 1; 62 int Rear = 0; 63 int size = 0; 64 int IsEmpty() 65 { 66 return (size == 0) ? 1 : 0; 67 } 68 int Succ(int Value) 69 { 70 if (Value < Size) 71 return Value; 72 else 73 return 0; 74 } 75 void EnQueue(int V) 76 { 77 Rear = Succ(Rear + 1); 78 Queue[Rear] = V; 79 size++; 80 } 81 int DeQueue() 82 { 83 int V = Queue[Front]; 84 Front = Succ(Front + 1); 85 size--; 86 return V; 87 } 88 void InitializeQueue() 89 { 90 for (int i = 0; i < Size; i++) 91 Queue[i] = 0; 92 Front = 1; 93 Rear = 0; 94 size = 0; 95 } 96 int visited[1001]; 97 void InitializeVisited() 98 { 99 for (int i = 0; i < 1001; i++) 100 visited[i] = 0; 101 } 102 int BFS(MGraph Graph, int V) 103 { 104 InitializeVisited(); 105 InitializeQueue(); 106 EnQueue(V); 107 visited[V] = 1; 108 int Level = 0; //从第0层开始 109 int LevelSize[1001] = {0}; 110 LevelSize[Level] = 1; //第0层自己算一个元素 111 NumberOfConnect[V]++; //令该顶点可以访问的个数加1 112 while (!IsEmpty()) 113 { 114 int W = DeQueue(); 115 LevelSize[Level]--; 116 for (int i = 1; i <= Graph->Nv; i++) 117 if (!visited[i]&&IsEdge(Graph, W, i)) 118 { 119 LevelSize[Level+1]++; 120 EnQueue(i); 121 visited[i] = 1; 122 NumberOfConnect[V]++; 123 } 124 if (LevelSize[Level] == 0) 125 Level++; 126 if (Level==6) 127 return NumberOfConnect[V]; 128 } 129 //当 达不到6 层时 130 return NumberOfConnect[V]; 131 } 132 void OutPut(MGraph Graph,int V,float num) 133 { 134 printf("%d: %.2f%%\n", V, (num / Graph->Nv) * 100); 135 } 136 void SDS(MGraph Graph) 137 { 138 for (int i = 1; i <= Graph->Nv; i++) 139 { 140 int num = BFS(Graph,i); 141 OutPut(Graph,i,num); 142 } 143 } 144 int main() 145 { 146 MGraph G; 147 G = BuildGraph(); 148 SDS(G); 149 return 0; 150 }
在网络中,求两个不同顶点之间的所有路径中 边的权值之和最小的那一条路径
这条路径就是两点之间的最短路径(Shortest Path)
第一个顶点为起点(源点 Source)
最后一个顶点为终点(Destination)
问题分类:
①单源最短路径问题:从某固定源点出发,求其到所有其他顶点的最短路径
Ⅰ.(有向/无向)无权图
Ⅱ.(有向/无向)有权图
②多源最短路径问题:求任意两顶点间的最短路径
无权图的单源最短路算法
按照递增(非递减)的顺序找出到各个项点的最短路 //利用 广度优先遍历
有权图的单源最短路算法
按照递增(非递减)的顺序找出到各个项点的最短路 //利用 Dijkstra算法
Dijkstra算法
令$S=\left\{\text源点s + 已经确定了最短路径的顶点 v_i \right\}$
多源最短路算法
①直接将单源最短路算法调用$V$遍 //对于稀疏图效果好
②Floyd算法 //对于稠密图效果好
Floyd算法
$D^k[i][j]=路径\left\{i \rightarrow \left\{l \leq k \right\} \rightarrow j \right\}$ 的最小长度
$D^0,D^1,\cdots,D^{|V|-1}[i][j] 即给出了i到j的真正最短距离$
三种算法:
1 //无权图的单源最短路算法 2 3 int Dist[50]; //S到W的最短距离(源点到某点的最短距离) 4 int Path[50]; //S到W的路上经过的某顶点 5 void InitializeDistAndPath() 6 { 7 for (int i = 0; i < 50; i++) 8 { 9 Dist[i] = -1; 10 Path[i] = -1; 11 } 12 } 13 void UnWeighted(MGraph Graph, Vertex S) 14 { 15 InitializeDistAndPath(); 16 EnQueue(S); 17 Dist[S] = 0; 18 while (!IsEmpty()) 19 { 20 Vertex V = DeQueue(); 21 for (int W = 0; W < Graph->Nv; W++) 22 if (Dist[W] == -1 && IsEdge(Graph, V, W)) 23 { 24 Dist[W] = Dist[V] + 1; 25 Path[W] = V; 26 EnQueue(W); 27 } 28 } 29 } 30 31 //有权图的单源最短路算法 32 //Dijkstra算法 //不能解决有负边的情况 33 int Dists[50]; 34 int Collected[50]; 35 int Paths[50]; 36 Vertex FindMinDist(MGraph Graph) //返回未被收录顶点中 Dists最小者 37 { 38 Vertex MinV, V; 39 int MinDist = INFINITY; 40 for (V = 0; V < Graph->Nv; V++) 41 { 42 if (Collected[V]!=0&&Dists[V] < MinDist) 43 { 44 MinDist = Dists[V]; 45 MinV = V; 46 } 47 } 48 if (MinDist < INFINITY) 49 return MinV; 50 else 51 return 0; 52 } 53 int Dijkstra(MGraph Graph, Vertex S) 54 { 55 Vertex V; 56 //初始化 57 for (int i = 0; i < Graph->Nv; i++) 58 { 59 Dists[i] = Graph->G[S][i]; //计算出与源点直接相连的节点的Dists 60 if (Dists[i] < INFINITY) 61 Paths[i] = S; 62 else 63 Paths[i] = -1; 64 } 65 66 Dists[S] = 0; //将源点收入 67 Collected[S] = 1; 68 69 while (1) 70 { 71 V = FindMinDist(Graph); 72 if (!V) 73 break; 74 Collected[V] = 1; //收录 75 for (Vertex W = 0; W < Graph->Nv; W++) 76 { 77 if (Collected[W] == 0 && IsEdge(Graph, V, W)) 78 { 79 if (Graph->G[V][W] < 0) //有负边 80 return -1; //不能解决 81 if (Dists[V] + Graph->G[V][W] < Dists[W]) 82 { 83 Dists[W] = Dists[V] + Graph->G[V][W]; 84 Paths[W] = V; 85 } 86 } 87 } 88 } 89 return 1; //算法执行完毕 90 } 91 92 //多源最短路算法 93 //Floyd算法 94 int D[50][50]; 95 int Pa[50][50]; //计算最短路径 96 int Floyd(MGraph Graph) 97 { 98 for (int i = 0; i < Graph->Nv; i++) 99 for (int j = 0; j < Graph->Nv; j++) 100 { 101 D[i][j] = Graph->G[i][j]; 102 Pa[i][j] = -1; 103 } 104 105 for (int k = 0; k < Graph->Nv; k++) 106 for (int i = 0; i < Graph->Nv; i++) 107 for (int j = 0; j < Graph->Nv; j++) 108 if (D[i][k] + D[k][j] < D[i][j]) 109 { 110 D[i][j] = D[i][k] + D[k][j]; 111 if (i == j && D[i][j] < 0) 112 return -1; //有负值圈 解决失败 113 Pa[i][j] = k; 114 } 115 }