C++读图txt文件,并将数据结构 图显示出来

网友投稿 281 2022-11-29

C++读图txt文件,并将数据结构 图显示出来

目录

下面分别是图的两个txt文件,现在用C++读取这个文件,并将图显示出来

第一行分别表示图的节点数和边数

13 130 54 30 19 126 45 40 211 129 100 67 89 115 3

6 80 10 20 51 21 31 43 43 5

代码中模板Graph,可以是稀疏图或者稠密的实现​

#include #include

//适用于稀疏图和稠密图的泛型读图编程实现template class ReadGraph{public: ReadGraph(Graph &g,const string &filetxt) { //读取文件 ifstream file(filetxt); //存储文件每行的数据 string line; int V, E; //确认文件是否打开 assert(file.is_open()); //将文件的第一行读取到line中,确认是否读取成功 assert(getline(file, line)); //将第一行输入到stringstream中,解析出变量V,E,即文件中开头第一行给出的string stringstream ss(line); ss >> V >> E; //检查读取的点数和引用图的点数是否是一致的 assert(g.V() == V); for (int i = 0; i < E; i++) { //读取下一行 assert(getline(file, line)); stringstream ss(line); int a, b; ss >> a >> b; //如果a,b不越界 assert(a >= 0 && a < V); assert(b >= 0 && b < V); g.AddEdge(a, b); } }private:};

整个代码展示

Graph.h文件

#pragma once#include//稠密图-邻接矩阵 class DenseGraph { private: //n表示图的点数,m表示图的边数 int n, m; //表示是否是有向图 bool directed; //将变量放在了public权限中,因为遍历方便 //表示稀疏矩阵 vector>g; public: DenseGraph(int n, bool directed) { this->n = n; this->m = 0; this->directed = directed; //初始化邻接矩阵 for (int i = 0; i < n; i++) { g.push_back(vector(n, false)); } } ~DenseGraph() { } //给图增加一条边,前提是这两个节点之间原来是没有边的 void AddEdge(int a, int b) { //检查越界 assert(a >= 0 && a < n); assert(b >= 0 && b < n); //判断a,b之间是否有边,如果已经存在边,返回 if (hasedge(a, b)) return; //赋值 g[a][b] = true; //判断是否是有向图 if (!directed) { g[b][a] = true; } //维护变量 m++; } //两个节点之间是否存在一条边 bool hasedge(int a, int b) { //检查越界 assert(a >= 0 && a < n); assert(b >= 0 && b < n); return g[a][b]; } //返回图的边数 int E() { return m; } //返回图的点数 int V() { return n; } //展示图 void show() { cout << "==========DenseGraph===============" << endl; for (int i = 0; i < n; i++) { cout << i << ": "; for (int j = 0; j < n; j++) { cout << g[i][j]<<" "; } cout << endl; } } class adjIterator { private: //定义一个图的引用 DenseGraph &G; //迭代器指向的节点 int v; //当前迭代器指向的索引 int index; public: //初始化引用类型数据成员的唯一机会是在构造函数初始化列表中 adjIterator(DenseGraph &g, int v) :G(g) { this->v = v; this->index = -1; } //迭代器的头 //返回第一个不为false的索引 int begin() { //index 是这个类的属性,只有赋值改变,才会改变,当几点序列改变时,index得初始化 index = -1; return next(); } //迭代器下一个 //返回下一个不为false的索引 int next() { //index 是这个类的属性,只有赋值改变,才会改变 for (index += 1; index < G.V(); index++) { if (G.g[v][index]) { //为了返回下一个不为false的索引,下一次跳入循环后需要index+1,跳过刚刚返回的索引值 return index; } } return -1; } //迭代的结尾 //返回这个图的总点数 int end() { return index >= G.V(); } }; };//稀疏图-邻接表 class SparseGraph { private: //n 表示点,m表示边 int n, m; //判断是否是有向图 int directed; //邻接表 vector>g; public: SparseGraph(int n, int directed) { this->n = n; this->m = 0; this->directed = directed; for (int i = 0; i < n; i++) { //将向量中的元素设为空 g.push_back(vector()); } } ~SparseGraph() { } //给图添加一条边,因为没有考虑平行边,所以该函数可能会导致平行边 void AddEdge(int a, int b) { //检查越界问题 assert(a >= 0 && a < n); assert(b >= 0 && b < n); //如果两点间存在边,则返回,如果加了下列几行代码,则时间复杂度编程O(N),故一般不考虑平行边, //if (hasEdge(a, b)) // return ; //赋值 g[a].push_back(b); //判断是否是自环边,或者是都是有向图,只有非自环边,或者无向图,才满足条件 if (a != b && !directed) g[b].push_back(a); m++; } //判断是否两点是否存在边 bool hasEdge(int a, int b) { //检查越界问题 assert(a >= 0 && a < n); assert(b >= 0 && b < n); for (int i = 0; i < g[a].size(); i++) { if (g[a][i] == b) { return true; } } return false; } //返回图的边数 int E() { return m; } //返回图的点数 int V() { return n; } //展示图 void show() { cout << "==========SparseGraph===============" << endl; for (int i = 0; i < n; i++) { cout << i << ": "; for (int j = 0; j < g[i].size(); j++) { cout << g[i][j] << " "; } cout << endl; } } //邻接表的迭代器类 class adjIterator { private: SparseGraph &G; //当前迭代器节点的索引 int v; //当前迭代器节点中的索引 int index; public: //初始化引用类型的数据成员,只能在构造函数的初始化列表中初始化 adjIterator(SparseGraph &g, int v) :G(g) { this->v = v; this->index = 0; } //迭代器的开始,返回当前节点中的第一个索引 int begin() { //对于后面的节点,begin必须将index初始化为0才行 index = 0; //此处不应该是G.V(),应该是对应每个节点中的多少个索引 if (G.g[v].size()) return G.g[v][index]; //return -1; } //迭代器的迭代,返回当前节点中下一个索引 int next() { index++; //此处不应该是G.V(),应该是对应每个节点中的多少个索引 if (index < G.g[v].size()) return G.g[v][index]; //return -1; } //迭代器的接受 int end() { return index >= G.g[v].size(); } }; };//适用于稀疏图和稠密图的泛型读图编程实现template class ReadGraph{public: ReadGraph(Graph &g,const string &filetxt) { //读取文件 ifstream file(filetxt); //存储文件每行的数据 string line; int V, E; //确认文件是否打开 assert(file.is_open()); //将文件的第一行读取到line中,确认是否读取成功 assert(getline(file, line)); //将第一行输入到stringstream中,解析出变量V,E,即文件中开头第一行给出的string stringstream ss(line); ss >> V >> E; //检查读取的点数和引用图的点数是否是一致的 assert(g.V() == V); for (int i = 0; i < E; i++) { //读取下一行 assert(getline(file, line)); stringstream ss(line); int a, b; ss >> a >> b; //如果a,b不越界 assert(a >= 0 && a < V); assert(b >= 0 && b < V); g.AddEdge(a, b); } }private:};

主函数部分,除了上文提到的库,还有一些常用的库需要包含,自行添加

int main(){ string filetext_0= "testG1.txt"; DenseGraph g1(13, false); ReadGraph readgraph(g1, filetext_0); //跟后面迭代器一样的功能,用来显示打印图 g1.show(); for (int i = 0; i < g1.V(); i++) { cout << i << ": "; DenseGraph::adjIterator iterator(g1, i); for (int j = iterator.begin(); !iterator.end(); j = iterator.next()) { cout << j << " "; } cout << endl; } cout << "============================" << endl; string filetext_1 = "testG2.txt"; SparseGraph g2(6, false); ReadGraph readgraph_1(g2, filetext_1); //跟后面迭代器一样的功能,用来显示打印图 g2.show(); for (int i = 0; i < g2.V(); i++) { cout << i << " : "; SparseGraph::adjIterator iterator(g2, i); for (int j = iterator.begin(); !iterator.end(); j = iterator.next()) { cout << j << " "; } cout << endl; }}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:野指针和内存泄漏
下一篇:Springboot jpa @Column命名大小写问题及解决
相关文章

 发表评论

暂时没有评论,来抢沙发吧~