【C++数据结构】链表实现图的存储及拓扑排序,基于C++自带的栈、队列及递归实现的拓扑排序。

链表实现的图存储及拓扑排序

注:本文内容为图的简易存储及拓扑排序,
标准版请查看[链表实现图存储及其遍历]

如下图所示,本文代码主要实现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");
}

推广

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

輕塵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值