-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrptree.hpp
99 lines (91 loc) · 2.74 KB
/
rptree.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#pragma once
#include<iostream>
#include<memory>
#include<queue>
#include<unordered_set>
#include<vector>
namespace rptree{
template <class Node, class F, class V = int>
void printTree(std::ostream& out, F&& f, Node* root, V Node::* value = &Node::value){
struct N;
using std::vector; using std::string; using std::queue;
using std::shared_ptr; using std::make_shared;
using uint = unsigned int;
using Np = shared_ptr<N>;
struct N{
string value;
size_t width = 0;
int pos = 0;
vector<Np> dests;
N(int v): value(std::to_string(v)){ }
int setWidth(int p = 0){
pos = p;
for(Np n : dests){
width += n->setWidth(pos + width);
}
width = std::max(width, value.size() + 2);
return width;
}
void print(string& s, string& s2, string& s3){
int w = width - value.size();
for(uint i = 0; i < value.size(); i++){
s[pos + (w + 1) / 2 + i] = value[i];
}
if(dests.empty()){
return;
}
s2[pos + (width + 0) / 2] = '|';
if(dests.size() == 1){
s3[pos + (width + 0) / 2] = '|';
}else{
for(uint i = dests[0]->width / 2; i < width - dests.back()->width / 2; i++){
s3[pos + i] = '-';
}
}
}
};
Np nroot = make_shared<N>(root->*value);
queue<std::pair<Node*, Np>> q;
q.push({root, nroot});
std::unordered_set<Node*> visited;
while(q.size()){
Node* n = q.front().first;
Np n2 = q.front().second;
q.pop();
if(visited.count(n)){ continue; }
visited.insert(n);
for(Node* d : n->dests){
if(visited.count(d)){ continue; }
Np np = make_shared<N>(d->*value);
n2->dests.push_back(np);
q.emplace(d, np);
}
}
int width = nroot->setWidth();
queue<Np> q2, next;
q2.emplace(nroot);
vector<string> elems, elems2, elems3;
out << '\n';
while(1){
string s(width, ' '), s2 = s, s3 = s;
while(q2.size()){
Np n = q2.front();
q2.pop();
n->print(s, s2, s3);
for(Np d : n->dests){
next.emplace(d);
}
}
f(out, s); out << '\n';
if(next.empty()){ break; }
f(out, s2); out << '\n';
f(out, s3); out << '\n';
q2.swap(next);
}
}
template <class Node, class V = int>
void printTree(std::ostream& out, Node* root, V Node::* value = &Node::value){
printTree(out, [](std::ostream& _out, auto e){ _out << e; }, root, value);
}
} // namespace rptree
using rptree::printTree;