网上看到过很多版本是用链表实现的,可能这样比较安全吧。个人总感觉用指针指来指去的代码比较丑= =
所以我想试试看用STL给的模版实现一下,可能安全性不够,之后学精了后再作修改吧。
于是便在此记录代码的成长。
代码的功能是可以实现创建一个图结构、计算这个图的出度和入度、进行深搜和广搜、打印图。
图的结点是以“0”作为起点,当然这个“0”可能用不上,但万一用上了又没有岂不是尴尬~
结点的权值默认是int类型,这并不完善,之后我会改写成函数模版的形式。
为什么会想到用vector<list<T> >?
vector[ i ] 这个“ i ” 就可以表示每个顶点,接着vector[ i ] 里面的内容是 list<T> ,而这个list就可以表示每个顶点所属的边表。
举个栗子: 以3为顶点的边表是这样的: 3: 1 -> 5 -> 8 这时候,list 里面没有“3”这个元素,但要访问完整的边表的话,“3” 应该也是要被检查一下是否访问过。
怎么办呢? 这时候vector[ i ] 里面的“ i ” 就可以充当成这个“ 3 ”,也就是说我们在进行DFS或BFS的时候可以先 visited[ i ],这就达到了检查“3”——也就是边表的
顶点有没有被访问过的目的了。
.h代码如下:
#ifndef AC #define AC #include<iostream> #include<cstring> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<list> using namespace std; const int MAXL=1000; bool visited[MAXL]; //visited数组用来标记某点是否被访问过 int n, m; //n,m 分别表示待输入的顶点数和边数 class Graph_AD { public: Graph_AD(int Vnum, int Enum); bool check_edge_value(int, int); void getIOdegree(); void creatGraph(); void showGraph(); void showIOdegree(); void DFS(); //进行深搜 void dfs(int); void BFS(); //进行广搜 void bfs(int); private: int vertax; //顶点数 int edge; //边数 vector<pair<int, int> > In_Out_degree; //用来记录每个顶点出入度的数组 first表示入度 second表示出度 vector< list<int> > map; }; #endif
.cpp文件如下:
#include"Graph_by_Adjacency_list.h" Graph_AD::Graph_AD(int Vnum, int Enum): vertax(Vnum), edge(Enum) { }; bool Graph_AD::check_edge_value(int start, int end) //检查输入是否正确,如果结点大于或者小于规定的边界就越界了,你是想搞事情吗?? { if (start<0 || end<0 || start>vertax || end>vertax) return false; return true; } void Graph_AD::getIOdegree() { In_Out_degree.resize(vertax+1); for (int i=0; i<=vertax; ++i) { if (!map[i].empty()) //这里要注意,当map[i]有元素时,也就是该顶点的边表不为空时才能计算出度和入度 { list<int>::iterator it; for (it=map[i].begin(); it!=map[i].end(); ++it) { ++In_Out_degree[i].second; ++In_Out_degree[*it].first; } } } } void Graph_AD::creatGraph() { map.resize(vertax+1); cout << "请输入" << edge << "条边" << endl; for (int i=0; i<edge; ++i) { int start, end; cin >> start >> end; while (!check_edge_value(start, end)) { cout << "输入有误,请重新输入" << endl; cin >> start >> end; } map[start].push_back(end); } } void Graph_AD::showGraph() { cout << "图的邻接表如下:" << endl; for (int i=0; i<=vertax; ++i) { if (!map[i].empty()) { cout << "Vertax " << i << ": "; list<int>::iterator it; for (it=map[i].begin(); it!=map[i].end(); ++it) { cout << *it <<"->"; } cout << "^" << endl; } } } void Graph_AD::showIOdegree() { for (int i=0; i<=vertax; ++i) { cout << "Vertax " << i << "-> Id: " << In_Out_degree[i].first << endl <<" Od: " <<In_Out_degree[i].second << endl; } } bool check(int Vexnum, int edge) //检查输入的顶点数和边数合不合法, 顶点数和边数的关系是:((Vexnum*(Vexnum - 1)) / 2) < edge { if (Vexnum<=0 || edge<=0 || ((Vexnum*(Vexnum-1))/2)<edge) return false; return true; } void Graph_AD::DFS() { cout << "深搜结果为:" << endl; memset(visited, true, sizeof(visited)); for (int i=0; i<=vertax; ++i) { if (!map[i].empty() && visited[i]==true) //此处检查是否访问需满足两个条件: map[i]有元素,且i这个顶点未被访问过 { cout << i << " "; //此处就是开头提到的先访问顶点的问题,用 i 来访问顶点 visited[i]=false; dfs(i); } } cout << endl; } void Graph_AD::dfs(int now) { list<int>::iterator it; for (it=map[now].begin(); it!=map[now].end(); ++it) { if (visited[*it]==true) { cout << *it << " "; visited[*it]=false; dfs(*it); } } } void Graph_AD::BFS() { cout << "广搜结果为:" << endl; memset(visited, true, sizeof(visited)); for (int i=0; i<=vertax; ++i) { if (!map[i].empty() && visited[i]==true) //此处同理DFS情形 { cout << i << " "; //此处同理DFS情形 visited[i]=false; bfs(i); } } cout << endl; } void Graph_AD::bfs(int now) { list<int>::iterator it; queue<int> q; q.push(now); while (!q.empty()) { now=q.front(); q.pop(); for (it=map[now].begin(); it!=map[now].end(); ++it) { if (visited[*it]==true) { cout << *it << " "; visited[*it]=false; } } } cout << endl; }
main.cpp文件如下:
#include"Graph_by_Adjacency_list.cpp" int main() { cout << "输入图的顶点个数和边的条数:" << endl; cin >> n >> m; while (!check(n, m)) { cout << "输入的数值不合法,请重新输入" << endl; cin >> n >> m; } Graph_AD g1(n, m); g1.creatGraph(); g1.showGraph(); cout << "-------------------------------" << endl; g1.getIOdegree(); g1.showIOdegree(); cout << "-------------------------------" << endl; g1.DFS(); cout << "-------------------------------" << endl; g1.BFS(); return 0; }
运行效果如下:
还在继续完善中,希望大二学数据结构时能够用上,欢迎提出见解