经过长时间的学习终于可以开始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);//加入终点
}
}
}