数据结构学习第二十天

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 }
View Code

 

 

 

最小生成树(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 }
View Code

 

 

写在最后: 到这基本认识了 树 与 图 (Kruskai算法还没实现) 暑假也到最后一天了 希望自己以后变得越来越好

posted @ 2019-09-04 21:14  57one  阅读(157)  评论(0编辑  收藏  举报