#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; }