数据结构学习第二十天
15:44:43 2019-09-04
勉強します
PTA第20题 Dijkstra算法的变形 其实是加了一个变量来辅助判别 那如果影响的判断的变量增加 就需要多加变量来 继续进行判断
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<malloc.h> 4 #define INIFITY 65635 5 int Departure; 6 int Destination; 7 typedef struct TypeInt Element; 8 struct TypeInt 9 { 10 int Length; 11 int Price; 12 }; 13 typedef struct ENode* Edge; 14 struct ENode 15 { 16 int V1, V2; 17 int Length; 18 int Price; 19 }; 20 21 typedef struct Graph* MGraph; 22 struct Graph 23 { 24 int Nv; 25 int Ne; 26 Element G[500][500]; 27 }; 28 29 MGraph CreateGraph(int MaxVertex) 30 { 31 MGraph Graph = (MGraph)malloc(sizeof(struct Graph)); 32 Graph->Nv = MaxVertex; 33 Graph->Ne = 0; 34 for (int i = 0; i < Graph->Nv; i++) 35 for (int j = 0; j < Graph->Nv; j++) 36 { 37 Graph->G[i][j].Length= INIFITY; 38 Graph->G[i][j].Price = INIFITY; 39 } 40 return Graph; 41 } 42 43 void Insert(MGraph Graph, Edge E) 44 { 45 Graph->G[E->V1][E->V2].Length= E->Length; 46 Graph->G[E->V2][E->V1].Length= E->Length; 47 Graph->G[E->V1][E->V2].Price = E->Price; 48 Graph->G[E->V2][E->V1].Price = E->Price; 49 } 50 51 MGraph BuildGraph() 52 { 53 MGraph Graph; 54 Edge E; 55 int Nv; 56 scanf("%d", &Nv); 57 Graph = CreateGraph(Nv); 58 scanf("%d %d %d", &Graph->Ne,&Departure,&Destination); 59 for (int i = 0; i < Graph->Ne; i++) 60 { 61 E = (Edge)malloc(sizeof(struct ENode)); 62 scanf("%d %d %d %d\n", &(E->V1), &(E->V2), &(E->Length),&(E->Price)); 63 Insert(Graph, E); 64 } 65 return Graph; 66 } 67 68 int IsEdge(MGraph Graph, int V, int W) 69 { 70 return (Graph->G[V][W].Length < INIFITY) ? 1 : 0; 71 } 72 int Dist[500]; //从源点到某点的路径长度 73 int Price[500]; //从源点到某点的价格 74 int Path[500]; //记录路径 75 int Collected[500]; //记录是否收录 76 int FindMinDist(MGraph Graph) 77 { 78 int MinDist = INIFITY; 79 int V; 80 for (int i = 0; i < Graph->Nv; i++) 81 { 82 if (!Collected[i]&&Dist[i] < MinDist) 83 { 84 MinDist = Dist[i]; 85 V = i; 86 } 87 } 88 if (MinDist < INIFITY) 89 return V; 90 else 91 return 0; 92 } 93 void Dijkstra(MGraph Graph,int S) 94 { 95 //先初始化源点连接的点 96 for (int i = 0; i < Graph->Nv; i++) 97 { 98 Dist[i] = Graph->G[S][i].Length; 99 Price[i] = Graph->G[S][i].Price; 100 if (IsEdge(Graph,S,i)) 101 Path[i] = S; 102 else 103 Path[i] = -1; 104 } 105 106 Collected[S] = 1; 107 Dist[S] = 0; 108 Price[S] = 0; 109 110 while (1) 111 { 112 int V = FindMinDist(Graph); 113 if (!V) 114 break; 115 Collected[V] = 1; 116 for (int i = 0; i < Graph->Nv; i++) 117 { 118 if (!Collected[i] && IsEdge(Graph, V, i)) 119 { 120 if (Dist[V] + Graph->G[V][i].Length < Dist[i]) 121 { 122 Dist[i] = Dist[V] + Graph->G[V][i].Length; 123 Path[i] = V; 124 Price[i] = Price[V] + Graph->G[V][i].Price; 125 } 126 else if (Dist[V] + Graph->G[V][i].Length == Dist[i]) 127 { 128 if (Price[V] + Graph->G[V][i].Price < Price[i]) 129 { 130 Price[i] = Price[V] + Graph->G[V][i].Price; 131 Path[i] = V; 132 } 133 } 134 } 135 136 } 137 } 138 } 139 int main() 140 { 141 MGraph Graph = BuildGraph(); 142 Dijkstra(Graph,Departure); 143 printf("%d %d", Dist[Destination], Price[Destination]); 144 return 0; 145 }
最小生成树(Minimum Spanning Tree)
利用贪心算法
什么是"贪":每一步都要最好的
两种有名的贪心算法
①Prim算法------让一颗小树长大
②Kruskal算法------将森林合并成树
Prim算法 //稠密图合算
Kruskal算法
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<malloc.h> 4 5 //图的邻接矩阵表示法 6 #define MaxVerterNum 100 //最大顶点数 7 #define INFINITY 65535 // 8 typedef int Vertex; //顶点下标表示顶点 9 typedef int WeightType; //边的权值 10 typedef char DataType; //顶点存储的数据类型 11 12 //边的定义 13 typedef struct ENode* PtrToENode; 14 typedef PtrToENode Edge; 15 struct ENode 16 { 17 Vertex V1, V2; //有向边<V1,V2> 18 WeightType Weight; //权重 19 }; 20 21 //图节点的定义 22 typedef struct GNode* PtrToGNode; 23 typedef PtrToGNode MGraph; //以邻接矩阵存储的图类型 24 struct GNode 25 { 26 int Nv; //顶点数 27 int Ne; //边数 28 WeightType G[MaxVerterNum][MaxVerterNum]; //邻接矩阵 29 DataType Data[MaxVerterNum]; //存顶点的数据 30 }; 31 32 MGraph CreateGraph(int VertexNum) 33 {//初始化一个有VerterNum个顶点但没有边的图 34 Vertex V, W; 35 MGraph Graph; 36 37 Graph = (MGraph)malloc(sizeof(struct GNode)); //建立图 38 Graph->Nv = VertexNum; 39 Graph->Ne = 0; 40 //初始化邻接矩阵 41 for (V = 0; V < Graph->Nv; V++) 42 for (W = 0; W < Graph->Nv; W++) 43 Graph->G[V][W] = INFINITY; 44 return Graph; 45 } 46 47 void InsertEdge(MGraph Graph, Edge E) 48 { 49 //插入边<V1,V2> 50 Graph->G[E->V1][E->V2] = E->Weight; 51 //如果是无向图 还要插入边<V2,V1> 52 Graph->G[E->V2][E->V1] = E->Weight; 53 } 54 55 MGraph BuildGraph() 56 { 57 MGraph Graph; 58 Edge E; 59 Vertex V; 60 int Nv, i; 61 62 scanf("%d", &Nv); //读入顶点个数 63 Graph = CreateGraph(Nv); //初始化有Nv个顶点但没有边的图 64 65 scanf("%d", &(Graph->Ne)); //读入边数 66 if (Graph->Ne != 0) //如果有边 67 { 68 E = (Edge)malloc(sizeof(struct ENode)); //建立边节点 69 //读入边 格式为 起点 终点 权重 插入邻接矩阵 70 for (int i = 0; i < Graph->Ne; i++) 71 { 72 scanf("%d %d %d", &(E->V1), &(E->V2), &(E->Weight)); 73 InsertEdge(Graph, E); 74 } 75 } 76 //若顶点有数据 读入数据 77 for (V = 0; V < Graph->Nv; V++) 78 scanf("%c", &(Graph->Data[V])); 79 return Graph; 80 } 81 82 int IsEdge(MGraph Graph, int V, int W) 83 { 84 return (Graph->G[V][W] < INFINITY) ? 1 : 0; 85 } 86 //邻接矩阵存储 Prim最小生成树的算法 87 int Dist[50]; //表示某个点到树的距离 88 int Parent[50]; //利用双亲表示法 :儿子指向父亲 89 Vertex FindMinDist(MGraph Graph) //返回未被收录顶点中 dist为最小的顶点 90 { 91 int MinDist = INFINITY; 92 int V; 93 for (int i = 0; i < Graph->Nv; i++) 94 { 95 if (!Dist[i] && Dist[i] < MinDist) 96 { 97 MinDist = Dist[i]; 98 V = i; 99 } 100 } 101 if (MinDist < INFINITY) 102 return V; 103 else 104 return 0; //返回0做为 找不到顶点的标记 105 } 106 107 int Prim(MGraph Graph,Vertex S) //从S开始 返回顶点数 108 { 109 int Vcount=0; //收录的顶点数 110 for (int i = 0; i < Graph->Nv; i++) //初始化 111 { 112 Dist[i] = Graph->G[S][i]; 113 if (Dist[i] < INFINITY) 114 Parent[i] = S; 115 else 116 Parent[i] = -1; 117 } 118 Dist[S] = 0; //将S收录 119 Vcount++; 120 while (1) 121 { 122 int V = FindMinDist(Graph); 123 if (!V) 124 break; 125 Dist[V] = 0; //将V收录 126 Vcount++; 127 for (int i = 0; i < Graph->Nv; i++) 128 { 129 if (!Dist[i] &&IsEdge(Graph,V,i)) 130 { 131 if(Graph->G[V][i]<Dist[i]) 132 Dist[i] = Graph->G[V][i]; 133 Parent[i] = V; 134 } 135 } 136 } 137 if (Vcount < Graph->Nv) 138 return 0; //收到的顶点不到Nv个 失败 无法成为最小生成树 139 else 140 return Vcount; 141 }
写在最后: 到这基本认识了 树 与 图 (Kruskai算法还没实现) 暑假也到最后一天了 希望自己以后变得越来越好