campo-sirio/cg/cg3600.cpp
guy 5ace216fda Mastrini a video!
git-svn-id: svn://10.65.10.50/trunk@3893 c028cbd2-c16b-5b4b-a496-9718f37d4682
1996-11-12 15:19:17 +00:00

287 lines
5.4 KiB
C++
Executable File

#include <stdlib.h>
#include <array.h>
#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 <time.h>
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;
}