Skip to content

Commit 29657e4

Browse files
committed
graph with weights finished
1 parent fe6d907 commit 29657e4

File tree

7 files changed

+395
-0
lines changed

7 files changed

+395
-0
lines changed

graph-theory/06-BFS-in-graph/main

-130 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#include <iostream>
2+
#include <cassert>
3+
#include <vector>
4+
#include "Edge.h"
5+
6+
using namespace std;
7+
// 稠密图 - 邻接矩阵
8+
template <typename Weight>
9+
10+
class DenseGraph
11+
{
12+
private:
13+
int n, m; // 节点数和边数
14+
bool directed; // 是否为有向图
15+
vector<vector<Edge<Weight> *> > g; // 图的具体数据
16+
17+
public:
18+
// 构造函数
19+
DenseGraph(int n, bool directed)
20+
{
21+
assert(n >= 0);
22+
this->n = n;
23+
this->m = 0;
24+
this->directed = directed;
25+
for (int i = 0; i < n; i++)
26+
{
27+
g.push_back(vector<Edge<Weight> *>(n, NULL));
28+
}
29+
}
30+
~DenseGraph() {
31+
for(int i = 0; i < n; i++)
32+
{
33+
for(int j = 0; j < n; j++)
34+
{
35+
if(g[i][j] != NULL)
36+
delete g[i][j];
37+
}
38+
}
39+
}
40+
41+
int V() { return n; }
42+
int E() { return m; }
43+
44+
void addEdge(int v, int w, Weight weight)
45+
{
46+
assert(v >= 0 && v < n);
47+
assert(w >= 0 && w < n);
48+
if (hasEdge(v, w))
49+
{
50+
delete g[v][w];
51+
if (!directed)
52+
delete g[w][v];
53+
m--;
54+
}
55+
g[v][w] = new Edge<Weight>(v, w, weight);
56+
if (!directed)
57+
g[w][v] = new Edge<Weight>(w, v, weight);
58+
m++;
59+
}
60+
61+
bool hasEdge(int v, int w)
62+
{
63+
assert(v >= 0 && v < n);
64+
assert(w >= 0 && w < n);
65+
return g[v][w] != NULL;
66+
}
67+
// 打印邻接矩阵
68+
void show()
69+
{
70+
for (int i = 0; i < n; i++)
71+
for (int j = 0; j < n; j++)
72+
if(g[i][j])
73+
cout << g[i][j]->wt() << "\t";
74+
else
75+
cout<<"NULL\t";
76+
cout << endl;
77+
}
78+
79+
class adjIterator
80+
{
81+
private:
82+
DenseGraph &G;
83+
int v;
84+
int index;
85+
86+
public:
87+
adjIterator(DenseGraph &graph, int v) : G(graph)
88+
{
89+
assert(v >= 0 && v < G.n);
90+
this->v = v;
91+
this->index = -1;
92+
}
93+
~adjIterator() {}
94+
// 返回图G中与顶点v相连接的第一个顶点
95+
Edge<Weight>* begin()
96+
{
97+
// 索引从-1开始, 因为每次遍历都需要调用一次next()
98+
index = -1;
99+
return next();
100+
}
101+
Edge<Weight>* next()
102+
{
103+
for (index += 1; index < G.V(); index++)
104+
if (G.g[v][index])
105+
return G.g[v][index];
106+
return NULL;
107+
}
108+
bool end()
109+
{
110+
return index >= G.V();
111+
}
112+
};
113+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//
2+
// Created by 3zz on 9/23/16.
3+
//
4+
5+
#ifndef INC_01_WEIGHTED_GRAPH_EDGE_H
6+
#define INC_01_WEIGHTED_GRAPH_EDGE_H
7+
8+
#include <iostream>
9+
#include <cassert>
10+
11+
using namespace std;
12+
13+
//
14+
template<typename Weight>
15+
class Edge{
16+
private:
17+
int a,b; // 边的两个端点
18+
Weight weight; // 边的权值
19+
20+
public:
21+
// 构造函数
22+
Edge(int a, int b, Weight weight){
23+
this->a = a;
24+
this->b = b;
25+
this->weight = weight;
26+
}
27+
// 空的构造函数, 所有的成员变量都取默认值
28+
Edge(){}
29+
30+
~Edge(){}
31+
32+
int v(){ return a;} // 返回第一个顶点
33+
int w(){ return b;} // 返回第二个顶点
34+
Weight wt(){ return weight;} // 返回权值
35+
36+
// 给定一个顶点, 返回另一个顶点
37+
int other(int x){
38+
assert( x == a || x == b );
39+
return x == a ? b : a;
40+
}
41+
42+
// 输出边的信息
43+
friend ostream& operator<<(ostream &os, const Edge &e){
44+
os<<e.a<<"-"<<e.b<<": "<<e.weight;
45+
return os;
46+
}
47+
48+
// 边的大小比较, 是对边的权值的大小比较
49+
bool operator<(Edge<Weight>& e){
50+
return weight < e.wt();
51+
}
52+
bool operator<=(Edge<Weight>& e){
53+
return weight <= e.wt();
54+
}
55+
bool operator>(Edge<Weight>& e){
56+
return weight > e.wt();
57+
}
58+
bool operator>=(Edge<Weight>& e){
59+
return weight >= e.wt();
60+
}
61+
bool operator==(Edge<Weight>& e){
62+
return weight == e.wt();
63+
}
64+
};
65+
66+
#endif //INC_01_WEIGHTED_GRAPH_EDGE_H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include <iostream>
2+
#include <string>
3+
#include <fstream>
4+
#include <cassert>
5+
#include <sstream>
6+
7+
using namespace std;
8+
9+
template <typename Graph, typename Weight>
10+
11+
class ReadGraph{
12+
13+
public:
14+
ReadGraph(Graph &graph, const string &filename){
15+
ifstream file(filename);
16+
string line;
17+
int V,E;
18+
19+
assert( file.is_open());
20+
assert(getline(file, line));
21+
22+
stringstream ss(line);
23+
ss>>V>>E;
24+
25+
assert(V == graph.V());
26+
for(int i = 0; i < E; i++)
27+
{
28+
assert(getline(file,line));
29+
stringstream ss(line);
30+
31+
int a,b;
32+
Weight w;
33+
ss>>a>>b>>w;
34+
assert(a >= 0 && a< V);
35+
assert(b >= 0 && b < V);
36+
graph.addEdge(a,b,w);
37+
}
38+
}
39+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//
2+
// Created by 3zz on 9/23/16.
3+
//
4+
5+
#ifndef INC_01_WEIGHTED_GRAPH_SPARSEGRAPH_H
6+
#define INC_01_WEIGHTED_GRAPH_SPARSEGRAPH_H
7+
8+
#include <iostream>
9+
#include <vector>
10+
#include <cassert>
11+
#include "Edge.h"
12+
13+
using namespace std;
14+
15+
// 稀疏图 - 邻接表
16+
template <typename Weight>
17+
class SparseGraph
18+
{
19+
20+
private:
21+
int n, m; // 节点数和边数
22+
bool directed; // 是否为有向图
23+
vector<vector<Edge<Weight> *> > g; // 图的具体数据
24+
25+
public:
26+
// 构造函数
27+
SparseGraph(int n, bool directed)
28+
{
29+
assert(n >= 0);
30+
this->n = n;
31+
this->m = 0; // 初始化没有任何边
32+
this->directed = directed;
33+
// g初始化为n个空的vector, 表示每一个g[i]都为空, 即没有任和边
34+
g = vector<vector<Edge<Weight> *> >(n, vector<Edge<Weight> *>());
35+
}
36+
37+
// 析构函数
38+
~SparseGraph()
39+
{
40+
for (int i = 0; i < n; i++)
41+
for (int j = 0; j < g[i].size(); j++)
42+
delete g[i][j];
43+
}
44+
45+
int V() { return n; } // 返回节点个数
46+
int E() { return m; } // 返回边的个数
47+
48+
// 向图中添加一个边, 权值为weight
49+
void addEdge(int v, int w, Weight weight)
50+
{
51+
assert(v >= 0 && v < n);
52+
assert(w >= 0 && w < n);
53+
54+
// 注意, 由于在邻接表的情况, 查找是否有重边需要遍历整个链表
55+
// 我们的程序允许重边的出现
56+
57+
g[v].push_back(new Edge<Weight>(v, w, weight));
58+
if (v != w && !directed)
59+
g[w].push_back(new Edge<Weight>(w, v, weight));
60+
m++;
61+
}
62+
63+
// 验证图中是否有从v到w的边
64+
bool hasEdge(int v, int w)
65+
{
66+
assert(v >= 0 && v < n);
67+
assert(w >= 0 && w < n);
68+
for (int i = 0; i < g[v].size(); i++)
69+
if (g[v][i]->other(v) == w)
70+
return true;
71+
return false;
72+
}
73+
74+
// 显示图的信息
75+
void show()
76+
{
77+
78+
for (int i = 0; i < n; i++)
79+
{
80+
cout << "vertex " << i << ":\t";
81+
for (int j = 0; j < g[i].size(); j++)
82+
cout << "( to:" << g[i][j]->w() << ",wt:" << g[i][j]->wt() << " )\t";
83+
cout << endl;
84+
}
85+
}
86+
87+
// 邻边迭代器, 传入一个图和一个顶点,
88+
// 迭代在这个图中和这个顶点向连的所有边
89+
class adjIterator
90+
{
91+
private:
92+
SparseGraph &G; // 图G的引用
93+
int v;
94+
int index;
95+
96+
public:
97+
// 构造函数
98+
adjIterator(SparseGraph &graph, int v) : G(graph)
99+
{
100+
this->v = v;
101+
this->index = 0;
102+
}
103+
104+
~adjIterator() {}
105+
106+
// 返回图G中与顶点v相连接的第一个边
107+
Edge<Weight> *begin()
108+
{
109+
index = 0;
110+
if (G.g[v].size())
111+
return G.g[v][index];
112+
// 若没有顶点和v相连接, 则返回NULL
113+
return NULL;
114+
}
115+
116+
// 返回图G中与顶点v相连接的下一个边
117+
Edge<Weight> *next()
118+
{
119+
index += 1;
120+
if (index < G.g[v].size())
121+
return G.g[v][index];
122+
return NULL;
123+
}
124+
125+
// 查看是否已经迭代完了图G中与顶点v相连接的所有顶点
126+
bool end()
127+
{
128+
return index >= G.g[v].size();
129+
}
130+
};
131+
};
132+
133+
#endif //INC_01_WEIGHTED_GRAPH_SPARSEGRAPH_H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <iostream>
2+
#include <iomanip>
3+
#include "DenseGraph.h"
4+
#include "ReadGraph.h"
5+
#include "SparseGraph.h"
6+
7+
using namespace std;
8+
9+
int main(){
10+
string filename = "testG1.txt";
11+
int V = 8;
12+
cout<<fixed<<setprecision(2);
13+
14+
// test Weight Dense Graph
15+
DenseGraph<double> g1 = DenseGraph<double> (V, false);
16+
ReadGraph<DenseGraph<double>, double> readGraph1(g1, filename);
17+
g1.show();
18+
cout<<endl;
19+
20+
// test Weight Sparse Graph
21+
SparseGraph<double> g2 = SparseGraph<double> (V,false);
22+
ReadGraph<SparseGraph<double>, double> readGraph2(g2,filename);
23+
g2.show();
24+
cout<<endl;
25+
26+
return 0;
27+
}

0 commit comments

Comments
 (0)