diff --git a/cg/cg3600.cpp b/cg/cg3600.cpp new file mode 100755 index 000000000..e26fa53d9 --- /dev/null +++ b/cg/cg3600.cpp @@ -0,0 +1,287 @@ +#include + +#include + +#include "cg3.h" + +/////////////////////////////////////////////////////////// +// TList +/////////////////////////////////////////////////////////// + +class TList : public TContainer +{ + enum { MAX_SKIP = 8192 }; + + struct TList_object : public TObject + { + TObject* _obj; + TList_object* _next; + TList_object* _prev; + }; + + TList_object** _skip; + long _items, _current; + long _step, _last_skip; + +protected: + // @cmember Ritorna un puntatore al primo oggetto del contenitore + virtual TObject* first_item( ); + // @cmember Ritorna un puntatore all'ultimo oggetto del contenitore + virtual TObject* last_item( ); + // @cmember Ritorna un puntatore all'oggetto successivo all'oggetto corrente + virtual TObject* succ_item( ); + // @cmember Ritorna un puntatore all'oggetto che precede l'oggetto corrente + virtual TObject* pred_item( ); + // @cmember Ritorna il numero di oggetti nel contenitore + virtual long objects( ); + +protected: + TList_object* detach_lstobj(long index); + TList_object* lstobjptr(long index); + void change_step(long step); + +public: + + TObject* TList::objptr(long index); + + void destroy(); + long insert(TObject* obj, long pos); + long add(TObject* obj, long pos = -1); + + TObject* detach(long pos); + bool remove(long pos); + + TList(long expected_size); + virtual ~TList(); +}; + +TList::TList(long expected_size) + : _items(0), _current(0) +{ + _step = expected_size / MAX_SKIP + 1; + _last_skip = 0; + + _skip = new TList_object*[MAX_SKIP]; + _skip[0] = NULL; +} + +TList::~TList() +{ + destroy(); + delete [] _skip; +} + +long TList::objects( ) +{ + return _items; +} + +TObject* TList::first_item() +{ + return objptr(_current = 0); +} + +TObject* TList::succ_item() +{ + return objptr(++_current); +} + +TObject* TList::pred_item() +{ + return objptr(_current++); +} + +TObject* TList::last_item() +{ + return objptr(_current = _items-1); +} + +void TList::destroy() +{ + TList_object* head = _skip[0]; + while (head) + { + TList_object* next = head->_next; + if (head->_obj) + delete head->_obj; + delete head; + head = next; + } + _items = _current = _last_skip = 0; + _skip[0] = NULL; +} + +TList::TList_object* TList::lstobjptr(long index) +{ + TList_object* lstobj = NULL; + const ldiv_t p = ldiv(index, _step); + if (p.quot >= 0 && p.quot < _last_skip) + { + TList_object* lo = _skip[p.quot]; + for (long s = p.rem; lo && s > 0; s--) + lo = lo->_next; + + lstobj = lo; + } + return lstobj; +} + +TObject* TList::objptr(long index) +{ + TList_object* lo = lstobjptr(index); + return lo ? lo->_obj : NULL; +} + +void TList::change_step(long step) +{ + CHECKD(step > 0 && step <= 16384, "Bad list step ", step); + _step = step; + _last_skip = 0; + + step = 0; + for (TList_object* lo = _skip[0]; lo; lo = lo->_next, step--) + { + if (step == 0) + { + CHECK(_last_skip < MAX_SKIP, "Too many items"); + _skip[_last_skip++] = lo; + step = _step; + } + } +} + +long TList::insert(TObject* obj, long index) +{ + if (index < 0) + index = 0; + else + { + if (index > _items) + index = _items; + } + const long pred = index-1; + + TList_object* newobj = new TList_object; + newobj->_obj = obj; + + if (pred < 0) + { + newobj->_prev = NULL; + newobj->_next = _skip[0]; + if (_skip[0]) + _skip[0]->_prev = newobj; + } + else + { + TList_object* lo = lstobjptr(pred); + CHECK(lo, "NULL insertion point"); + newobj->_next = lo->_next; + newobj->_prev = lo; + if (lo->_next) + lo->_next->_prev = newobj; + lo->_next = newobj; + } + _items++; + + ldiv_t p = ldiv(index, _step); + if (p.rem == 0 && p.quot < MAX_SKIP) // Cambia il capolista + _skip[p.quot] = newobj; + + for (long i = p.quot + 1; i < _last_skip; i++) + _skip[i] = _skip[i]->_prev; // Aggiorna capilista successivi + + // Siamo andati oltre l'ultimo skip + const long s = (_items - 1) / _step + 1; + if (s > _last_skip) + { + if (s > MAX_SKIP) + change_step(_step+1); + else + _last_skip++; + } + + return index; +} + +long TList::add(TObject* obj, long index) +{ + if (index < 0 || index >= _items) + { + index = insert(obj, _items); + } + else + { + TList_object* lo = lstobjptr(index); + CHECK(lo, "NULL list object"); + delete lo->_obj; + lo->_obj = obj; + } + return index; +} + +TList::TList_object* TList::detach_lstobj(long index) +{ + TList_object* lo = lstobjptr(index); + if (lo) + { + if (lo->_prev) + lo->_prev->_next = lo->_next; + if (lo->_next) + lo->_next->_prev = lo->_prev; + ldiv_t res = ldiv(index, _step); + if (res.rem == 0) + _skip[res.quot] = lo->_next; + long p; + for (p = res.quot + 1; p < _last_skip; p++) + _skip[p] = _skip[p]->_next; + + _items--; + + p = (_items - 1) / _step + 1; + if (p < _last_skip) + { + _last_skip--; + _skip[_last_skip] = NULL; + } + } + + return lo; +} + +TObject* TList::detach(long index) +{ + TList_object* lo = detach_lstobj(index); + TObject* obj; + if (lo) + { + obj = lo->_obj; + delete lo; + } + else + obj = NULL; + return obj; +} + +bool TList::remove(long index) +{ + TObject* o = detach(index); + if (o) + delete o; + return o != NULL; +} + +#include + +int cg3600(int argc, char* argv[]) +{ + long max = 100000L; + TList l(max); + const clock_t start = clock(); + + for (long i = 0; i < max; i++) + l.add(NULL); + + const clock_t end = clock()-start; + + return 0; +} \ No newline at end of file