图结构——邻接表
1 const int max_vertexs=20;
2
3 //边结构
4 class Edge;
5 bool operator < (const Edge&,const Edge&);
6 bool operator <=(const Edge&,const Edge&);
7
8 class Edge{
9 public:
10 Edge(int i=0,int j=0,int k=0):from(i),to(j),weight(k){}
11 friend bool operator < (const Edge&,const Edge&);
12 friend bool operator <=(const Edge&,const Edge&);
13 bool operator > (const Edge&);
14 bool operator >=(const Edge&);
15 void print();
16 public:
17 int from;
18 int to;
19 int weight;
20 };
21
22 //图的邻接矩阵存储表示
23 class Graph{
24 public:
25 Graph(int*,int,bool);
26 Graph(int n,bool);
27 void InsertEdge(int u,int v,int weight=1);
28 void DFS(int v); // 深度优先
29 void BFS(int v); //广度优先
30 void DFS_iter(int v); //深度非递归
31 void Kruskal(); //求最小代价生成树,无向图
32 void Prim(); //求最小代价生成树,无向图
33 void Dijkstra(int v); //单源点最短路径,有向图
34 void Floyd(); //求有向图中任意两点最短距离
35 private:
36 int graph[max_vertexs][max_vertexs];
37 int vertex;
38 bool visited[max_vertexs];
39 bool directed;
40 vector<Edge*> edge_set; //边集合
41 private:
42 void DFS_Rec(int);
43 void visited_reset();
44 void set_edge_set(); //设置边集合
45 vector<Edge *> *get_edge_set(); //获得边集合
46 };
其中边结构,用于记录图中边(包括:边起点,终点,权重)
边结构
1 /************************************************************************/
2 /* 图的边结构 */
3 /************************************************************************/
4 bool Edge::operator >(const Edge &rhs)
5 {
6 return this->weight>rhs.weight;
7 }
8 bool Edge::operator >=(const Edge&rhs)
9 {
10 return this->weight>=rhs.weight;
11 }
12
13 bool operator < (const Edge& lhs,const Edge& rhs)
14 {
15 return lhs.weight<rhs.weight;
16 }
17 bool operator <=(const Edge& lhs,const Edge& rhs)
18 {
19 return lhs.weight<=rhs.weight;
20
21 }
22
23 void Edge::print()
24 {
25 //cout<<from<<"->"<<to<<"("<<weight<<") ";
26 printf("v%d->v%d(%d) ",from,to,weight);
27 }
图成员函数-DFS,BFS,kruskal算法
1 Graph::Graph(int n,bool dir)
2 {
3 if (n>=max_vertexs)
4 {
5 cout<<"error:the number of vertexs beyond Max defined"<<endl;
6 }
7 else
8 {
9
10 memset(graph,0,sizeof(int)*max_vertexs*max_vertexs);
11 memset(visited,0,sizeof(bool)*max_vertexs);
12 vertex=n;
13 directed=dir;
14 }
15
16 }
17
18
19 // 构造函数,array是邻接矩阵,n是顶点数,dir是否是有向图
20 Graph::Graph(int* array,int n,bool dir)
21 {
22 if (n>=max_vertexs)
23 {
24 cout<<"error:the number of vertexs beyond Max defined"<<endl;
25 }
26 else
27 {
28 memset(graph,0,sizeof(int)*max_vertexs*max_vertexs);
29 memset(visited,0,sizeof(bool)*max_vertexs);
30 vertex=n;
31 for(int i=0;i<n;i++)
32 for(int j=0;j<n;j++)
33 {
34 graph[i][j]=*((array+i*n)+j);
35 }
36
37 directed=dir;
38 }
39
40 }
41
42 //插入一条边
43 void Graph::InsertEdge(int u,int v,int weight)
44 {
45 if (directed)
46 {
47 graph[u][v]=weight;
48 }
49 else
50 {
51 graph[u][v]=graph[v][u]=weight;
52 }
53 }
54
55
56 //设置边集合
57 void Graph::set_edge_set()
58 {
59 if (directed)
60 {
61 //有向图
62 for (int i=0;i<vertex;i++)
63 for(int j=0;j<vertex;j++)
64 {
65 if (graph[i][j])
66 {
67 Edge *p=new Edge(i,j,graph[i][j]);
68
69 edge_set.push_back(p);
70 }
71 }
72 }
73 else
74 {
75 //无向图
76 for (int i=0;i<vertex;i++)
77 for (int j=i+1;j<vertex;j++)
78 {
79 if (graph[i][j])
80 {
81 Edge *p=new Edge(i,j,graph[i][j]);
82 edge_set.push_back(p);
83 }
84 }
85
86 }
87 }
88
89 vector<Edge *>* Graph::get_edge_set()
90 {
91 return &this->edge_set;
92 }
93
94
95 //重置visited 数组
96 void Graph::visited_reset()
97 {
98 memset(visited,0,sizeof(bool)*max_vertexs);
99 }
100
101 //depth first search 深度优先搜索
102 void Graph::DFS(int v)
103 {
104 visited_reset();
105 cout<<"depth first search:"<<endl;
106 DFS_Rec(v);
107 cout<<"\nEnd!"<<endl;
108
109 }
110
111 void Graph::DFS_Rec(int v)
112 {
113 cout<<v<<'>';
114 visited[v]=true;
115 for(int i=0;i<vertex;i++)
116 {
117 if(graph[v][i]&&!visited[i])
118 {
119 DFS_Rec(i);
120 }
121 }
122
123 }
124
125 //breadth first search 广度优先搜索
126 void Graph::BFS(int v)
127 {
128 Queue<int> queue;
129 visited_reset();
130 cout<<"breadth first search:"<<endl;
131 queue.push(v);
132 visited[v]=true;
133
134 while (1)
135 {
136 if (queue.isEmpty())
137 break;
138 int top=queue.Front();
139
140 queue.pop();
141 cout<<top<<">";
142
143 //找出与top对头元素,相邻的节点,入队
144 for (int i=0;i<vertex;i++)
145 {
146 if (graph[top][i]&&!visited[i])
147 {
148 queue.push(i);
149 visited[i]=true;
150 }
151 }
152
153 }
154
155 cout<<"\nover!"<<endl;
156
157 }
158
159 //depth first search 深度非递归
160 void Graph::DFS_iter(int v)
161 {
162 visited_reset();
163 stack<int> stack;
164 stack.push(v);
165
166 cout<<"depth first search:"<<endl;
167
168 while(1)
169 {
170 if (stack.isEmpty())
171 break;
172 int top=stack.Top();
173
174 if (!visited[top])
175 {
176 cout<<top<<'>';
177 visited[top]=true;
178 }
179
180 for(int i=0;i<vertex;i++)
181 {
182 //找出top的一个临边
183 if (graph[top][i]&&!visited[i])
184 {
185 stack.push(i);
186 break;
187 }
188 }
189
190 //没有临边,出栈
191 if (i==vertex)
192 {
193 stack.pop();
194 }
195 }
196 cout<<"\nover!"<<endl;
197 }
198
199 //克鲁斯卡尔算法,求最小生成树,找最小的边,且不存在回路.时间复杂度(eloge)
200 void Graph::Kruskal()
201 {
202
203 set_edge_set();
204 Forest ver_set(vertex); //vertexd多个顶点的森林
205 MinHeap<Edge> heap(edge_set.size()+1);
206 for(vector<Edge *>::const_iterator iter=edge_set.begin();iter!=edge_set.end();++iter)
207 {
208 //每个定点插入到堆中(小根堆)
209 heap.Insert(*(*iter));
210 }
211
212 vector<Edge> T; //最小生成树的边数
213
214 cout<<"Kruskal Algorithm : "<<endl;
215
216 while (1)
217 {
218 //找出最小边
219 Edge min_edge=heap.Delete();
220 int from=ver_set.Find(min_edge.from); //最小边from所在的集合
221 int to=ver_set.Find(min_edge.to); //最小边to所在的集合
222
223 if (from==to) //from 和 to 在同一个集合中,存在环路
224 continue;
225 else
226 {
227 //不存在环路,合并from 和to两个集合
228 ver_set.Union(from,to);
229
230 //加入到边集中
231 T.push_back(min_edge);
232 }
233
234 //已找到所有的生成树的边集
235 if (T.size()==vertex-1)
236 {
237 break;
238 }
239
240 if (heap.isEmpty())
241 {
242 //边不够,不能构成最小生成树
243 break;
244 }
245 }
246 if (T.size()==vertex-1)
247 {
248 //输出最小生成树
249 cout<<"the spanning tree is :";
250 for (vector<Edge>::iterator iter1=T.begin();iter1!=T.end();++iter1)
251 {
252 iter1->print();
253 }
254 cout<<endl;
255
256 }
257 else
258 {
259 //没有最小生成树
260 cout<<"\tNo spanning tree"<<endl;
261 }
262
263 cout<<"End"<<endl;
264
265 }
图类成员函数-prim,Dijkstra算法
1 // 普里姆最小生成树
2 void Graph::Prim()
3 {
4 vector<Edge> T;
5 set<int> U; //不在生成树集合中点集
6 set<int> V; //生成树中点集
7 int distance[max_vertexs][2];
8
9 static int MAX=9999;
10
11 //初始化
12 distance[0][0]=-1;
13 distance[0][1]=0;
14 V.insert(0);
15 for (int i=1;i<vertex;i++)
16 {
17 U.insert(i);
18 distance[i][0]=MAX; //表示结点i到V 的最短距离
19 distance[i][1]=0; //i 到V最短几点v
20 }
21
22 int last=0; //上一次加入V的结点
23
24 //找出U中到V中集合最优路径,(u,v) 并加入T中
25 while (true)
26 {
27 int min_cost=MAX;
28 int u=0;
29
30 //从U中到V中最小距离 (u,v)
31 for (set<int>::iterator iter=U.begin();iter!=U.end();++iter)
32 {
33 i=*iter;
34 if (distance[i][0]>0)
35 {
36 if (graph[i][last]>0 && graph[i][last]<distance[i][0])
37 {
38 distance[i][0]=graph[i][last];
39 distance[i][1]=last;
40 }
41 if (distance[i][0]<min_cost)
42 {
43 min_cost=distance[i][0];
44 u=i;
45 }
46 }
47
48 }
49
50 if (min_cost==MAX)
51 {
52 break;
53 }
54 else
55 {
56 //新的u加入到V中,并从U中去点
57 Edge temp(u,distance[u][1],distance[u][0]);
58 distance[u][0]=-1;
59 T.push_back(temp);
60 V.insert(u);
61 U.erase(u);
62 last=u;
63 }
64 }
65
66 cout<<"Prim Algorithm :"<<endl;
67
68 if (T.size()==vertex-1)
69 {
70 //输出最小生成树
71 cout<<"the spanning tree is : ";
72 for (vector<Edge>::iterator iter1=T.begin();iter1!=T.end();++iter1)
73 iter1->print();
74 cout<<endl;
75 }
76 else
77 {
78 //没有最小生成树
79 cout<<"No spanning tree"<<endl;
80 }
81 cout<<"Over!"<<endl;
82
83 }
84
85 //单源点最短路径,从v出发
86 //S表示已找到元素顶点集合, W 表示未找到的集合
87 //W中的每个元素,维持一张找v的最短路径表distance,找出最小的distance[w],将w加入S中,并更新distance表
88 //重复以上,知道所有的顶点都加入S中
89 //可以证明:每次加入S的w,所经过的中间节点(i...k)必在S中。如果x是v-->x-->w,且x不在S中,那么则有v-->x 小于 v--->w,那么x应先背更新到S中,矛盾。
90 void Graph::Dijkstra(int v)
91 {
92 int distance[max_vertexs]; //i到v的最短路径
93 int path[max_vertexs]; //i到v,经过的中间结点
94 bool found[max_vertexs]; //表示i是否已在S中 {i是数组下表,表示顶点编号}
95
96 int MAX_INF=10000;
97
98 //初始化
99 for(int i=0;i<vertex;i++)
100 {
101 distance[i]=MAX_INF;
102 path[i]=v;
103 found[i]=false;
104 }
105 distance[v]=0;
106 found[v]=true;
107 int latest=v; //最新加入S的节点
108
109 while (true)
110 {
111 int min_cost=MAX_INF;
112 //找到未加入的节点
113 for (i=0;i<vertex;i++)
114 {
115 if (!found[i])
116 {
117 //i是没有加入的,更新i最短距离
118 if (graph[latest][i]==0)
119 {
120 graph[latest][i]=MAX_INF;
121 }
122 if (distance[latest]+graph[latest][i]<distance[i])
123 {
124 distance[i]=distance[latest]+graph[latest][i];
125 path[i]=latest;
126 }
127 }
128 }
129
130 //选择最短distance[i]加入到S中
131 for (i=0;i<vertex;i++)
132 {
133 if (!found[i]&&distance[i]<min_cost)
134 {
135 min_cost=distance[i];
136 latest=i;
137 }
138 }
139
140 //所有节点都已加入
141 if (min_cost==MAX_INF)
142 {
143 break;
144 }
145 else
146 {
147 //把latest加入到S中
148 found[latest]=true;
149
150 }
151
152 }
153
154 //输出结果
155 cout<<"Dijkstra Algorithm: "<<endl;
156 for (i=0;i<vertex;i++)
157 {
158 printf("v%d-->v%d: path:",v,i);
159 stack<int> stack;
160 if (distance[i]>=MAX_INF)
161 {
162 cout<<"no path"<<endl;
163 continue;
164 }
165 for(int j=i;j!=v;j=path[j])
166 stack.push(j);
167
168 stack.push(v);
169
170 while (!stack.isEmpty())
171 {
172 printf("v%d,",stack.Top());
173 stack.pop();
174 }
175
176 printf("\t\tlength:%d\n",distance[i]);
177
178 }
179
180 }
View Code
1 //floyd算法,求任意两点间最短距离
2 //算法思想:floyd是动态规划算法,cost[i][j],表示i,j间的最短路径,
3 //对cost不断更新,每次更新是让 i->j 经过k(0,n),
4 //比如:在k次更新时,即i->j 经过k,如果 i->k->j 比 i>k-1>j(上一次k-1时更新)要小,则设置cost[i][j],表示经过k,有最短路径
5 //则样不断重复 k=n 次循环,则可算出,cost[i][j] 最短路径,每个经过的点,都是在(0,n)中,选出最小的。
6 //时间复杂度O(n^3)
7 void Graph::Floyd()
8 {
9 int MAX_INF=10000;
10 int cost[max_vertexs][max_vertexs]; //两点间最短距离代价矩阵
11 int path[max_vertexs][max_vertexs]; //最短距离,经过的中间节点
12
13 int n=vertex;
14 for (int i=0;i<n;i++)
15 for(int j=0;j<n;j++)
16 {
17 cost[i][j]=(graph[i][j]>0||i==j)?graph[i][j]:MAX_INF;
18 path[i][j]=-1;
19 }
20
21 for(int k=0;k<n;k++)
22 {
23 //更细cost,中间经过k节点
24 for (int i=0;i<n;i++)
25 for (int j=0;j<n;j++)
26 {
27 //经过k,cost[i][j]更优化
28 if(cost[i][k]+cost[k][j]<cost[i][j])
29 {
30 cost[i][j]=cost[i][k]+cost[k][j];
31 path[i][j]=k;
32 }
33 }
34 }
35
36 for (i=0;i<n;i++)
37 {
38 for(int j=0;j<n;j++)
39 cout<<cost[i][j]<<' ';
40 cout<<endl;
41 }
42
43 cout<<"**********************"<<endl;
44
45 for (i=0;i<n;i++)
46 {
47 for(int j=0;j<n;j++)
48 cout<<path[i][j]<<' ';
49 cout<<endl;
50 }
51
52 stack<int> stack; //依次进栈2次j,i,表示从路径要经过i->j
53 Queue<int> queue; //重i->j 之间要经过的节点
54
55 for (i=0;i<n;i++)
56 for (int j=0;j<n;j++)
57 {
58 //没有路径
59 if (i==j)
60 {
61 continue;
62 }
63 else if (cost[i][j]>=MAX_INF)
64 {
65 printf("v%d-->v%d : has no path!\n",i,j);
66 continue;
67 }
68 else
69 {
70 //寻找i和j间的最短路径
71 printf("v%d-->v%d : path is:(",i,j);
72
73 //初始化
74 stack.push(j);
75 stack.push(i);
76 queue.push(i);
77
78 int from,to;
79 while (1)
80 {
81 if (stack.isEmpty())
82 {
83 break;
84 }
85
86 from=stack.Top();
87 stack.pop();
88 to=stack.Top();
89 stack.pop();
90
91 int mid=path[from][to];
92 if (mid>0)
93 {
94 //from to 有中间结点
95 stack.push(to);
96 stack.push(mid);
97 stack.push(mid);
98 stack.push(from);
99 }
100 else
101 {
102 queue.push(to);
103 }
104
105 }
106
107 //输出从 i->j 的路径
108 while(!queue.isEmpty())
109 {
110 printf("v%d ",queue.Front());
111 queue.pop();
112 }
113
114 printf(") length : %d\n",cost[i][j]);
115
116 }
117
118 }
119
120 }

浙公网安备 33010602011771号