--------------
1)图存储结构
--------------
typedef int WeightType; //权重类型
typedef int VertexType; //顶点类型
const int MaxVertexNum = 10; //最大顶点
const int MaxEdgeNum = 10; //最大边数
const WeightType maxvalue = 1000; //最大值1000
//图数组存储
typedef VertexType vexlist[MaxVertexNum];//顶点向量
typedef int adjmatrix[MaxVertexNum][MaxVertexNum];
//图链接表存储
struct edgenode {
int adjvex; //结点序号
WeightType weight; //权重
edgenode* next; //指向下一个结点
};
typedef edgenode* adjlist[MaxVertexNum];
//图边集存储
struct edge{
int fromvex; //起始点
int endvex; //终点
WeightType weight;//权重
};
typedef edge edgeset[MaxEdgeNum];
---------------
2)图的遍历
---------------
1 #include <iostream>
2 #include <cstdlib>
3 #include <string>
4
5
6 using namespace std;
7
8 typedef int VertexType;
9 typedef int WeightType;
10
11 const int MaxVertexNum = 10;
12 const WeightType MaxValue = 1000;
13
14 typedef VertexType vexlist[MaxVertexNum];
15 typedef int adjmatrix[MaxVertexNum][MaxVertexNum];
16
17
18 void dfsMatrix(adjmatrix GA,int i, int n,bool * visited)
19 {
20 cout<<i<<' ';
21 visited[i] = true;
22 for (int j = 0; j < n; ++j)
23 {
24 if(GA[i][j]!=0&&GA[i][j]!=MaxValue&&!visited[j])
25 dfsMatrix(GA,j,n,visited);
26 }
27 }
28
29 void bfsMatrix(adjmatrix GA,int i,int n,bool* visited)
30 {
31 const int maxsize = 30;
32 int q[maxsize] = {0};
33 int front = 0,rear = 0;
34 cout<< i <<' ';
35 visited[i] = true;
36 q[++rear] = i;
37 while (front != rear)
38 {
39 front = (front+1)%maxsize;
40 int k = q[front];
41 for (int j = 0; j < n; ++j)
42 {
43 if (GA[k][j]!=0&&GA[k][j]!=MaxValue&&!visited[j])
44 {
45 cout<<j<<' ';
46 visited[j] = true;
47 rear = rear+1%maxsize;
48 q[rear] = j;
49 }//if
50 }//for
51 }//while
52 }
53
54 int main(int argc, char * argv[])
55 {
56 cout << "======= DFS ====== " << endl;
57 for (i = 0; i < n; ++i)
58 {
59 visited[i] = false;
60 }
61 dfsMatrix(ga,0,n,visited);
62 cout<<endl;
63
64 cout << "======= BFS ====== " << endl;
65 for (i = 0; i < n; ++i)
66 {
67 visited[i] = false;
68 }
69 bfsMatrix(ga,0,n,visited);
70 cout<<endl;
71
72 return 0;
73 }
-------------------
3)图的连通性问题(最小生成树)
-------------------
1.prim算法:(适合求稠密图求最小生成树)(O(n^2))
Prim算法的基本思想是:
(1) 在图G=(V, E) (V表示顶点,E表示边)中,从集合V中任取一个顶点(例如取顶点v0)放入集合 U中,这时 U={v0},集合T(E)为空。
(2) 从v0出发寻找与U中顶点相邻(另一顶点在V中)权值最小的边的另一顶点v1,并使v1加入U。即U={v0,v1 },同时将该边加入集合T(E)中。
(3) 重复(2),直到U = V为止。
这时T(E)中有n-1条边,T = (U, T(E))就是一棵最小生成树。
1 #include <iostream>
2 #include <cstring>
3 #include <fstream>
4
5 using namespace std;
6
7 typedef int WeightType;
8 typedef int VertexType;
9 const int MaxVertexNum = 10;
10 const int MaxEdgeNum = 10;
11 const WeightType maxvalue = 100;
12 typedef VertexType vexlist[MaxVertexNum];
13 typedef int adjmatrix[MaxVertexNum][MaxVertexNum];
14
15 struct edge{
16 int fromvex;
17 int endvex;
18 WeightType weight;
19 };
20 typedef edge edgeset[MaxEdgeNum];
21
22 void mst_prim(adjmatrix GA, edgeset CT,int n)
23 {
24 //利用普里姆算法从顶点v0出发求出用邻接矩阵GA表示的图的最小生成树,
25 //最小生成树的边集存于数组CT中
26 int i,j,k,min,t,m,w;
27 //v0 initial CT
28 for (i = 0; i < n-1; ++i)
29 {
30 CT[i].fromvex = 0;
31 CT[i].endvex = i+1;
32 CT[i].weight = GA[0][i+1];
33 }
34 //进行n-1循环,每次求出最小生成树中的第k条边
35 for(k = 1;k<n;k++)
36 {
37 //从CT[k-1]至CT[n-1]中查找最短边CT[m]
38 min = CT[k-1].weight;//先假设CT[k-1]为最短边
39 m=k-1;
40 for (j = k-1; j < n-1; ++j)
41 {
42 if (CT[j].weight<min)
43 {
44 min = CT[j].weight;
45 m = j;
46 }
47 }
48 swap(CT[k-1] , CT[m]);//把最短边调到k-1下标的位置
49 j = CT[k-1].endvex;//把新并入最小生成树T中的顶点的顶点序号赋值给j
50 /*
51 *-------------------------------------
52 *修改LW中的有关边,使T中到T外的每一个顶点各保持一条到目前为止最短边
53 *CT[0]~CT[K-2](已经求得的最短边): CT[K]: CT[K-1]~CT[n-1]
54 *对于T:n-(k+1)中的每个顶点t,若(j,t)边上的权值小于原来已经保留从T
55 *到顶点t的最短边的权值,则用(j,t)修改之,使得从T中到T外顶点t的最短边
56 *为(j,t),否则原有最短边保持不变。
57 *-------------------------------------
58 */
59 for (i = k; i < n-1; ++i)
60 {
61 t=CT[i].endvex;
62 w=GA[j][t];
63 if(w<CT[i].weight){
64 CT[i].weight = w;
65 CT[i].fromvex = j;
66 }
67 }//inner for
68 }//outer for
69 }
70
71 void mst_kruskal(edgeset GE,edgeset CT,int n)
72 {
73 int i,j;
74 //用二维数组s作为集合使用,其中每一行元素
75 //s[i][0]~s[i][n-1]用来表示一个集合,若s[i][t]==1
76 //则表示v[t]顶点属于该集合,否则不属于s[i]集合
77 adjmatrix s;
78
79 for (i = 0; i < n; ++i)
80 {
81 for (j = 0; j < n; ++j)
82 {
83 if(i ==j) s[i][j] = true;
84 else s[i][j] = false;
85 }
86 }
87
88 int k =1;//k表示待获取的最小生成树中的边数,初值为1
89 int d = 0;//d表示GE中待扫描边元素的下标位置,初值为0
90 int m1,m2;
91
92 while (k<n)
93 {
94 /*for(i=0;i<n;i++)
95 {//求出边GE[d]的两个顶点所在集合的序号m1和m2]
96 for(j=0;j<n;j++)
97 {
98 if(GE[d].fromvex==j&&s[i][j]==1)//找起点
99 m1=i;
100 if(GE[d].endvex==j&&s[i][j]==1)//找终点
101 m2=i;
102 }
103
104 }*/
105 //可以把上面的二重for循环改良成如下的一重for循环
106 for (i = 0; i < n; ++i)
107 {
108 if(s[i][GE[d].fromvex] == true) m1 =i;
109 if(s[i][GE[d].endvex] == true) m2 = i;
110 }
111
112 if (m1 != m2)
113 {
114 //若两集合序号不等,则表明GE[d]是生成树中的一条边,
115 //应将它加入到数组C中
116 CT[k-1] = GE[d];
117 k++;
118 for (j = 0; j < n; ++j)
119 {//合并两个集合,并将另一个置为空集
120 s[m1][j] = s[m1][j]||s[m2][j];
121 s[m2][j] = false;
122 }
123 }
124 d++;//d后移一个位置,以便扫描GE中的下一条边
125 }
126 }
127
128 int main(int argc, char * argv[])
129 {
130 ifstream cin ("aaa.txt");
131 adjmatrix ga;
132 edgeset ge;
133 edgeset ct;
134 int vexnum;
135 int edgenum;
136 int casenum;
137 int cn = 0;
138 cin>>casenum;
139 cout<<"There are "<<casenum<<" cases;"<<endl;
140 while(cin>>vexnum)
141 {
142 if(88 == vexnum)break;
143 cn++;
144 for(int i = 0 ;i<vexnum;i++)
145 {
146 for(int j = 0; j<vexnum;j++)
147 {
148 cin>>ga[i][j];
149 }
150 }
151 mst_prim(ga,ct,vexnum);
152 cout<<"The "<<cn<<"th case:"<<endl;
153 for(int i=0;i<vexnum-1;i++)
154 {
155 cout<<" 起点:"<<ct[i].fromvex<<" "
156 <<"终点:"<<ct[i].endvex<<" "
157 <<"权值:"<<ct[i].weight<<endl;
158 }
159 }
160 puts("--------------------------");
161 cin>>vexnum>>edgenum;
162 for (int i = 0;i<edgenum;i++)
163 {
164 cin>>ge[i].fromvex>>ge[i].endvex>>ge[i].weight;
165 }
166 mst_kruskal(ge,ct,vexnum);
167 for(int i=0;i<vexnum-1;i++)
168 {
169 cout<<" 起点:"<<ct[i].fromvex<<" "
170 <<"终点:"<<ct[i].endvex<<" "
171 <<"权值:"<<ct[i].weight<<endl;
172 }
173 return 0;
174 }
--------------------------
There are 3 cases;
The 1th case:
起点:0 终点:3 权值:5
起点:3 终点:1 权值:3
起点:3 终点:5 权值:7
起点:5 终点:2 权值:2
起点:2 终点:4 权值:6
起点:3 终点:6 权值:15
The 2th case:
起点:0 终点:2 权值:3
起点:2 终点:1 权值:4
The 3th case:
起点:0 终点:2 权值:3
起点:2 终点:1 权值:4
-------------------------
起点:0 终点:4 权值:4
起点:1 终点:2 权值:5
起点:1 终点:3 权值:8
起点:1 终点:5 权值:12
起点:0 终点:1 权值:18
---------------------------