home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************
- +
- + LEDA 2.1.1 11-15-1991
- +
- +
- + _list.c
- +
- +
- + Copyright (c) 1991 by Max-Planck-Institut fuer Informatik
- + Im Stadtwald, 6600 Saarbruecken, FRG
- + All rights reserved.
- +
- *******************************************************************************/
-
-
- #include <LEDA/list.h>
-
- /* Definition der Member-Funktionen der Klasse "dlist"
- (doppelt verkettete Listen)
-
- Stefan Naeher
- FB10 Informatik
- Universitaet des Saarlandes
- 6600 Saarbruecken
-
- September 1988
-
- */
-
- //------------------------------------------------------------------------------
- // Members of class dlist: base class for all lists
- //------------------------------------------------------------------------------
-
- dlist::dlist()
- { h=0;
- t=0;
- count=0;
- iterator=0;
- }
-
- dlist::dlist(ent a)
- { h=t=new dlink(a,0,0);
- count=1;
- iterator=0;
- }
-
- dlist::dlist(const dlist& x)
- { h=0;
- t=0;
- count=0;
- iterator=0;
-
- dlink* p = x.h;
-
- while (p) { x.copy_el(p->e); /* copy list using virtual copy_el of x !! */
- append(p->e); // does not make a copy !!
- p = p->succ;
- }
- }
-
- //------------------------------------------------------------------------------
- // Iteration:
- //------------------------------------------------------------------------------
-
- dlink* dlist::move_iterator(int dir) const
- { if (iterator)
- set_iterator(dir ? iterator->pred : iterator->succ);
- else
- set_iterator(dir ? t : h);
- return iterator;
- }
-
- bool dlist::current_element(ent& x) const
- { if (iterator)
- { x = iterator->e;
- return true;
- }
- return false;
- }
-
- bool dlist::next_element(ent& x) const
- { if (iterator)
- set_iterator(iterator->succ);
- else
- set_iterator(h);
-
- if (iterator)
- { x = iterator->e;
- return true;
- }
- return false;
- }
-
- bool dlist::prev_element(ent& x) const
- { if (iterator)
- set_iterator(iterator->pred);
- else
- set_iterator(t);
-
- if (iterator)
- { x = iterator->e;
- return true;
- }
- return false;
- }
-
- //------------------------------------------------------------------------------
-
- dlink* dlist::get_item(int i) const
- { dlink* p = h;
- while ( p && i--) p = p->succ;
- return p;
- }
-
- dlink* dlist::succ(dlink* p, int i) const
- { while ( p && i--) p = p->succ;
- return p;
- }
-
- dlink* dlist::pred(dlink* p, int i) const
- { while ( p && i--) p = p->pred;
- return p;
- }
-
- dlink* dlist::search(ent x) const /* linear search */
- { dlink* p = h;
- while ( p && (p->e != x)) p = p->succ;
- return p;
- }
-
- int dlist::rank(ent x) const /* rank by linear search */
- { dlink* p = h;
- int r = 1;
- while ( p && (p->e != x))
- { p = p->succ;
- r++;
- }
- return (p) ? r : 0;
- }
-
- void dlist::pop()
- { if (iterator!=0) error_handler(1,"pop: deletion while iterator is active");
- dlink* x=h;
- if (count==0) return;
- if (--count) { h = h->succ; h->pred = 0; }
- else h = t = 0;
- clear_el(x->e);
- delete x;
- }
-
- void dlist::Pop()
- { if (iterator!=0) error_handler(1,"Pop: deletion while iterator is active");
- dlink* x=t;
- if (count==0) return;
- if (--count) { t = t->pred; t->succ = 0; }
- else h = t = 0;
- clear_el(x->e);
- delete x;
- }
-
- dlink* dlist::insert(ent a, dlink* l, int dir)
- {
- if (iterator!=0) error_handler(2,"insert: insertion while iterator is active");
-
- if (l==0) return dir ? append(a) : push(a);
-
- dlink* s=l->succ;
- dlink* p=l->pred;
- dlink* n;
-
- if (dir==0) //insert after l
- { n= new dlink(a,l,s);
- l->succ = n;
- if (l==t) t=n;
- else s->pred = n;}
-
- else //insert before l
- { n= new dlink(a,p,l);
- l->pred = n;
- if (l==h) h=n;
- else p->succ = n;}
-
- count++;
-
- return n;
- }
-
- dlink* dlist::push(ent a)
- { if (iterator!=0) error_handler(2,"push: insertion while iterator is active");
- count++;
- if (h) h = h->pred = new dlink(a,0,h);
- else h = t = new dlink(a,0,0);
- return h;
- }
-
- dlink* dlist::append(ent a)
- { if(iterator!=0) error_handler(2,"append: insertion while iterator is active");
- count++;
- if (t) t = t->succ = new dlink(a,t,0);
- else t = h = new dlink(a,0,0);
- return t;
- }
-
- void dlist::conc(dlist& l)
- { if (iterator!=0) error_handler(2,"conc: iterator is active");
- if (t) { t->succ = l.h;
- if (l.h) { l.h->pred = t; t = l.t; } }
- else { h = l.h; t = l.t; }
- count = count+l.count;
- l.h = l.t = 0;
- l.count = 0;
- }
-
-
- void dlist::split(dlink* p, dlist& l1, dlist& l2)
- { if (iterator!=0)
- error_handler(1,"list: split while iterator is active");
-
- //if (p==nil) error_handler(888,"split at nil item");
-
- l1.clear();
- l2.clear();
-
- if (p==nil) // l1 = empty, l2 = l, l = empty;
- { l2.h = h;
- l2.t = t;
- l2.count = count;
- h = t = 0;
- count = 0;
- return;
- }
-
- if (h == 0) return; /* empty list */
-
-
- if (p->pred)
- { l1.h = h;
- l1.t = p->pred;
- p->pred->succ = 0;
- }
-
- p->pred = 0;
- l2.h = p;
- l2.t = t;
-
-
- // have to set counters
- // "count the smaller half" gives amortized n log n bound
-
- dlink* l = l1.h;
- dlink* r = l2.h;
- int c = 0;
-
- while (l && r)
- { l = l->succ;
- r = r->succ;
- c++;
- }
-
- if (l==0) // left end reached first
- { l1.count = c;
- l2.count = count - l1.count;
- }
-
- else
- { l2.count = c;
- l1.count = count - l2.count;
- }
-
- /* make original list empty */
-
- h = t = 0;
- count = 0;
-
- }
-
-
- void dlist::del(dlink* loc)
- { if (iterator!=0)
- error_handler(1,"dlist::del: deletion while iterator is active");
-
- if (loc==0)
- error_handler(999,"dlist::del: item = nil");
-
- if (loc==h) { pop(); return; }
-
- if (loc==t) { Pop(); return; }
-
-
- dlink* p = loc->pred;
- dlink* s = loc->succ;
- p->succ = s;
- s->pred = p;
- count--;
-
- clear_el(loc->e);
- delete loc;
- }
-
- dlink* dlist::cyclic_succ(dlink* loc) const
- { if (loc==0) return 0;
- return loc->succ? loc->succ : h;
- }
-
- dlink* dlist::cyclic_pred(dlink* loc) const
- { if (loc==0) return 0;
- return loc->pred? loc->pred : t;
- }
-
- dlink* dlist::max(CMP_ENT f) const
- { if (h==0) return 0;
- dlink* m=h;
- dlink* p=m->succ;
-
- if (f) // use cmp function f
- while (p)
- { if (f(p->e,m->e)) m=p;
- p=p->succ;
- }
- else /* // use virtual cmp function
- while (p)
- { if (cmp(p->e,m->e)) m=p;
- p=p->succ;
- }
- */
- error_handler(1,"list: max needs cmp function parameter");
-
- return m;
- }
-
- dlink* dlist::min(CMP_ENT f) const
- { if (h==0) return 0;
- dlink* m=h;
- dlink* p=m->succ;
-
- if (f) // use cmp function f
- while (p)
- { if (f(m->e,p->e)) m=p;
- p=p->succ;
- }
- else /* // use virtual cmp function
- while (p)
- { if (cmp(m->e,p->e)) m=p;
- p=p->succ;
- }
- */
- error_handler(1,"list: min needs cmp function parameter");
-
- return m;
- }
-
- void dlist::apply(ENT_TO_VOID f)
- { dlink* p = h;
-
- while (p)
- { f(p->e);
- p = p->succ;
- }
- }
-
- void dlist::permute()
- {
- if (iterator!=0) error_handler(3,"permute: modification while iterator is active");
-
- list_item* A = new list_item[count+2];
- list_item x = h;
- int j;
-
- A[0] = A[count+1] = 0;
-
- for(j=1; j <= count; j++)
- { A[j] = x;
- x = x->succ;
- }
-
- init_random();
-
- for(j=1; j<count; j++)
- { int r = random(j,count);
- if (j!=r) SWAP(A[j],A[r]);
- }
-
- for(j=1; j<=count; j++)
- { A[j]->succ = A[j+1];
- A[j]->pred = A[j-1];
- }
-
- h = A[1];
- t = A[count];
-
- delete A;
- }
-
-
- void dlist::bucket_sort(int i, int j, ENT_TO_INT f)
- { if (iterator!=0) error_handler(3,"bucket_sort: modification while iterator is active");
- int k;
- dlist* bucket= new dlist[j-i+1];
- ent e;
-
- while (count) { e = head();
- copy_el(e);
- pop(); // destroys one copy
- k = f(e);
- if ((k>=i)&&(k<=j)) bucket[k-i].append(e);
- else error_handler(4,"bucket_sort: value out of range") ;
- }
- for (k=i;k<=j;k++)
- while (bucket[k-i].count)
- { e = bucket[k-i].head();
- append(e);
- bucket[k-i].pop(); // no destroy in dlist::pop
- }
-
- delete (char*)bucket;
- }
-
- /*
- void dlist::quick_sort(dlink** A,int l, int r)
- { // use virtual cmp routine (member of dlist)
-
- register int i = l;
- register int k = r+1;
- ent s = A[l]->e;
- //dlink* t;
-
- while (i<k)
- { while (i < r && cmp(A[++i]->e,s) < 0);
- while (k > l && cmp(A[--k]->e,s) > 0);
- if (k>i) SWAP(A[i],A[k]);
- }
-
- SWAP(A[l],A[k]);
-
- if (l < k-1) quick_sort(A,l,k-1);
- if (r > k+1) quick_sort(A,k+1,r);
- }
- */
-
-
- void dlist::quick_sort(dlink** A,int l, int r, CMP_ENT cmp_fct)
- { // use ordering defined by cmp_fct(ent& x,ent& y)
-
- register int i = l;
- register int k = r+1;
- ent s = A[l]->e;
- //dlink* t;
-
- while (i<k)
- { while (i<r && cmp_fct(A[++i]->e,s)<0);
- while (k>l && cmp_fct(A[--k]->e,s)>0);
- if (k>i) SWAP(A[i],A[k]);
- }
-
- SWAP(A[l],A[k]);
-
- //t = A[l];
- //A[l] = A[k];
- //A[k] = t;
-
- if (l < k-1) quick_sort(A,l,k-1,cmp_fct);
- if (r > k+1) quick_sort(A,k+1,r,cmp_fct);
- }
-
- void dlist::sort(CMP_ENT cmp_fct)
- { if (iterator!=0)
- error_handler(1,"sort: modification while iterator is active");
-
- if (count==0) return; // nothing to sort
-
- register int i;
- register dlink* loc = h;
- dlink** A = new dlink*[count+2];
-
- A[0] = A[count+1] = 0;
-
- for(i=1;i<=count;i++)
- { A[i] = loc;
- loc = loc->succ;
- }
-
- init_random();
-
- for(i=1;i<=count;i++)
- { int j = random(1,count); // random permutation
- if (i!=j) SWAP(A[i],A[j]);
- }
-
- if (cmp_fct)
- quick_sort(A,1,count,cmp_fct);
- else // quick_sort(A,1,count);
- error_handler(1,"list: sort needs cmp function parameter");
-
- for (i=1;i<=count;i++)
- { A[i]->succ = A[i+1];
- A[i]->pred = A[i-1];
- }
-
- h = A[1];
- t = A[count];
-
- delete A;
- }
-
-
- dlist& dlist::operator=(const dlist& x)
- { iterator=0;
- clear();
-
- dlink* p = x.h;
-
- while (p) { copy_el(p->e);
- append(p->e); // does not make a copy !!!
- p = p->succ;
- }
- return *this;
- }
-
- dlist dlist::operator+(const dlist& x) // concatenation
- {
- dlist y = x;
- dlink* p = t;
- while (p) { x.copy_el(p->e);
- y.push(p->e);
- p = p->pred;}
- return y;
- }
-
- void dlist::clear()
- { if (h==nil) return;
- register dlink* p = h;
- while (p)
- { clear_el(p->e);
- p = p->succ;
- //delete h;
- //h = p;
- }
- deallocate_list(h,t,3);
- h=0;
- t=0;
- iterator=0;
- count=0;
- }
-
- void dlist::print(ostream& out, string s, char space) const
- { list_item l = h;
- cout << s;
- if (l)
- { print_el(l->e,out);
- l = l->succ;
- while (l)
- { out << chr(space);
- print_el(l->e,out);
- l = l->succ;
- }
- }
- out.flush();
- }
-
- void dlist::read(istream& in, string s, char delim)
- { char c;
- ent x;
- cout << s;
-
- clear();
- while (in)
- { in.get(c);
- if (c==delim) break;
- in.putback(c);
- read_el(x,in); // creates an object
- append(x); // makes no copy (dlist)
- }
-
- }
-