图、 prim 和 kruskal


数据结构笔记目录

https://hubojing.github.io/2017/11/14/%E6%A0%88/
队列 https://hubojing.github.io/2017/11/12/%E9%98%9F%E5%88%97/
线性表 https://hubojing.github.io/2019/06/12/%E7%BA%BF%E6%80%A7%E8%A1%A8/
https://hubojing.github.io/2017/07/23/%E6%A0%91/

图的基本操作和遍历

Node.h

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef NODE_H
#define NODE_H

class Node
{
public:
Node(char data = 0);
char m_cData;
bool m_bIsVisited;
};

#endif

Node.cpp

1
2
3
4
5
6
7
#include "Node.h"

Node::Node(char data)
{
m_cData = data;
m_bIsVisited = false;
}

CMap.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include"Node.h"
#include <vector>
using namespace std;

class CMap
{
public:
CMap(int capacity);
~CMap();
bool addNode(Node *pNode);
void resetNode();
bool setValueToMatrixForDirectedGraph(int row, int col, int val = 1);//为有向图设置邻接矩阵
bool setValueToMatrixForUndirectedGraph(int row, int col, int val = 1);//为无向图设置邻接矩阵

void printMatrix();

void depthFirstTraverse(int nodeIndex);//深度优先遍历
void breadthFirstTraverse(int nodeIndex);//广义优先遍历

private:
bool getValueFromMatrix(int row, int col, int &val);//从矩阵中获取权值
void breadthFirstTraverseImpl(vector<int> preVec);//广度优先遍历实现函数
private:
int m_iCapacity;//最多可容纳的顶点数
int m_iNodeCount;//已添加的顶点个数
Node *m_pNodeArray;//存放顶点数组
int *m_pMatrix;//存放邻接矩阵
};

CMap.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include "CMap.h"
#include <iostream>
#include <vector>
using namespace std;

CMap::CMap(int capacity)
{
m_iCapacity = capacity;
m_iNodeCount = 0;
m_pNodeArray = new Node[m_iCapacity];
m_pMatrix = new int[m_iCapacity * m_iCapacity];
memset(m_pMatrix, 0, m_iCapacity*m_iCapacity * sizeof(int));
// for (int i = 0; i < m_iCapacity*m_iCapacity; ++i)
// {
// m_pMatrix[i] = 0;
// }
}

CMap::~CMap()
{
delete[]m_pNodeArray;
delete[]m_pMatrix;
}

bool CMap::addNode(Node *pNode)
{
if (pNode == NULL)
{
return false;
}
m_pNodeArray[m_iNodeCount].m_cData = pNode->m_cData;
m_iNodeCount++;
return true;
}

void CMap::resetNode()
{
for (int i = 0; i < m_iNodeCount; ++i)
{
m_pNodeArray[i].m_bIsVisited = false;
}
}

bool CMap::setValueToMatrixForDirectedGraph(int row, int col, int val)
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}
m_pMatrix[row * m_iCapacity + col] = val;
return true;
}

bool CMap::setValueToMatrixForUndirectedGraph(int row, int col, int val)
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}
m_pMatrix[row * m_iCapacity + col] = val;
m_pMatrix[col * m_iCapacity + row] = val;
return true;
}

void CMap::printMatrix()
{
for (int i = 0; i < m_iCapacity; ++i)
{
for (int j = 0; j < m_iCapacity; ++j)
{
cout << m_pMatrix[i * m_iCapacity + j] << " ";
}
cout << endl;
}
}

bool CMap::getValueFromMatrix(int row, int col, int &val)
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}

val = m_pMatrix[row * m_iCapacity + col];
return true;
}

void CMap::depthFirstTraverse(int nodeIndex)
{
int value = 0;
cout << m_pNodeArray[nodeIndex].m_cData << " ";
m_pNodeArray[nodeIndex].m_bIsVisited = true;

//通过邻接矩阵判断是否与其他顶点相连
for (int i = 0; i < m_iCapacity; ++i)
{
getValueFromMatrix(nodeIndex, i, value);
if (value == 1)//判断有弧连接其他顶点
{
//再判断该点是否被访问过
if (m_pNodeArray[i].m_bIsVisited)
{
continue;
}
else
{
depthFirstTraverse(i);
}
}
else
{
continue;
}
}
}

void CMap::breadthFirstTraverse(int nodeIndex)
{
cout << m_pNodeArray[nodeIndex].m_cData << " ";
m_pNodeArray[nodeIndex].m_bIsVisited = true;

vector<int> curVec;
curVec.push_back(nodeIndex);

breadthFirstTraverseImpl(curVec);
}

void CMap::breadthFirstTraverseImpl(vector<int> preVec)
{
int value = 0;
vector<int> curVec;

for (int i = 0; (int)i < preVec.size(); ++i)
{
for (int j = 0; j < m_iCapacity; ++j)
{
getValueFromMatrix(preVec[i], j, value);
if (value != 0)
{
if (m_pNodeArray[j].m_bIsVisited)
{
continue;
}
else
{
cout << m_pNodeArray[j].m_cData << " ";
m_pNodeArray[j].m_bIsVisited = true;

curVec.push_back(j);
}
}
}
}

if (curVec.size() == 0)
{
return;
}
else
{
breadthFirstTraverseImpl(curVec);
}
}

demo.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <stdlib.h>
#include "CMap.h"
using namespace std;

/*
A
/ \
B D
/ \ / \
C - F G - H
\ /
E
*/

int main()
{
CMap *pMap = new CMap(8);

Node *pNodeA = new Node('A');
Node *pNodeB = new Node('B');
Node *pNodeC = new Node('C');
Node *pNodeD = new Node('D');
Node *pNodeE = new Node('E');
Node *pNodeF = new Node('F');
Node *pNodeG = new Node('G');
Node *pNodeH = new Node('H');

pMap->addNode(pNodeA);
pMap->addNode(pNodeB);
pMap->addNode(pNodeC);
pMap->addNode(pNodeD);
pMap->addNode(pNodeE);
pMap->addNode(pNodeF);
pMap->addNode(pNodeG);
pMap->addNode(pNodeH);

pMap->setValueToMatrixForUndirectedGraph(0, 1);
pMap->setValueToMatrixForUndirectedGraph(0, 3);
pMap->setValueToMatrixForUndirectedGraph(1, 2);
pMap->setValueToMatrixForUndirectedGraph(1, 5);
pMap->setValueToMatrixForUndirectedGraph(3, 6);
pMap->setValueToMatrixForUndirectedGraph(3, 7);
pMap->setValueToMatrixForUndirectedGraph(6, 7);
pMap->setValueToMatrixForUndirectedGraph(2, 4);
pMap->setValueToMatrixForUndirectedGraph(4, 5);

pMap->printMatrix();
cout << endl;

pMap->depthFirstTraverse(0);
cout << endl;

pMap->resetNode();
pMap->breadthFirstTraverse(0);
cout << endl;

return 0;
}

输出:

1
2
3
4
5
6
7
8
9
10
11
0 1 0 1 0 0 0 0
1 0 1 0 0 1 0 0
0 1 0 0 1 0 0 0
1 0 0 0 0 0 1 1
0 0 1 0 0 1 0 0
0 1 0 0 1 0 0 0
0 0 0 1 0 0 0 1
0 0 0 1 0 0 1 0

A B C E F D G H
A B D C F G H E

最小生成树算法

普利姆算法

Edge.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef EDGE_H
#define EDGE_H

class Edge
{
public:
Edge(int nodeIndexA = 0, int nodeIndexB = 0, int weightValue = 0);
int m_iNodeIndexA;
int m_iNodeIndexB;
int m_iWeightValue;
bool m_bSelected;

};

#endif

Edge.cpp

1
2
3
4
5
6
7
8
9
#include "Edge.h"

Edge::Edge(int nodeIndexA, int nodeIndexB, int weightValue)
{
m_iNodeIndexA = nodeIndexA;
m_iNodeIndexB = nodeIndexB;
m_iWeightValue = weightValue;
m_bSelected = false;
}

Node.h

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef NODE_H
#define NODE_H

class Node
{
public:
Node(char data = 0);
char m_cData;
bool m_bIsVisited;
};

#endif

Node.cpp

1
2
3
4
5
6
7
#include "Node.h"

Node::Node(char data)
{
m_cData = data;
m_bIsVisited = false;
}

CMap.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include"Node.h"
#include "Edge.h"
#include <vector>
using namespace std;

class CMap
{
public:
CMap(int capacity);
~CMap();
bool addNode(Node *pNode);
void resetNode();
bool setValueToMatrixForDirectedGraph(int row, int col, int val = 1);//为有向图设置邻接矩阵
bool setValueToMatrixForUndirectedGraph(int row, int col, int val = 1);//为无向图设置邻接矩阵

void printMatrix();

void depthFirstTraverse(int nodeIndex);//深度优先遍历
void breadthFirstTraverse(int nodeIndex);//广义优先遍历

void primTree(int nodeIndex);//普里姆生成树

private:
bool getValueFromMatrix(int row, int col, int &val);//从矩阵中获取权值
void breadthFirstTraverseImpl(vector<int> preVec);//广度优先遍历实现函数

int getMinEdge(vector<Edge> edgeVec);

private:
int m_iCapacity;//最多可容纳的顶点数
int m_iNodeCount;//已添加的顶点个数
Node *m_pNodeArray;//存放顶点数组
int *m_pMatrix;//存放邻接矩阵

Edge *m_pEdge;
};

CMap.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#include "CMap.h"
#include <iostream>
#include <vector>
using namespace std;

CMap::CMap(int capacity)
{
m_iCapacity = capacity;
m_iNodeCount = 0;
m_pNodeArray = new Node[m_iCapacity];
m_pMatrix = new int[m_iCapacity * m_iCapacity];
memset(m_pMatrix, 0, m_iCapacity*m_iCapacity * sizeof(int));
// for (int i = 0; i < m_iCapacity*m_iCapacity; ++i)
// {
// m_pMatrix[i] = 0;
// }

m_pEdge = new Edge[m_iCapacity - 1];
}

CMap::~CMap()
{
delete[]m_pNodeArray;
delete[]m_pMatrix;
}

bool CMap::addNode(Node *pNode)
{
if (pNode == NULL)
{
return false;
}
m_pNodeArray[m_iNodeCount].m_cData = pNode->m_cData;
m_iNodeCount++;
return true;
}

void CMap::resetNode()
{
for (int i = 0; i < m_iNodeCount; ++i)
{
m_pNodeArray[i].m_bIsVisited = false;
}
}

bool CMap::setValueToMatrixForDirectedGraph(int row, int col, int val)
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}
m_pMatrix[row * m_iCapacity + col] = val;
return true;
}

bool CMap::setValueToMatrixForUndirectedGraph(int row, int col, int val)
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}
m_pMatrix[row * m_iCapacity + col] = val;
m_pMatrix[col * m_iCapacity + row] = val;
return true;
}

void CMap::printMatrix()
{
for (int i = 0; i < m_iCapacity; ++i)
{
for (int j = 0; j < m_iCapacity; ++j)
{
cout << m_pMatrix[i * m_iCapacity + j] << " ";
}
cout << endl;
}
}

bool CMap::getValueFromMatrix(int row, int col, int &val)
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}

val = m_pMatrix[row * m_iCapacity + col];
return true;
}

void CMap::depthFirstTraverse(int nodeIndex)
{
int value = 0;
cout << m_pNodeArray[nodeIndex].m_cData << " ";
m_pNodeArray[nodeIndex].m_bIsVisited = true;

//通过邻接矩阵判断是否与其他顶点相连
for (int i = 0; i < m_iCapacity; ++i)
{
getValueFromMatrix(nodeIndex, i, value);
if (value == 1)//判断有弧连接其他顶点
{
//再判断该点是否被访问过
if (m_pNodeArray[i].m_bIsVisited)
{
continue;
}
else
{
depthFirstTraverse(i);
}
}
else
{
continue;
}
}
}

void CMap::breadthFirstTraverse(int nodeIndex)
{
cout << m_pNodeArray[nodeIndex].m_cData << " ";
m_pNodeArray[nodeIndex].m_bIsVisited = true;

vector<int> curVec;
curVec.push_back(nodeIndex);

breadthFirstTraverseImpl(curVec);
}

void CMap::breadthFirstTraverseImpl(vector<int> preVec)
{
int value = 0;
vector<int> curVec;

for (int i = 0; (int)i < preVec.size(); ++i)
{
for (int j = 0; j < m_iCapacity; ++j)
{
getValueFromMatrix(preVec[i], j, value);
if (value != 0)
{
if (m_pNodeArray[j].m_bIsVisited)
{
continue;
}
else
{
cout << m_pNodeArray[j].m_cData << " ";
m_pNodeArray[j].m_bIsVisited = true;

curVec.push_back(j);
}
}
}
}

if (curVec.size() == 0)
{
return;
}
else
{
breadthFirstTraverseImpl(curVec);
}
}

void CMap::primTree(int nodeIndex)
{
int value = 0;
int edgeCount = 0;
vector<int> nodeVec;
vector<Edge> edgeVec;

cout << m_pNodeArray[nodeIndex].m_cData << endl;

nodeVec.push_back(nodeIndex);
m_pNodeArray[nodeIndex].m_bIsVisited = true;


while (edgeCount < m_iCapacity - 1)
{
int temp = nodeVec.back();
for (int i = 0; i < m_iCapacity; ++i)
{
getValueFromMatrix(temp, i, value);
if (value != 0)
{
if (m_pNodeArray[i].m_bIsVisited)
{
continue;
}
else
{
Edge edge(temp, i, value);
edgeVec.push_back(edge);
}
}
}

//从可选边集合中找出最小的边
int edgeIndex = getMinEdge(edgeVec);
edgeVec[edgeIndex].m_bSelected = true;

cout << edgeVec[edgeIndex].m_iNodeIndexA << "---" << edgeVec[edgeIndex].m_iNodeIndexB << " ";
cout << edgeVec[edgeIndex].m_iWeightValue << endl;

m_pEdge[edgeCount] = edgeVec[edgeIndex];
edgeCount++;

int nextNodeIndex = edgeVec[edgeIndex].m_iNodeIndexB;

nodeVec.push_back(nextNodeIndex);

m_pNodeArray[nextNodeIndex].m_bIsVisited = true;
cout << m_pNodeArray[nextNodeIndex].m_cData << endl;
}
}

int CMap::getMinEdge(vector<Edge> edgeVec)
{
int minWeight = 0;
int edgeIndex = 0;
int i = 0;
for (; i < edgeVec.size(); ++i)
{
if (!edgeVec[i].m_bSelected)
{
minWeight = edgeVec[i].m_iWeightValue;
edgeIndex = i;
break;
}
}

if (minWeight == 0)
{
return -1;
}

for (; i < edgeVec.size(); ++i)
{
if (edgeVec[i].m_bSelected)
{
continue;
}
else
{
if (minWeight > edgeVec[i].m_iWeightValue)
{
minWeight = edgeVec[i].m_iWeightValue;
edgeIndex = i;
}
}
}

return edgeIndex;
}

demo.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <stdlib.h>
#include "CMap.h"
using namespace std;

/*
A
/ \
B D
/ \ / \
C - F G - H
\ /
E
*/

/*算法例子:
A
/ | \
B - F - E
\ / \ /
C - D

权值:
A-B 6 A-E 5 A-F 1
B-C 3 B-F 2
C-F 8 C-D 7
D-F 4 D-E 2
E-F 9
*/

int main()
{
CMap *pMap = new CMap(6);

Node *pNodeA = new Node('A');
Node *pNodeB = new Node('B');
Node *pNodeC = new Node('C');
Node *pNodeD = new Node('D');
Node *pNodeE = new Node('E');
Node *pNodeF = new Node('F');

pMap->addNode(pNodeA);
pMap->addNode(pNodeB);
pMap->addNode(pNodeC);
pMap->addNode(pNodeD);
pMap->addNode(pNodeE);
pMap->addNode(pNodeF);

pMap->setValueToMatrixForUndirectedGraph(0, 1, 6);
pMap->setValueToMatrixForUndirectedGraph(0, 4, 5);
pMap->setValueToMatrixForUndirectedGraph(0, 5, 1);
pMap->setValueToMatrixForUndirectedGraph(1, 2, 3);
pMap->setValueToMatrixForUndirectedGraph(1, 5, 2);
pMap->setValueToMatrixForUndirectedGraph(2, 5, 8);
pMap->setValueToMatrixForUndirectedGraph(2, 3, 7);
pMap->setValueToMatrixForUndirectedGraph(3, 5, 4);
pMap->setValueToMatrixForUndirectedGraph(3, 4, 2);
pMap->setValueToMatrixForUndirectedGraph(4, 5, 9);

pMap->primTree(0);

return 0;
}

输出:

1
2
3
4
5
6
7
8
9
10
11
A
0---5 1
F
5---1 2
B
1---2 3
C
5---3 4
D
3---4 2
E

克鲁斯卡尔算法

Node.h

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef NODE_H
#define NODE_H

class Node
{
public:
Node(char data = 0);
char m_cData;
bool m_bIsVisited;
};

#endif

Node.cpp

1
2
3
4
5
6
7
#include "Node.h"

Node::Node(char data)
{
m_cData = data;
m_bIsVisited = false;
}

Edge.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef EDGE_H
#define EDGE_H

class Edge
{
public:
Edge(int nodeIndexA = 0, int nodeIndexB = 0, int weightValue = 0);
int m_iNodeIndexA;
int m_iNodeIndexB;
int m_iWeightValue;
bool m_bSelected;

};

#endif

Edge.cpp

1
2
3
4
5
6
7
8
9
#include "Edge.h"

Edge::Edge(int nodeIndexA, int nodeIndexB, int weightValue)
{
m_iNodeIndexA = nodeIndexA;
m_iNodeIndexB = nodeIndexB;
m_iWeightValue = weightValue;
m_bSelected = false;
}

CMap.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include"Node.h"
#include "Edge.h"
#include <vector>
using namespace std;

class CMap
{
public:
CMap(int capacity);
~CMap();
bool addNode(Node *pNode);
void resetNode();
bool setValueToMatrixForDirectedGraph(int row, int col, int val = 1);//为有向图设置邻接矩阵
bool setValueToMatrixForUndirectedGraph(int row, int col, int val = 1);//为无向图设置邻接矩阵

void printMatrix();

void depthFirstTraverse(int nodeIndex);//深度优先遍历
void breadthFirstTraverse(int nodeIndex);//广义优先遍历

void primTree(int nodeIndex);
void kruskalTree();


private:
bool getValueFromMatrix(int row, int col, int &val);//从矩阵中获取权值
void breadthFirstTraverseImpl(vector<int> preVec);//广度优先遍历实现函数

int getMinEdge(vector<Edge> edgeVec);//获取最小边
bool isInSet(vector<int> nodeSet, int target);//判断顶点是否在点集合中
void mergeNodeSet(vector<int> &nodeSetA, vector<int> nodeSetB);//合并两个顶点集合

private:
int m_iCapacity;//最多可容纳的顶点数
int m_iNodeCount;//已添加的顶点个数
Node *m_pNodeArray;//存放顶点数组
int *m_pMatrix;//存放邻接矩阵

Edge *m_pEdge;
};

CMap.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
#include "CMap.h"
#include <iostream>
#include <vector>
using namespace std;

CMap::CMap(int capacity)
{
m_iCapacity = capacity;
m_iNodeCount = 0;
m_pNodeArray = new Node[m_iCapacity];
m_pMatrix = new int[m_iCapacity * m_iCapacity];
memset(m_pMatrix, 0, m_iCapacity*m_iCapacity * sizeof(int));
// for (int i = 0; i < m_iCapacity*m_iCapacity; ++i)
// {
// m_pMatrix[i] = 0;
// }

m_pEdge = new Edge[m_iCapacity - 1];
}

CMap::~CMap()
{
delete[]m_pNodeArray;
delete[]m_pMatrix;
delete[]m_pEdge;
}

bool CMap::addNode(Node *pNode)
{
if (pNode == NULL)
{
return false;
}
m_pNodeArray[m_iNodeCount].m_cData = pNode->m_cData;
m_iNodeCount++;
return true;
}

void CMap::resetNode()
{
for (int i = 0; i < m_iNodeCount; ++i)
{
m_pNodeArray[i].m_bIsVisited = false;
}
}

bool CMap::setValueToMatrixForDirectedGraph(int row, int col, int val)
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}
m_pMatrix[row * m_iCapacity + col] = val;
return true;
}

bool CMap::setValueToMatrixForUndirectedGraph(int row, int col, int val)
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}
m_pMatrix[row * m_iCapacity + col] = val;
m_pMatrix[col * m_iCapacity + row] = val;
return true;
}

void CMap::printMatrix()
{
for (int i = 0; i < m_iCapacity; ++i)
{
for (int j = 0; j < m_iCapacity; ++j)
{
cout << m_pMatrix[i * m_iCapacity + j] << " ";
}
cout << endl;
}
}

bool CMap::getValueFromMatrix(int row, int col, int &val)
{
if (row < 0 || row >= m_iCapacity)
{
return false;
}
if (col < 0 || col >= m_iCapacity)
{
return false;
}

val = m_pMatrix[row * m_iCapacity + col];
return true;
}

void CMap::depthFirstTraverse(int nodeIndex)
{
int value = 0;
cout << m_pNodeArray[nodeIndex].m_cData << " ";
m_pNodeArray[nodeIndex].m_bIsVisited = true;

//通过邻接矩阵判断是否与其他顶点相连
for (int i = 0; i < m_iCapacity; ++i)
{
getValueFromMatrix(nodeIndex, i, value);
if (value == 1)//判断有弧连接其他顶点
{
//再判断该点是否被访问过
if (m_pNodeArray[i].m_bIsVisited)
{
continue;
}
else
{
depthFirstTraverse(i);
}
}
else
{
continue;
}
}
}

void CMap::breadthFirstTraverse(int nodeIndex)
{
cout << m_pNodeArray[nodeIndex].m_cData << " ";
m_pNodeArray[nodeIndex].m_bIsVisited = true;

vector<int> curVec;
curVec.push_back(nodeIndex);

breadthFirstTraverseImpl(curVec);
}

void CMap::breadthFirstTraverseImpl(vector<int> preVec)
{
int value = 0;
vector<int> curVec;

for (int i = 0; (int)i < preVec.size(); ++i)
{
for (int j = 0; j < m_iCapacity; ++j)
{
getValueFromMatrix(preVec[i], j, value);
if (value != 0)
{
if (m_pNodeArray[j].m_bIsVisited)
{
continue;
}
else
{
cout << m_pNodeArray[j].m_cData << " ";
m_pNodeArray[j].m_bIsVisited = true;

curVec.push_back(j);
}
}
}
}

if (curVec.size() == 0)
{
return;
}
else
{
breadthFirstTraverseImpl(curVec);
}
}

void CMap::primTree(int nodeIndex)
{
int value = 0;
int edgeCount = 0;
vector<int> nodeVec;
vector<Edge> edgeVec;

cout << m_pNodeArray[nodeIndex].m_cData << endl;

nodeVec.push_back(nodeIndex);
m_pNodeArray[nodeIndex].m_bIsVisited = true;


while (edgeCount < m_iCapacity - 1)
{
int temp = nodeVec.back();
for (int i = 0; i < m_iCapacity; ++i)
{
getValueFromMatrix(temp, i, value);
if (value != 0)
{
if (m_pNodeArray[i].m_bIsVisited)
{
continue;
}
else
{
Edge edge(temp, i, value);
edgeVec.push_back(edge);
}
}
}

//从可选边集合中找出最小的边
int edgeIndex = getMinEdge(edgeVec);
edgeVec[edgeIndex].m_bSelected = true;

cout << edgeVec[edgeIndex].m_iNodeIndexA << "---" << edgeVec[edgeIndex].m_iNodeIndexB << " ";
cout << edgeVec[edgeIndex].m_iWeightValue << endl;

m_pEdge[edgeCount] = edgeVec[edgeIndex];
edgeCount++;

int nextNodeIndex = edgeVec[edgeIndex].m_iNodeIndexB;

nodeVec.push_back(nextNodeIndex);

m_pNodeArray[nextNodeIndex].m_bIsVisited = true;
cout << m_pNodeArray[nextNodeIndex].m_cData << endl;
}
}

int CMap::getMinEdge(vector<Edge> edgeVec)
{
int minWeight = 0;
int edgeIndex = 0;
int i = 0;
for (; i < edgeVec.size(); ++i)
{
if (!edgeVec[i].m_bSelected)
{
minWeight = edgeVec[i].m_iWeightValue;
edgeIndex = i;
break;
}
}

if (minWeight == 0)
{
return -1;
}

for (; i < edgeVec.size(); ++i)
{
if (edgeVec[i].m_bSelected)
{
continue;
}
else
{
if (minWeight > edgeVec[i].m_iWeightValue)
{
minWeight = edgeVec[i].m_iWeightValue;
edgeIndex = i;
}
}
}

return edgeIndex;
}

void CMap::kruskalTree()
{
int value = 0;
int edgeCount = 0;

//定义存放结点集合的数组
vector<vector<int>> nodeSets;


//第一步:取出所有边
vector<Edge> edgeVec;
for (int i = 0; i < m_iCapacity; ++i)
{
for (int j = i + 1; j < m_iCapacity; ++j)
{
getValueFromMatrix(i, j, value);
if (value != 0)
{
Edge edge(i, j, value);
edgeVec.push_back(edge);
}
}
}
//1.找到算法结束条件
while (edgeCount < m_iCapacity - 1)
{
//2.从边集合中找到最小边
int minEdgeIndex = getMinEdge(edgeVec);
edgeVec[minEdgeIndex].m_bSelected = true;
//3.找出最小边连接的点
int nodeAIndex = edgeVec[minEdgeIndex].m_iNodeIndexA;
int nodeBIndex = edgeVec[minEdgeIndex].m_iNodeIndexB;

bool nodeAIsInSet = false;
bool nodeBIsInSet = false;

int nodeAInSetLabel = -1;
int nodeBInSetLabel = -1;

//4.找出点所在的点集合
for (int i = 0; i < nodeSets.size(); ++i)
{
nodeAIsInSet = isInSet(nodeSets[i], nodeAIndex);
if (nodeAIsInSet)
{
nodeAIsInSet = i;
}
}

for (int i = 0; i < nodeSets.size(); ++i)
{
nodeBIsInSet = isInSet(nodeSets[i], nodeBIndex);
if (nodeBIsInSet)
{
nodeBIsInSet = i;
}
}

//5.根据点所在集合的不同做出不同处理
if (nodeAInSetLabel == -1 && nodeBInSetLabel == -1)
{
vector<int> vec;
vec.push_back(nodeAIndex);
vec.push_back(nodeBIndex);
nodeSets.push_back(vec);
}
else if (nodeAInSetLabel == -1 && nodeBInSetLabel != -1)
{
nodeSets[nodeBInSetLabel].push_back(nodeAIndex);
}
else if (nodeAInSetLabel != -1 && nodeBInSetLabel == -1)
{
nodeSets[nodeBInSetLabel].push_back(nodeBIndex);
}
else if (nodeAInSetLabel != -1 && nodeBInSetLabel != -1 && nodeAInSetLabel != nodeBInSetLabel)
{
mergeNodeSet(nodeSets[nodeAInSetLabel], nodeSets[nodeBInSetLabel]);
for (int i = 0; i < (int)nodeSets.size() - 1; ++i)
{
nodeSets[i] = nodeSets[i + 1];
}
}
else if (nodeAInSetLabel != -1 && nodeBInSetLabel != -1 && nodeAInSetLabel == nodeBInSetLabel)
{
continue;
}

m_pEdge[edgeCount] = edgeVec[minEdgeIndex];
edgeCount++;

cout << edgeVec[minEdgeIndex].m_iNodeIndexA << "---" << edgeVec[minEdgeIndex].m_iNodeIndexB << " ";
cout << edgeVec[minEdgeIndex].m_iWeightValue << endl;
}
}

bool CMap::isInSet(vector<int> nodeSet, int target)
{
for (int i = 0; i < nodeSet.size(); ++i)
{
if (nodeSet[i] == target)
{
return true;
}
}
return false;
}

void CMap::mergeNodeSet(vector<int> &nodeSetA, vector<int> nodeSetB)
{
for (int i = 0; i < nodeSetB.size(); ++i)
{
nodeSetA.push_back(nodeSetB[i]);
}
}

demo.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <stdlib.h>
#include "CMap.h"
using namespace std;

/*
A
/ \
B D
/ \ / \
C - F G - H
\ /
E
*/

/*算法例子:
A
/ | \
B - F - E
\ / \ /
C - D

权值:
A-B 6 A-E 5 A-F 1
B-C 3 B-F 2
C-F 8 C-D 7
D-F 4 D-E 2
E-F 9
*/

int main()
{
CMap *pMap = new CMap(6);

Node *pNodeA = new Node('A');
Node *pNodeB = new Node('B');
Node *pNodeC = new Node('C');
Node *pNodeD = new Node('D');
Node *pNodeE = new Node('E');
Node *pNodeF = new Node('F');

pMap->addNode(pNodeA);
pMap->addNode(pNodeB);
pMap->addNode(pNodeC);
pMap->addNode(pNodeD);
pMap->addNode(pNodeE);
pMap->addNode(pNodeF);

pMap->setValueToMatrixForUndirectedGraph(0, 1, 6);
pMap->setValueToMatrixForUndirectedGraph(0, 4, 5);
pMap->setValueToMatrixForUndirectedGraph(0, 5, 1);
pMap->setValueToMatrixForUndirectedGraph(1, 2, 3);
pMap->setValueToMatrixForUndirectedGraph(1, 5, 2);
pMap->setValueToMatrixForUndirectedGraph(2, 5, 8);
pMap->setValueToMatrixForUndirectedGraph(2, 3, 7);
pMap->setValueToMatrixForUndirectedGraph(3, 5, 4);
pMap->setValueToMatrixForUndirectedGraph(3, 4, 2);
pMap->setValueToMatrixForUndirectedGraph(4, 5, 9);

// pMap->primTree(0);
pMap->kruskalTree();


return 0;
}

输出:

1
2
3
4
5
0---5 1
1---5 2
3---4 2
1---2 3
3---5 4