From 172244b353ec9b68effd119026b01a4123fe5bdf Mon Sep 17 00:00:00 2001 From: Augustin Degomme <augustin.degomme@imag.fr> Date: Mon, 13 Jun 2011 20:30:17 +0000 Subject: [PATCH] feature : add IntervalOfContainers which are described in https://gforge.inria.fr/plugins/wiki/index.php?NewDataStructPage&id=1596&type=g A new IntervalOfContainer is built only when a certain (10000 for the moment) number of StateChanges or Links are attached to it. (initially only StateChanges were taken into account, but Links are created in parent containers without States, so they were all allocated in the same IntevalOfContainers, making them huge). This is not activated right now by default, but can be turned on by setting the flag USE_ITC before compiling to perform tests. --- src/CMakeLists.txt | 2 + src/src.pro | 2 + src/trace/Container.cpp | 278 ++++++++++++++++++++++++++++++++-- src/trace/Container.hpp | 10 ++ src/trace/DrawTrace.hpp | 69 ++++++--- src/trace/Entity.cpp | 10 +- src/trace/Entity.hpp | 2 + src/trace/EntityType.cpp | 15 +- src/trace/StateChange.cpp | 8 + src/trace/StateChange.hpp | 2 + src/trace/Variable.cpp | 2 +- src/trace/Variable.hpp | 2 +- src/trace/tree/BinaryTree.hpp | 135 +++++++++++++++++ 13 files changed, 496 insertions(+), 41 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 764b2449..5558f59b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -81,6 +81,7 @@ SET(VITE_HDRS trace/DrawTrace.hpp trace/DrawTree.hpp trace/Trace.hpp + trace/IntervalOfContainer.hpp # Render headers render/Palette.hpp render/Render.hpp @@ -176,6 +177,7 @@ SET(VITE_SRCS trace/Variable.cpp trace/Container.cpp trace/Trace.cpp + trace/IntervalOfContainer.cpp # Render code files render/Palette.cpp render/Geometry.cpp diff --git a/src/src.pro b/src/src.pro index 94be4a71..2cb9b311 100644 --- a/src/src.pro +++ b/src/src.pro @@ -142,6 +142,7 @@ HEADERS += common/common.hpp \ trace/tree/BinaryTree.hpp \ trace/tree/Node.hpp \ trace/tree/Interval.hpp \ + trace/IntervalOfContainer.hpp # Statistics headers statistics/Stats_window.hpp \ statistics/Statistic.hpp \ @@ -194,6 +195,7 @@ SOURCES += common/Message.cpp \ trace/Container.cpp \ trace/tree/Interval.cpp \ trace/Trace.cpp \ + trace/IntervalOfContainer.cpp\ # Parser code files parser/Parser.cpp \ parser/ParserFactory.cpp \ diff --git a/src/trace/Container.cpp b/src/trace/Container.cpp index 16736635..7c7f05f4 100644 --- a/src/trace/Container.cpp +++ b/src/trace/Container.cpp @@ -62,6 +62,14 @@ /* -- */ #include "trace/Container.hpp" /* -- */ +#ifdef USE_ITC +#include "trace/IntervalOfContainer.hpp" + + +//number of Events before reallocation of the array +#define N 1000 + +#endif using namespace std; @@ -74,6 +82,11 @@ Container::Container(Name name, Date creation_time, ContainerType *type, Contain _depth = parent->_depth+1; else _depth=0; + +#ifdef USE_ITC + IntervalOfContainer * itc= new IntervalOfContainer(); + _intervalsOfContainer.push_back(itc); +#endif } template <class T> @@ -88,14 +101,21 @@ Container::~Container() { MyDelete<Container>); _children.clear(); _children.resize(0); - + #ifdef USE_ITC + std::for_each(_intervalsOfContainer.begin(), + _intervalsOfContainer.end(), + MyDelete<IntervalOfContainer>); + _intervalsOfContainer.clear(); + +#endif + // Delete states - delete _state_tree; + // delete _state_tree; _state_tree = NULL; // Delete events - delete _event_tree; + //delete _event_tree; _event_tree = NULL; - + #ifndef USE_ITC // Delete links while (!_links.empty()){ delete _links.front(); @@ -108,6 +128,9 @@ Container::~Container() { delete (*it).second; } _variables.clear(); +#endif + + } void Container::add_child(Container *child) { @@ -123,7 +146,42 @@ void Container::add_view_child(Container *child) { } void Container::add_current_state(Date end) { - State *new_state = new State( +#ifdef USE_ITC + State* new_state=_intervalsOfContainer.back()->add_state( + _current_states.top().start, + end, + _current_states.top().type, + _current_states.top().value, + this, + _current_states.top().opt); + + if (_n_states!=0) + (_intervalsOfContainer.back()->_statechanges[_intervalsOfContainer.back()->_n_statechanges-1]).set_right_state(new_state); + else { + _n_states++; + _intervalsOfContainer.back()->add_statechange(new_state->get_start_time(), NULL, new_state); + } + if(_intervalsOfContainer.back()->add_statechange(end, new_state,0)==false){ + + //dump_last_itc(); + //this interval is full, create a new one + IntervalOfContainer* itc=new IntervalOfContainer(); + + State* first_state=itc->add_state( + _current_states.top().start, + end, + _current_states.top().type, + _current_states.top().value, + this, + _current_states.top().opt); + + _intervalsOfContainer.push_back(itc); + //add the state to the new intervalOfContainer + itc->add_statechange(end, first_state,0); + } + +#else + State *new_state = new State( _current_states.top().start, end, _current_states.top().type, @@ -141,6 +199,7 @@ void Container::add_current_state(Date end) { // Set the change from the new state _states.push_back(new StateChange(end, new_state)); +#endif _n_states++; } @@ -174,8 +233,12 @@ void Container::pop_state(Date time) { } void Container::new_event(Date time, EventType *type, EntityValue *value, map<string, Value *> &opt) { +#ifdef USE_ITC + _intervalsOfContainer.back()->add_event(time, type,this, value, opt); +#else _events.push_back(new Event(time, type, this, value, opt)); _n_events++; +#endif } @@ -195,7 +258,30 @@ void Container::start_link(Date time, LinkType *type, Container *source, { (*i).second.opt[(*j).first] = (*j).second; } - +#ifdef USE_ITC + if( _intervalsOfContainer.back()->add_link(time, + (*i).second.start, + type, + this, + source, + (*i).second.source, + value, + ((*i).second).opt)==false){ + //dump_last_itc(); + //this interval is full, create a new one + IntervalOfContainer* itc=new IntervalOfContainer(); + _intervalsOfContainer.push_back(itc); + //add the state to the new intervalOfContainer + _intervalsOfContainer.back()->add_link(time, + (*i).second.start, + type, + this, + source, + (*i).second.source, + value, + ((*i).second).opt); + } +#else _links.push_back(new Link( time, (*i).second.start, @@ -205,7 +291,9 @@ void Container::start_link(Date time, LinkType *type, Container *source, (*i).second.source, value, (*i).second.opt)); +#endif _current_links.erase(i); + } } @@ -223,7 +311,30 @@ void Container::end_link(Date time, Container *destination, String key, map<stri { (*i).second.opt[(*j).first] = (*j).second; } - +#ifdef USE_ITC + if(_intervalsOfContainer.back()->add_link((*i).second.start, + time, + (*i).second.type, + this, + (*i).second.source, + destination, + (*i).second.value, + (*i).second.opt)==false){ + //dump_last_itc(); + //this interval is full, create a new one + IntervalOfContainer* itc=new IntervalOfContainer(); + _intervalsOfContainer.push_back(itc); + //add the state to the new intervalOfContainer + _intervalsOfContainer.back()->add_link((*i).second.start, + time, + (*i).second.type, + this, + (*i).second.source, + destination, + (*i).second.value, + (*i).second.opt); + } +#else _links.push_back(new Link( (*i).second.start, time, @@ -233,11 +344,31 @@ void Container::end_link(Date time, Container *destination, String key, map<stri destination, (*i).second.value, (*i).second.opt)); +#endif _current_links.erase(i); } } void Container::set_variable(Date time, VariableType *type, Double value) { +#ifdef USE_ITC + int i=0; + IntervalOfContainer* itc= _intervalsOfContainer.back(); + for(i=0;i< itc->_n_variables && itc->_variables[i].get_type()!=type; i++); + + if (i==itc->_n_variables) { + itc->_n_variables++; + itc->_variables=(Variable*)realloc(itc->_variables, itc->_n_variables*sizeof(Variable)); + memset(itc->_variables+(itc->_n_variables-1)*sizeof(Variable),0,sizeof(Variable)); + _variables[type] = new Variable(this, type); + _n_variables++; + Variable* v=new(&itc->_variables[i]) Variable (this, type); + //itc->_variables[i].set_values(this, type); + itc->_variables[i].add_value(time, value); + } + else { + itc->_variables[i].add_value(time, value); + } +#else map<VariableType *, Variable *>::iterator i = _variables.find(type); if (i == _variables.end()) { _variables[type] = new Variable(this, type); @@ -247,9 +378,29 @@ void Container::set_variable(Date time, VariableType *type, Double value) { else { (*i).second->add_value(time, value); } +#endif } void Container::add_variable(Date time, VariableType *type, Double value) { +#ifdef USE_ITC + int i=0; + IntervalOfContainer* itc= _intervalsOfContainer.back(); + for(i=0;i< itc->_n_variables && itc->_variables[i].get_type()!=type; i++); + + if (i==itc->_n_variables) { + itc->_n_variables++; + itc->_variables=(Variable*)realloc(itc->_variables, itc->_n_variables*sizeof(Variable)); + memset(itc->_variables+(itc->_n_variables-1)*sizeof(Variable),0,sizeof(Variable)); + _variables[type] = new Variable(this, type); + _n_variables++; + + Variable* v=new(&itc->_variables[i]) Variable (this, type); + itc->_variables[i].add_value(time, value); + } + else { + itc->_variables[i].add_value(time,itc->_variables[i].get_last_value()+ value); + } +#else map<VariableType *, Variable *>::iterator i = _variables.find(type); if (i == _variables.end()) { _variables[type] = new Variable(this, type); @@ -259,11 +410,30 @@ void Container::add_variable(Date time, VariableType *type, Double value) { else { (*i).second->add_value(time, (*i).second->get_last_value() + value); } - +#endif } void Container::sub_variable(Date time, VariableType *type, Double value) { - map<VariableType *, Variable *>::iterator i = _variables.find(type); +#ifdef USE_ITC + int i=0; + IntervalOfContainer* itc= _intervalsOfContainer.back(); + for(i=0;i< itc->_n_variables && itc->_variables[i].get_type()!=type; i++); + + if (i==itc->_n_variables) { + itc->_n_variables++; + itc->_variables=(Variable*)realloc(itc->_variables, itc->_n_variables*sizeof(Variable)); + memset(itc->_variables+(itc->_n_variables-1)*sizeof(Variable),0,sizeof(Variable)); + _variables[type] = new Variable(this, type); + _n_variables++; + + Variable* v=new(&itc->_variables[i]) Variable (this, type); + itc->_variables[i].add_value(time, value); + } + else { + itc->_variables[i].add_value(time,itc->_variables[i].get_last_value()- value); + } +#else + map<VariableType *, Variable *>::iterator i = _variables.find(type); if (i == _variables.end()) { _variables[type] = new Variable(this, type); _variables[type]->add_value(time, -value); @@ -272,6 +442,7 @@ void Container::sub_variable(Date time, VariableType *type, Double value) { else { (*i).second->add_value(time, (*i).second->get_last_value() - value); } +#endif } Name Container::get_name() const { @@ -351,10 +522,99 @@ void Container::destroy(const Date &time) { } void Container::finish(const Date &time) { + +#ifdef USE_ITC +// if( Info::Splitter::split==false && Info::Splitter::preview ==false){ + + //boolean to check if the intervalOfcontainer is fully inside the visible interval, in order not to check each state if yes + bool fully_contained=false; + if(_n_events!=0)delete _event_tree; + if(_n_states!=0)delete _state_tree; + + _states.clear(); + _links.clear(); + _variables.clear(); + //delete _events; + _n_states=0; + _n_events=0; + _events=NULL; + //iterates through all intervalOfContainers + list<IntervalOfContainer* > ::const_iterator it_end= _intervalsOfContainer.end(); + for(list<IntervalOfContainer *>::const_iterator it = _intervalsOfContainer.begin() ; + it != it_end; + it++){ + //only work with intervalOfContainers which are loaded in memory + if(((*it)->_loaded)==true){ + //add all statechanges to the global one + if((*it)->_n_statechanges!=0){ + for(int i=0; i< (*it)->_n_statechanges; i++){ + _states.push_back(&((*it)->_statechanges[i])); + _n_states++; + } + } + + if((*it)->_n_events!=0) + for(int i=0; i< (*it)->_n_events; i++){ + if(_events==NULL){ + _events=(Event**)malloc((_n_events+N)*sizeof(Event*)); + memset(_events, 0, (_n_events+N)*sizeof(Event*)); + } + _events[_n_events]=(&((*it)->_events[i])); + _n_events++; + if(_n_events%N==0)_events=(Event**)realloc(_events,(_n_events+N)*sizeof(Event*)); + } + + if((*it)->_n_links!=0) + for(int i=0; i< (*it)->_n_links; i++){ + _links.push_back(&((*it)->_links[i])); + } + + if((*it)->_n_variables!=0) + for(int i=0; i< (*it)->_n_variables; i++){ + + VariableType* type=((*it)->_variables[i]).get_type(); + + if (_variables.find(type)==_variables.end()){ + _variables.insert(std::pair<VariableType*, Variable*>(type,(&((*it)->_variables[i])))); + _n_variables++; + }else{ + if(((*it)->_variables[i]).get_values()!=NULL){ + std::list<std::pair<Date, Double> >::const_iterator it_val = ((*it)->_variables[i]).get_values()->begin(); + for(; + it_val!=((*it)->_variables[i]).get_values()->end(); + it++){ + pair<Date, Double> t= *it_val; + _variables[type]->add_value(t.first, t.second); + } + } + } + + } + } + + // } + + /*if(_n_states!=0 && (_states.back()->get_right_state()!=NULL)) { + //add a new state at the end if not already presently + StateChange* end = new StateChange(_destruction_time,_states.back()->get_right_state(), NULL ); + _states.push_back(end); + _n_states++; + + }*/ + + +} + if(_n_events==0)_event_tree=NULL; + else _event_tree = new BinaryTree<Event>(_events, _n_events); + + if(_n_states==0)_state_tree=NULL; + else _state_tree = new BinaryTree<StateChange>(_states,_n_states); +#else if (_destruction_time.get_value() == 0.0) destroy(time); _event_tree = new Event::Tree(_events, _n_events); _state_tree = new StateChange::Tree(_states,_n_states); +#endif } diff --git a/src/trace/Container.hpp b/src/trace/Container.hpp index 4627b185..cb5560fb 100644 --- a/src/trace/Container.hpp +++ b/src/trace/Container.hpp @@ -50,6 +50,9 @@ template <typename E> class Node; template <typename E> class BinaryTree; class Statistic; class Interval; +#ifdef USE_ITC +struct IntervalOfContainer; +#endif /*! * \class Container * \brief Contains others containers or entities @@ -73,7 +76,11 @@ private: StateChange::Vector _states; StateChange::Tree *_state_tree; unsigned int _n_events; + #ifdef USE_ITC + Event** _events; + #else Event::Vector _events; + #endif Event::Tree *_event_tree; Link::Vector _links; unsigned int _n_variables; @@ -81,6 +88,9 @@ private: std::map<std::string, Value *> _extra_fields; int _depth;/* The container depth within the datastructure. The _depth of seed is equal to 0 */ + #ifdef USE_ITC + std::list<IntervalOfContainer* > _intervalsOfContainer; + #endif /* * Temporary stores states before complete definition */ diff --git a/src/trace/DrawTrace.hpp b/src/trace/DrawTrace.hpp index 8d48dd33..0a04b10a 100644 --- a/src/trace/DrawTrace.hpp +++ b/src/trace/DrawTrace.hpp @@ -315,8 +315,12 @@ public: _container_positions[container] = position + size; // First line after children // Use one line for states and events - if (!container->get_states()->empty() || !container->get_events()->empty()) { - size++; +#ifdef USE_ITC + if ((container->get_states()!=NULL && !container->get_states()->empty() )|| (container->get_events()!=NULL && !container->get_events()->empty())) { +#else + if ((!container->get_states()->empty() )|| (!container->get_events()->empty())) { +#endif + size++; _entity_containers.push_back(container); } @@ -392,17 +396,30 @@ public: state_tree = container->get_states(); event_tree = container->get_events(); - if (!state_tree->empty() || !event_tree->empty()) { - // Browse states - DrawTree<T, StateChange>(draw_object, position, lvl_zoom, - _container_height, _container_v_space, _state_height, _state_v_space) - .draw_tree(state_tree, *interval); - - // Browse events - DrawTree<T, Event>(draw_object, position, lvl_zoom, - _container_height, _container_v_space, _state_height, _state_v_space) - .draw_tree(event_tree, *interval); +#ifdef USE_ITC + if(state_tree!=NULL){ +#endif + if ( !state_tree->empty() ) { + //printf("drawing states for %s\n", container->get_name().to_string().c_str()); + // Browse states + DrawTree<T, StateChange>(draw_object, position, lvl_zoom, + _container_height, _container_v_space, _state_height, _state_v_space) + .draw_tree(state_tree, *interval); + } +#ifdef USE_ITC + } + if(event_tree!=NULL){ +#endif + if ( !event_tree->empty()){ + //printf("drawing events for %s\n", container->get_name().to_string().c_str()); + // Browse events + DrawTree<T, Event>(draw_object, position, lvl_zoom, + _container_height, _container_v_space, _state_height, _state_v_space) + .draw_tree(event_tree, *interval); + } +#ifdef USE_ITC } +#endif } }/* end for (!_stack_states.empty()) */ @@ -456,7 +473,7 @@ public: container = *c; position = (int)_container_positions[container]; - if (!container->get_states()->empty() || !container->get_events()->empty()) + if ((container->get_states()!=NULL && !container->get_states()->empty()) ||(container->get_events()!=NULL && !container->get_events()->empty())) position++; // Browse variables variable_map = container->get_variables(); @@ -587,7 +604,11 @@ public: // Now browsing for the events of the container root // Verification if it is a clic on an event +#ifndef USE_ITC if ((!container->get_events()->empty() || !container->get_states()->empty()) && yr < _container_height+_container_v_space) { +#else + if (((container->get_states()!=NULL && !container->get_states()->empty()) ||(container->get_events()!=NULL && !container->get_events()->empty())) && yr < _container_height+_container_v_space) { +#endif if (!Info::Render::_no_events) if ((event = find_event(container, x, d))) { *Message::get_instance() << "<center><strong>Event</strong></center>" @@ -616,7 +637,11 @@ public: } } else { - if (!container->get_events()->empty() || !container->get_states()->empty()) +#ifndef USE_ITC + if ((container->get_states()!=NULL && !container->get_states()->empty()) ||(container->get_events()!=NULL && !container->get_events()->empty())) +#else + if (!container->get_events()->empty() || !container->get_states()->empty()) +#endif yr -= _container_height+_container_v_space; const std::map<VariableType *, Variable *> *variable_map = container->get_variables(); std::map<VariableType *, Variable *>::const_iterator i = variable_map->begin(); @@ -669,7 +694,11 @@ public: // Calculate the size of the container (without its children) int size = 0; - if (!container->get_states()->empty() || !container->get_events()->empty()) +#ifdef USE_ITC + if ((container->get_states()!=NULL && !container->get_states()->empty()) ||(container->get_events()!=NULL && !container->get_events()->empty())) +#else + if (!container->get_states()->empty() || !container->get_events()->empty()) +#endif size++; if (container->get_variable_number() > 0) size += container->get_variable_number(); @@ -708,7 +737,11 @@ public: _container_positions[container] = position + size; // First line after children // Use one line for states and events - if (!container->get_states()->empty() || !container->get_events()->empty()) { +#ifdef USE_ITC + if ((container->get_states()!=NULL && !container->get_states()->empty()) ||(container->get_events()!=NULL && !container->get_events()->empty())){ +#else + if (!container->get_states()->empty() || !container->get_events()->empty()) { +#endif size++; } @@ -763,7 +796,7 @@ public: * \brief Returns the event that occurs at the time x in the container */ const Event *find_event(const Container *container, Element_pos x, Element_pos d) { - if(!container) + if(!container || container->get_events()==NULL) return NULL; Node<Event> *node = container->get_events()->get_root(); @@ -789,7 +822,7 @@ public: * \brief Returns the state at the time x */ const State * find_state(const Container *container, Element_pos x) { - if(!container) + if(!container || container->get_states()==NULL) return NULL; Node<StateChange> *node = container->get_states()->get_root(); diff --git a/src/trace/Entity.cpp b/src/trace/Entity.cpp index 8dfa9e8a..668fb5e0 100644 --- a/src/trace/Entity.cpp +++ b/src/trace/Entity.cpp @@ -50,12 +50,15 @@ #include "trace/values/Values.hpp" #include "trace/EntityTypes.hpp" #include "trace/Entitys.hpp" +#include "trace/Entity.hpp" /* -- */ using namespace std; Entity::Entity(Container *container, map<std::string, Value *> opt): _container(container)/*, _extra_fields(opt)*/ { if(opt.empty())_extra_fields=NULL; - else _extra_fields=new map<std::string, Value *>(opt); + else{ _extra_fields=new map<std::string, Value *>(opt); + opt.clear(); + } } @@ -77,3 +80,8 @@ Entity::~Entity(){ // (*it).second = NULL; // } } + +void Entity::clear(){ + if(_extra_fields !=NULL)delete _extra_fields; + _extra_fields=NULL; +} \ No newline at end of file diff --git a/src/trace/Entity.hpp b/src/trace/Entity.hpp index f81798ea..5af30ea8 100644 --- a/src/trace/Entity.hpp +++ b/src/trace/Entity.hpp @@ -79,6 +79,8 @@ public: const std::map<std::string, Value *> *get_extra_fields() const; ~Entity(); + + void clear(); }; #endif diff --git a/src/trace/EntityType.cpp b/src/trace/EntityType.cpp index 64c86831..d3b19688 100644 --- a/src/trace/EntityType.cpp +++ b/src/trace/EntityType.cpp @@ -53,17 +53,10 @@ using namespace std; EntityType::EntityType(Name name, ContainerType *container_type, map<std::string, Value *>& opt): _name(name), _container_type(container_type) { - if (!opt.empty()) { - _extra_fields=new map<std::string, Value *>(); - map<std::string , Value * >::iterator cur = opt.end(); - for(map<std::string, Value *>::iterator it = opt.begin(); - it != cur; - it++){ - _extra_fields->insert(*it); - } - opt.clear(); - } - else _extra_fields=NULL; + if(opt.empty())_extra_fields=NULL; + else{ _extra_fields=new map<std::string, Value *>(opt); + opt.clear(); + } } diff --git a/src/trace/StateChange.cpp b/src/trace/StateChange.cpp index 2ae55f6e..b147e0a1 100644 --- a/src/trace/StateChange.cpp +++ b/src/trace/StateChange.cpp @@ -90,3 +90,11 @@ StateChange::~StateChange(){ delete _right; _right = NULL; } +void StateChange::clear(){ + if(_left!=NULL){ + _left->clear(); + //free(_left_state); + // Alloc<State2>::Instance().free(_left_state); + } + +} \ No newline at end of file diff --git a/src/trace/StateChange.hpp b/src/trace/StateChange.hpp index 03293563..53906ddd 100644 --- a/src/trace/StateChange.hpp +++ b/src/trace/StateChange.hpp @@ -69,6 +69,8 @@ public: const State *get_left_state() const; const State *get_right_state() const; ~StateChange(); + + void clear(); }; #endif diff --git a/src/trace/Variable.cpp b/src/trace/Variable.cpp index 2e74a0d0..f7125728 100644 --- a/src/trace/Variable.cpp +++ b/src/trace/Variable.cpp @@ -88,7 +88,7 @@ Double Variable::get_max() const { return _max; } -const VariableType *Variable::get_type() const { +VariableType *Variable::get_type() const { return _type; } diff --git a/src/trace/Variable.hpp b/src/trace/Variable.hpp index d1be638d..be9deba2 100644 --- a/src/trace/Variable.hpp +++ b/src/trace/Variable.hpp @@ -103,7 +103,7 @@ public: /*! * \brief Get the type of the variable */ - const VariableType *get_type() const; + VariableType *get_type() const; }; diff --git a/src/trace/tree/BinaryTree.hpp b/src/trace/tree/BinaryTree.hpp index acd5bf92..16b9504d 100644 --- a/src/trace/tree/BinaryTree.hpp +++ b/src/trace/tree/BinaryTree.hpp @@ -56,6 +56,141 @@ private: Node<E> *_root; public: + + /*! + * \brief Constructor + * \param list List from which the tree is made + * \param size Number of element in the list + */ + BinaryTree(E * list[], unsigned int size) { + if (size == 0 || list==NULL ||list[0]==NULL) { + _root = NULL; + return; + } + + // Calculate n and m as size = 2^n - 1 + m and m < 2^n + int n = 0; + unsigned int a = 1; + while (size >= 2*a - 1) { + a *= 2; + n++; + } + int m = size - a + 1; + + // Initialize the array + Node<E> **temp = new Node<E> *[n+1]; + int start = 0; + int i = 0; + for (i = 0; i < n+1; i++) + temp[i] = NULL; + + i = 0; + // Reads elements from the list and empty it + for (unsigned int j=0; j<size; j++) { + E *element = list[j]; + + while (temp[i]) // Find the first free element in temp + i++; + + temp[i] = new Node<E>(element); + + if (i == 0 && m > 0) { // The node is a leaf and its depth is n+1 + m--; + if (m == 0) + start = 1; + } + + if (i < n && temp[i+1]) { // The node has a parent + temp[i]->_parent = temp[i+1]; + temp[i+1]->_right_child = temp[i]; + } + + if (i > 0 && temp[i-1]) { // The node is not a leaf + temp[i]->_left_child = temp[i-1]; + temp[i-1]->_parent = temp[i]; + while (i > 0) { + i--; + temp[i] = NULL; + } + i = start; + } + } + + _root = temp[n-1+start]; + + delete[] temp; + // delete[] list; + } + + + /*! + * \brief Constructor + * \param list List from which the tree is made + * \param size Number of element in the list + */ + BinaryTree(E * list, unsigned int size) { + if (size == 0 || list==NULL) { + _root = NULL; + return; + } + + // Calculate n and m as size = 2^n - 1 + m and m < 2^n + int n = 0; + unsigned int a = 1; + while (size >= 2*a - 1) { + a *= 2; + n++; + } + int m = size - a + 1; + + // Initialize the array + Node<E> **temp = new Node<E> *[n+1]; + int start = 0; + int i = 0; + for (i = 0; i < n+1; i++) + temp[i] = NULL; + + i = 0; + // Reads elements from the list and empty it + for (unsigned int j=0; j<size; j++) { + E *element = &(list[j]); + + while (temp[i]) // Find the first free element in temp + i++; + + temp[i] = new Node<E>(element); + + if (i == 0 && m > 0) { // The node is a leaf and its depth is n+1 + m--; + if (m == 0) + start = 1; + } + + if (i < n && temp[i+1]) { // The node has a parent + temp[i]->_parent = temp[i+1]; + temp[i+1]->_right_child = temp[i]; + } + + if (i > 0 && temp[i-1]) { // The node is not a leaf + temp[i]->_left_child = temp[i-1]; + temp[i-1]->_parent = temp[i]; + while (i > 0) { + i--; + temp[i] = NULL; + } + i = start; + } + } + + _root = temp[n-1+start]; + + delete[] temp; + // delete[] list; + } + + + + /*! * \brief Constructor * \param list List from which the tree is made -- GitLab