tinystl实现(第二十七步:graph实现)

经过长时间的学习终于可以开始tinystl的仿(chao)写工作了,本文参考了这位大神的github,坦白讲我只是补充了注释,因为tinystl的代码真的非常经典而我又没什么这种大型项目的经验,所以只能这样做,不过相信能够有助于大家的学习
#强烈建议按顺序阅读本专栏
.h

#pragma once
#ifndef _GRAPH_H_
#define _GRAPH_H_

#include "Iterator.h"
#include "List.h"
#include "String.h"
#include "Unordered_set.h"
#include "Utility.h"
#include "Vector.h"

#include <functional>
#include <iomanip>
#include <sstream>

namespace mySTL {
	namespace Detail {
		template<class Index, class Value, class EqualFunc>
		class inner_iterator;
		template<class Index, class Value, class EqualFunc>
		class outter_iterator;

		template<class Index, class Value, class EqualFunc = equal_to<Index>>
		class graph {//base class
		public:
			friend class inner_iterator < Index, Value, EqualFunc >;
			friend class outter_iterator < Index, Value, EqualFunc >;
		public:
			typedef Index index_type;
			typedef Value value_type;
			typedef EqualFunc equal_func_type;
			typedef pair<Index, Value> node_type;
			typedef vector<node_type> nodes_set_type;
			typedef std::function<void(node_type&)> visiter_func_type;
			typedef outter_iterator<Index, Value, EqualFunc> iterator;
			typedef inner_iterator<Index, Value, EqualFunc> inner_iterator;
		public:
			graph() :size_(0) {};
			virtual ~graph() {};

			//node can be not in the graph
			virtual void add_node(const node_type& item, const nodes_set_type& nodes) = 0;
			//node of the index must in the graph
			virtual void add_node(const Index& index, const nodes_set_type& nodes) = 0;
			virtual void make_edge(const Index& index1, const Index& index2) = 0;

			virtual void delete_node(const node_type& item) = 0;
			virtual void delete_node(const Index& index) = 0;

			void DFS(const Index& index, visiter_func_type func);
			void BFS(const Index& index, visiter_func_type func);

			node_type make_node(const Index& index, const Value& val);
			const node_type& get_node(const Index& index);

			bool is_contained(const Index& index);
			inline static nodes_set_type empty_node_set();
			nodes_set_type adjacent_nodes(const Index& index);
			nodes_set_type adjacent_nodes(const node_type& n);

			bool empty()const;
			size_t size()const;
			inner_iterator begin(const Index& index);
			inner_iterator end(const Index& index);
			iterator begin();
			iterator end();

			equal_func_type get_equal_func()const;
			string to_string();
		protected:
			void _DFS(node_type& node, visiter_func_type func, Unordered_set<Index, std::hash<Index>, EqualFunc>& visited);
			void _BFS(node_type& node, visiter_func_type func, Unordered_set<Index, std::hash<Index>, EqualFunc>& visited);
		protected:
			list<pair<node_type, list<node_type>>> nodes_;
			equal_func_type equal_func;
			size_t size_;
		};

		template<class Index, class Value, class EqualFunc = equal_to<Index>>
		class inner_iterator :public iterator<bidirectional_iterator_tag,
			typename graph<Index, Value, EqualFunc>::node_type> {
		public:
			friend class graph < Index, Value, EqualFunc >;
			typedef graph<Index, Value, EqualFunc>* cntrPtr;
			typedef graph<Index, Value, EqualFunc> graph_type;
			typedef typename list<typename graph_type::node_type>::iterator inner_it_type;
		public:
			explicit inner_iterator(cntrPtr c = nullptr, inner_it_type iit = inner_it_type())
				:container_(c), inner_it_(iit) {}

			inner_iterator& operator ++();
			const inner_iterator operator ++(int);

			typename graph_type::node_type& operator*() { return *inner_it_; }
			typename graph_type::node_type* operator ->() { return &(operator*()); }
		private:
			cntrPtr container_;
			inner_it_type inner_it_;
		public:
			template<class Index, class Value, class EqualFunc>
			friend bool operator ==(const inner_iterator<Index, Value, EqualFunc>& lhs,
				const inner_iterator<Index, Value, EqualFunc>& rhs);
			template<class Index, class Value, class EqualFunc>
			friend bool operator !=(const inner_iterator<Index, Value, EqualFunc>& lhs,
				const inner_iterator<Index, Value, EqualFunc>& rhs);
		};
		template<class Index, class Value, class EqualFunc = equal_to<Index>>
		class outter_iterator :public iterator<bidirectional_iterator_tag,
			typename graph<Index, Value, EqualFunc>::node_type> {
		public:
			friend class graph < Index, Value, EqualFunc >;
			typedef graph<Index, Value, EqualFunc>* cntrPtr;
			typedef graph<Index, Value, EqualFunc> graph_type;
			typedef typename list<pair<typename graph_type::node_type, list<typename graph_type::node_type>>>::iterator outter_it_type;
		private:
			cntrPtr container_;
			outter_it_type outter_it_;
		public:
			explicit outter_iterator(cntrPtr c = nullptr, outter_it_type oit = outter_it_type())
				:container_(c), outter_it_(oit) {}

			outter_iterator& operator ++();
			const outter_iterator operator ++(int);

			typename graph_type::node_type& operator*() { return outter_it_->first; }
			typename graph_type::node_type* operator ->() { return &(operator*()); }
		public:
			template<class Index, class Value, class EqualFunc>
			friend bool operator ==(const outter_iterator<Index, Value, EqualFunc>& lhs,
				const outter_iterator<Index, Value, EqualFunc>& rhs);
			template<class Index, class Value, class EqualFunc>
			friend bool operator !=(const outter_iterator<Index, Value, EqualFunc>& lhs,
				const outter_iterator<Index, Value, EqualFunc>& rhs);
		};
	}//end of namespace Detail

	//directed graph
	template<class Index, class Value, class EqualFunc = equal_to<Index>>
	class directed_graph :public Detail::graph < Index, Value, EqualFunc > {
	public:
		directed_graph();
		~directed_graph() {}
		//node n -> every node_type in the nodes set
		void add_node(const node_type& n, const nodes_set_type& nodes) override final;
		void add_node(const Index& index, const nodes_set_type& nodes) override final;
		//node index1 -> node index2
		void make_edge(const Index& index1, const Index& index2) override final;

		void delete_node(const node_type& item) override final;
		void delete_node(const Index& index) override final;
	private:
		void add_node_helper(const Index& index, const nodes_set_type& nodes);
	};
}

#include "Detail\Graph.impl.h"
#endif

impl.h

#pragma once
#include "../Graph.h"
namespace mySTL {
	namespace Detail {
		template<class Index, class Value, class EqualFunc>
		typename graph<Index, Value, EqualFunc>::node_type
			graph<Index, Value, EqualFunc>::make_node(const Index& index, const Value& val) {
			return node_type(index, val);
		}
		//依序号获得node
		template<class Index, class Value, class EqualFunc>
		typename const graph<Index, Value, EqualFunc>::node_type&
			graph<Index, Value, EqualFunc>::get_node(const Index& index) {
			for (auto& pair : nodes_) {
				if (equal_func(pair.first.first, index))
					return pair.first;
			}
			static node_type empty_node;
			return empty_node;
		}
		//查看序号是否存在
		template<class Index, class Value, class EqualFunc>
		bool graph<Index, Value, EqualFunc>::is_contained(const Index& index) {
			for (auto& pair : nodes_) {
				if (equal_func(pair.first.first, index))
					return true;
			}
			return false;
		}
		template<class Index, class Value, class EqualFunc>
		typename graph<Index, Value, EqualFunc>::nodes_set_type
			graph<Index, Value, EqualFunc>::empty_node_set() {
			return nodes_set_type();
		}
		template<class Index, class Value, class EqualFunc>
		bool graph<Index, Value, EqualFunc>::empty()const {
			return nodes_.empty();
		}
		//按点的下标查找begin,end
		template<class Index, class Value, class EqualFunc>
		typename graph<Index, Value, EqualFunc>::inner_iterator
			graph<Index, Value, EqualFunc>::begin(const Index& index) {
			for (auto& pair : nodes_) {
				if (equal_func(pair.first.first, index))
					return inner_iterator(this, (pair.second).begin());
			}
			return end(index);
		}
		template<class Index, class Value, class EqualFunc>
		typename graph<Index, Value, EqualFunc>::inner_iterator
			graph<Index, Value, EqualFunc>::end(const Index& index) {
			for (auto& pair : nodes_) {
				if (equal_func(pair.first.first, index))
					return inner_iterator(this, (pair.second).end());
			}
			return inner_iterator();
		}
		//迭代器查找begin/end
		template<class Index, class Value, class EqualFunc>
		typename graph<Index, Value, EqualFunc>::iterator graph<Index, Value, EqualFunc>::begin() {
			return iterator(this, nodes_.begin());
		}
		template<class Index, class Value, class EqualFunc>
		typename graph<Index, Value, EqualFunc>::iterator graph<Index, Value, EqualFunc>::end() {
			return iterator(this, nodes_.end());
		}
		//
		template<class Index, class Value, class EqualFunc>
		size_t graph<Index, Value, EqualFunc>::size()const {
			return size_;
		}
		//获得某点出发的所有终点
		template<class Index, class Value, class EqualFunc>
		typename graph<Index, Value, EqualFunc>::nodes_set_type
			graph<Index, Value, EqualFunc>::adjacent_nodes(const Index& index) {
			nodes_set_type s;
			for (auto it = begin(index); it != end(index); ++it) {
				s.push_back(*it);
			}
			return s;
		}
		template<class Index, class Value, class EqualFunc>
		typename graph<Index, Value, EqualFunc>::nodes_set_type
			graph<Index, Value, EqualFunc>::adjacent_nodes(const node_type& n) {
			return adjacent_nodes(n.first);
		}
		//dfs
		template<class Index, class Value, class EqualFunc>
		void graph<Index, Value, EqualFunc>::_DFS(node_type& node,
			visiter_func_type func, Unordered_set<Index, std::hash<Index>, EqualFunc>& visited) {
			auto nodes = adjacent_nodes(node.first);//加入接下来能去的节点
			func(node);//使用函数
			visited.insert(node.first);//标记访问
			for (auto& n : nodes) {
				if (visited.count(n.first) == 0)//has not visited
					_DFS(n, func, visited);
			}
		}
		template<class Index, class Value, class EqualFunc>
		void graph<Index, Value, EqualFunc>::DFS(const Index& index, visiter_func_type func) {
			node_type start = (get_node(index));
			Unordered_set<Index, std::hash<Index>, EqualFunc> visited(7);
			_DFS(start, func, visited);
		}
		//bfs
		template<class Index, class Value, class EqualFunc>
		void graph<Index, Value, EqualFunc>::_BFS(node_type& node,
			visiter_func_type func, Unordered_set<Index, std::hash<Index>, EqualFunc>& visited) {
			auto nodes = adjacent_nodes(node.first);
			func(node);
			visited.insert(node.first);
			do {
				nodes_set_type temp;
				for (auto it = nodes.begin(); it != nodes.end(); ++it) {
					if (visited.count(it->first) == 0) {//has not visited
						func(*it);
						visited.insert(it->first);
						auto s = adjacent_nodes(it->first);
						temp.insert(temp.end(), s.begin(), s.end());//迭代访问(其实这里用队列更稳妥)
					}
				}
				nodes = temp;
			} while (!nodes.empty());//全部访问
		}
		template<class Index, class Value, class EqualFunc>
		void graph<Index, Value, EqualFunc>::BFS(const Index& index, visiter_func_type func) {
			node_type start = (get_node(index));
			Unordered_set<Index, std::hash<Index>, EqualFunc> visited(7);
			_BFS(start, func, visited);
		}
		//
		template<class Index, class Value, class EqualFunc>
		string graph<Index, Value, EqualFunc>::to_string() {
			string str;
			std::ostringstream oss;
			for (auto oit = begin(); oit != end(); ++oit) {

				oss << "[" << oit->first << "," << oit->second << "]" << ":";//打印点
				auto eit = end(oit->first);
				for (auto iit = begin(oit->first); iit != eit; ++iit) {
					oss << "[" << iit->first << "," << iit->second << "]" << "->";
				}
				oss << "[nil]" << std::endl << std::setw(4) << "|" << std::endl;
			}
			oss << "[nil]" << std::endl;
			str.append(oss.str().c_str());//如果str为空则置空
			return str;
		}
		template<class Index, class Value, class EqualFunc>
		typename graph<Index, Value, EqualFunc>::equal_func_type
			graph<Index, Value, EqualFunc>::get_equal_func()const {
			return equal_func;
		}
		//********************************************************************************
		template<class Index, class Value, class EqualFunc>
		inner_iterator<Index, Value, EqualFunc>& inner_iterator<Index, Value, EqualFunc>::operator ++() {
			++inner_it_;
			return *this;
		}
		template<class Index, class Value, class EqualFunc>
		const inner_iterator<Index, Value, EqualFunc> inner_iterator<Index, Value, EqualFunc>::operator ++(int) {
			auto temp = *this;
			++*this;
			return temp;
		}
		template<class Index, class Value, class EqualFunc>
		bool operator ==(const inner_iterator<Index, Value, EqualFunc>& lhs,
			const inner_iterator<Index, Value, EqualFunc>& rhs) {
			return lhs.container_ == rhs.container_ && lhs.inner_it_ == rhs.inner_it_;
		}
		template<class Index, class Value, class EqualFunc>
		bool operator !=(const inner_iterator<Index, Value, EqualFunc>& lhs,
			const inner_iterator<Index, Value, EqualFunc>& rhs) {
			return !(lhs == rhs);
		}
		//*********************************************************************************
		template<class Index, class Value, class EqualFunc>
		outter_iterator<Index, Value, EqualFunc>& outter_iterator<Index, Value, EqualFunc>::operator ++() {
			++outter_it_;
			return *this;
		}
		template<class Index, class Value, class EqualFunc>
		const outter_iterator<Index, Value, EqualFunc> outter_iterator<Index, Value, EqualFunc>::operator ++(int) {
			auto temp = *this;
			++*this;
			return temp;
		}
		template<class Index, class Value, class EqualFunc>
		bool operator ==(const outter_iterator<Index, Value, EqualFunc>& lhs,
			const outter_iterator<Index, Value, EqualFunc>& rhs) {
			return lhs.container_ == rhs.container_ && lhs.outter_it_ == rhs.outter_it_;
		}
		template<class Index, class Value, class EqualFunc>
		bool operator !=(const outter_iterator<Index, Value, EqualFunc>& lhs,
			const outter_iterator<Index, Value, EqualFunc>& rhs) {
			return !(lhs == rhs);
		}
	}
	//构造函数
	template<class Index, class Value, class EqualFunc>
	directed_graph<Index, Value, EqualFunc>::directed_graph() :graph() {}
	template<class Index, class Value, class EqualFunc>
	void directed_graph<Index, Value, EqualFunc>::add_node_helper(const Index& index, const nodes_set_type& nodes) {
		if (nodes.empty())
			return;
		//find node n's list
		list<typename graph::node_type>* l;
		for (auto& pair : nodes_) {
			if (equal_func(pair.first.first, index))
				l = &(pair.second);
		}
		for (const auto& item : nodes) {
			l->push_front(item);
			if (!is_contained(item.first)) {//如果边的末节点不存在则添加
				add_node(item, empty_node_set());
			}
		}
	}
	template<class Index, class Value, class EqualFunc>
	void directed_graph<Index, Value, EqualFunc>::add_node(const node_type& n, const nodes_set_type& nodes) {
		if (!is_contained(n.first)) {
			nodes_.push_front(make_pair(n, list<typename graph::node_type>()));
			++size_;
		}
		add_node_helper(n.first, nodes);
	}
	template<class Index, class Value, class EqualFunc>
	void directed_graph<Index, Value, EqualFunc>::add_node(const Index& index, const nodes_set_type& nodes) {
		add_node_helper(index, nodes);
	}
	//根据迭代器删除节点
	template<class Index, class Value, class EqualFunc>
	void directed_graph<Index, Value, EqualFunc>::delete_node(const node_type& item) {
		delete_node(item.first);
	}
	//
	template<class Index, class Value, class EqualFunc>
	void directed_graph<Index, Value, EqualFunc>::make_edge(const Index& index1, const Index& index2) {
		auto node1 = get_node(index1), node2 = get_node(index2);
		for (auto it = nodes_.begin(); it != nodes_.end(); ++it) {
			if (equal_func((it->first).first, index1))//找到起点
				(it->second).push_front(node2);//加入终点
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值