]> ruin.nu Git - germs.git/blob - src/componenttree.cpp
count leaves
[germs.git] / src / componenttree.cpp
1 /***************************************************************************
2  *   Copyright (C) 2006 by Michael Andreen                                 *
3  *   andreen@student.chalmers.se                                           *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA          *
19  ***************************************************************************/
20
21 #include "componenttree.h"
22
23 #include <map>
24 using namespace std;
25
26 ComponentTree::Node::Node(Node* parent, Component comp): _parent(parent), _comp(comp){
27         if (_parent){
28                 _parent->_children.push_back(this);
29         }
30 }
31
32 ComponentTree::Node::~Node(){
33         for (vector<Node*>::iterator c = _children.begin();
34                         c != _children.end(); ++c){
35                 delete *c;
36         }
37 }
38
39 /**
40  * Implemented as O(n*log n), should be possible in O(n), but this is pretty clean, and should
41  * be fast enough
42  */
43 ComponentTree::ComponentTree(const std::vector<Component>& components) : _root(new Node(0,Component())){
44         map<size_t,Component> starting;
45         map<size_t,Component> ending;
46         size_t max = 0;
47         for (vector<Component>::const_iterator c = components.begin(); c != components.end(); ++c){
48                 starting.insert(pair<size_t,Component>(c->i1,*c));
49                 ending.insert(pair<size_t,Component>(c->i2,*c));
50                 max = (c->i2 > max ? c->i2 : max);
51         }
52
53         Node* q = _root;
54         Node* p = new Node(q,starting[0]);
55
56         for (size_t i = 1; i < max; ++i){
57                 map<size_t,Component>::iterator c = starting.find(i);
58                 if (c != starting.end()){
59                         if (ending.find(i) == ending.end()){
60                                 q = new Node(p,Component());
61                         }
62                         p = new Node(q,c->second);
63
64                 }else if (ending.find(i) != ending.end()){
65                         p = q->_parent;
66                         q = p->_parent;
67                 }
68         }
69
70 }
71
72 ComponentTree::~ComponentTree(){
73         delete _root;
74 }
75
76 void ComponentTree::makeUnoriented(){
77         removeOriented(_root);
78         while (_root->_children.size() == 1 && _root->_comp.sign == 0){
79                 Node* n = _root->_children[0];
80                 _root->_children.clear();
81                 delete _root;
82                 _root = n;
83         }
84 }
85
86 void ComponentTree::removeOriented(Node* n){
87         for (vector<Node*>::iterator c = n->_children.begin();
88                         c != n->_children.end(); /*empty*/){
89                 removeOriented(*c);
90                 if ((*c)->_children.empty() && (*c)->_comp.sign == 0){
91                         delete *c;
92                         n->_children.erase(c);
93                 }else{
94                         ++c;
95                 }
96         }
97 }
98
99 size_t ComponentTree::countLeaves(){
100         size_t leaves = countLeaves(_root);
101         if (_root->_children.size() < 2 && _root->_comp.sign != 0){
102                 ++leaves;
103         }
104         return leaves;
105 }
106
107 size_t ComponentTree::countLeaves(Node* n){
108         if (n != _root && n->_children.empty()){
109                 return 1;
110         }
111         size_t leaves = 0;
112         for (vector<Node*>::iterator c = n->_children.begin();
113                         c != n->_children.end(); ++c){
114                 leaves += countLeaves(*c);
115         }
116         return leaves;
117 }