链表实现的图存储及拓扑排序
注:本文内容为图的简易存储及拓扑排序,
标准版请查看[链表实现图存储及其遍历]
如下图所示,本文代码主要实现c图的结构,并基于该结构完成广度和深度优先排序。
代码如下:
#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<list>
#include<stdlib.h>
using namespace std;
typedef int Vertex;
template<int graph_size>
class Diagraph {
public:
Diagraph();
void read();
void write();
void depth_sort(list<Vertex> &topological_order);//深度优先递归拓扑排序
void depth_sort_stack(list<Vertex> &topological_order);//深度优先拓扑排序栈
void breadth_sort(list<Vertex> &topological_order);//广度优先拓扑排序
private:
int count;
list<Vertex> neighbors[graph_size]; //存放每个节点的后继
void recursive_depth_sort(Vertex v, bool visited[], list<Vertex> &topological_order);//递归排序
};
template<int graph_size> Diagraph<graph_size>::Diagraph() {
count = 0;
}
template<int graph_size>void Diagraph<graph_size>::read() {
cin >> count;
for (Vertex v = 0; v < count; v++) { //输入count个节点
int degree = 0;
string c;
cout << "Vertex" << v << ":" << endl;
while (1) {
cin >> c; //输入后继节点
if (c[0] == '-') //输入-该节点输入结束
break;
int w = atoi(c.c_str()); //字符串转为int型
neighbors[v].push_back(w);
}
}
}
template<int graph_size>void Diagraph<graph_size>::write() {
// list<int> copy_neighbor = neighbor;
for (Vertex v = 0; v < count; v++) {
int degree = neighbors[v].size();
cout << "Vertex" << v << " :" << endl;
if (degree == 0)
cout << "没有后继" << endl;
else
cout << "有后继" << endl;
list<int>::iterator iter;
iter = neighbors[v].begin();
int temple = 0;
while (iter != neighbors[v].end())
{
cout << *iter++;
if (temple < degree-1)
cout << ",";
else
cout << endl;
temple++;
}
/*for (int j = 0; j < degree; j++) {
Vertex w;
neighbors[v].retrieve(j, w);
cout << w;
if (j < degree - 1)
cout << ",";
else
cout << endl;
}*/
}
}
template<int graph_size>void Diagraph<graph_size>::depth_sort(list<Vertex> &topological_order) {
bool visited[graph_size]; //每个节点是否被访问
Vertex v;
for (v = 0; v < count; v++) //初始化未被访问
visited[v] = false;
topological_order.clear(); //清空目标链表
for (v = 0; v < count; v++)
if (!visited[v]) //如果未被访问
recursive_depth_sort(v, visited, topological_order); //递归访问
}
template<int graph_size>void Diagraph<graph_size>::recursive_depth_sort(Vertex v, bool visited[], list<Vertex> &topological_order) {
visited[v] = true; //进来的节点被访问
int degree = neighbors[v].size();
int index = 0;
list<int>::iterator itor;
itor = neighbors[v].begin();
while (itor != neighbors[v].end()) {
Vertex w;
w = *itor;
if (!visited[w])
recursive_depth_sort(w, visited, topological_order);
index++;
itor++;
}
topological_order.push_front(v);
/*
int degree = neighbors[v].size(); //该节点后继个数
for (int i = 0; i < degree; i++) { //依次访问该节点后继
Vertex w;
neighbors[v].retrieve(i, w); //读出后继
if (!visited[w]) //如果没访问
recursive_depth_sort(w, visited, topological_order); //递归访问
}
topological_order.insert(0, v); //该节点所有后继访问后,将该节点插入前面
*/
}
template<int graph_size>void Diagraph<graph_size>::depth_sort_stack(list<Vertex> &topological_order) {
topological_order.clear(); //先清空目标链表
Vertex v, w;
stack<int> s; //存放节点的栈
int predecessor_count[graph_size]; //每个节点前驱个数
for (v = 0; v < count; v++)
predecessor_count[v] = 0;
for (v = 0; v < count; v++) {
list<int>::iterator it;
it = neighbors[v].begin();
while (it != neighbors[v].end()) { //所有节点前驱存放在该数组
w = *it;
predecessor_count[w]++;
it++;
}
}
for (v = 0; v < count; v++)
if (predecessor_count[v] == 0) //先把所有没有前驱的节点入栈
s.push(v);
while (!s.empty()) { //栈不为空循环
v=s.top(); //取出栈顶并访问
s.pop();
topological_order.push_back(v); //插入该节点
list<int>::iterator itea;
itea = neighbors[v].begin();
while (itea!=neighbors[v].end()) { //访问该节点所有后继
w=*itea;
predecessor_count[w]--; //所有后继入度减1
if (predecessor_count[w] == 0) //如果后继没有前驱了,入栈
s.push(w);
itea++;
}
}
}
template<int graph_size>void Diagraph<graph_size>::breadth_sort(list<Vertex> &topological_order) {
topological_order.clear(); //先清空目标链表
Vertex v, w;
int predecessor_count[graph_size]; //每个节点前驱个数
for (v = 0; v < count; v++)
predecessor_count[v] = 0;
for (v = 0; v < count; v++) {
list<int>::iterator it;
it = neighbors[v].begin();
while (it != neighbors[v].end()) { //所有节点前驱存放在该数组
w = *it;
predecessor_count[w]++;
it++;
}
}
queue<int> ready_to_process; //存放节点的队列
for (v = 0; v < count; v++)
if (predecessor_count[v] == 0)
ready_to_process.push(v); //先把所有没有前驱的节点入队
while (!ready_to_process.empty()) { //队列不为空循环
v=ready_to_process.front(); //取出队首并访问
ready_to_process.pop();
topological_order.push_back(v); //插入该节点
list<int>::iterator itea;
itea = neighbors[v].begin();
while (itea != neighbors[v].end()) { //访问该节点所有后继
w = *itea;
predecessor_count[w]--; //所有后继入度减1
if (predecessor_count[w] == 0) //如果后继没有前驱了,入栈
ready_to_process.push(w);
itea++;
}
}
}
int main() {
Diagraph<10> graph;
list<Vertex> topo;
graph.read();
graph.write();
list<int>::iterator iter;
graph.depth_sort(topo);
iter = topo.begin();
cout << "递归实现深度优先拓扑排序:\n";
while (iter != topo.end())
cout << *iter++ << "\t";
cout << endl;
graph.depth_sort_stack(topo);
iter = topo.begin();
cout << "栈实现深度优先拓扑排序:\n";
while (iter != topo.end())
cout << *iter++ << "\t";
cout << endl;
graph.breadth_sort(topo);
iter = topo.begin();
cout << "队列实现广度优先拓扑排序:\n";
while (iter != topo.end())
cout << *iter++ << "\t";
cout << endl;
system("pause");
}