home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************
- +
- + LEDA 2.1.1 11-15-1991
- +
- +
- + _range_tree.c
- +
- +
- + Copyright (c) 1991 by Max-Planck-Institut fuer Informatik
- + Im Stadtwald, 6600 Saarbruecken, FRG
- + All rights reserved.
- +
- *******************************************************************************/
-
-
-
- // ------------------------------------------------------------------
- //
- // d-dimensional Range Trees
- //
- // Michael Wenzel (1990)
- //
- // Implementation follows
- // Data Structure Lecture, K. Mehlhorn, Summer 1989
- // K. Mehlhorn: Data Structures and Algorithms, Vol. 3
- //
- // ------------------------------------------------------------------
-
- #include <LEDA/range_tree.h>
-
- enum left_or_right {left = 0, right = 1};
-
- #undef TEST
- #undef DUMP
- #undef STAT
-
- #ifdef TEST
- #define DPRINT(x) cout << x
- #else
- #define DPRINT(x)
- #endif
-
- #ifdef DUMP
- #define DDUMP(x) cout << x
- #else
- #define DDUMP(x)
- #endif
-
- #ifdef STAT
- #define DSTAT print_statistics()
- #else
- #define DSTAT
- #endif
-
- //------------------------------------------------------------------
- // member-functions of class tuple
- //
- // Michael Wenzel (1990)
- //------------------------------------------------------------------
-
- tuple::tuple()
- {
- d=0;
- t=0; }
-
- tuple::tuple(ent a, ent b)
- {
- d=2;
- t=new ent[2];
- t[0] = a;
- t[1] = b; }
-
- tuple::tuple(ent a, ent b, ent c)
- {
- d=3;
- t=new ent[3];
- t[0] = a;
- t[1] = b;
- t[2] = c; }
-
- tuple::tuple(int dim)
- {
- d=dim;
- inf = 0;
- t=new ent[dim]; }
-
- tuple::~tuple()
- { if (t)
- delete t;
- }
-
- //-------------------------------------------------------------------
- // RANGE TREE
- //-------------------------------------------------------------------
-
-
- int range_tree::tuple_cmp(tuplep p, tuplep q)
- { int i = p->cmp_dim();
- int stop = (i==0) ? p->d-1 : i-1;
- int res;
- while ((res=cmp_tuple_entry(i,p,q))==0 && i!=stop)
- i=(i+1)%p->d;
- return res;
- }
-
- // ------------------------------------------------------------
- // lrot() , rrot() , ldrot() , rdrot()
- // Rotationen am Knoten p
-
- void range_tree::lrot(bb_item p, bb_item q)
- {
- bb_item h = p->sohn[right];
- int help_dim = key(h)->cmp_dim();
- key(h)->set_cmp(key(h)->dimension()-dim+1);
-
- DDUMP("lrot "<< (int)key(p)) ;
- if (q) DDUMP(" Vater " << (int)(key(q)));
- DDUMP("\n");
-
- p->sohn[right] = h->sohn[left];
- h->sohn[left] = p;
- if (!q)
- root=h;
- else
- { if (tuple_cmp(key(h),key(q))>0)
- q->sohn[right]=h;
- else
- q->sohn[left]=h;
- }
- p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
- h->gr=p->groesse()+h->sohn[right]->groesse();
-
- // update nodelists
- list(range_tree_item) L;
- range_tree_item x;
-
- bb_item s = p->sohn[left];
- if (s->blatt())
- inf(h)->insert_tuple(key(s));
- else
- { L = inf(s)->all_tuples();
- forall(x,L) inf(h)->insert_tuple(x);
- L.clear();
- }
-
- s = h->sohn[right];
- if (s->blatt())
- inf(h)->del_tuple(key(s));
- else
- { L = inf(s)->all_tuples();
- forall(x,L) inf(p)->del_tuple(x);
- }
-
- key(h)->set_cmp(help_dim);
- }
-
- void range_tree::rrot(bb_item p, bb_item q)
- {
- bb_item h = p->sohn[left];
- int help_dim = key(h)->cmp_dim();
- key(h)->set_cmp(key(h)->dimension()-dim+1);
-
- DDUMP("rrot "<< (int)(key(p))) ;
- if (q) DDUMP(" Vater " << (int)(key(q)));
- DDUMP("\n");
-
- p->sohn[left] = h->sohn[right];
- h->sohn[right] = p;
- if (!q) root=h;
- else
- { if (tuple_cmp(key(h),key(q))>0)
- q->sohn[right] = h;
- else
- q->sohn[left] = h; }
- p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
- h->gr=p->groesse()+h->sohn[left]->groesse();
-
- // update nodelists
- list(range_tree_item) L;
- range_tree_item x;
- bb_item s = p->sohn[right];
- if (s->blatt())
- inf(h)->insert_tuple(key(s));
- else
- { L = inf(s)->all_tuples();
- forall(x,L) inf(h)->insert_tuple(x);
- L.clear();
- }
-
- s = h->sohn[left];
- if (s->blatt())
- inf(p)->del_tuple(key(s));
- else
- { L = inf(s)->all_tuples();
- forall(x,L) inf(p)->del_tuple(x);
- }
- key(h)->set_cmp(help_dim);
- }
-
- void range_tree::ldrot(bb_item p, bb_item q)
- {
- bb_item h = p->sohn[right];
- bb_item g = h->sohn[left];
- int help_dim = key(h)->cmp_dim();
- key(h)->set_cmp(key(h)->dimension()-dim+1);
-
- DDUMP("ldrot "<< (int)(key(p))) ;
- if (q) DDUMP(" Vater " << (int)(key(q)));
- DDUMP("\n");
-
- p->sohn[right] = g->sohn[left];
- h->sohn[left] = g->sohn[right];
- g->sohn[left] = p;
- g->sohn[right] = h;
- if (!q) root=g;
- else
- { if (tuple_cmp(key(h),key(q))>0)
- q->sohn[right] =g ;
- else
- q->sohn[left] = g ; }
- p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
- h->gr=h->sohn[left]->groesse()+h->sohn[right]->groesse();
- g->gr=p->groesse()+h->groesse();
- // update nodelists
- list(range_tree_item) L;
- range_tree_item x;
- range_tree* help = (range_tree*)g->inf;
-
- g->inf = p->inf;
-
- bb_item s = p->sohn[right];
- if (s->blatt())
- inf(h)->del_tuple(key(s));
- else
- { L = inf(s)->all_tuples();
- forall(x,L) inf(h)->del_tuple(x);
- L.clear();
- }
-
- s = h->sohn[left];
- if (s->blatt())
- help->del_tuple(key(s));
- else
- { L = inf(s)->all_tuples();
- forall(x,L) help->del_tuple(x);
- L.clear();
- }
-
- s = p->sohn[left];
- if (s->blatt())
- help->insert_tuple(key(s));
- else
- { L = inf(s)->all_tuples();
- forall(x,L) help->insert_tuple(x);
- }
-
- p->inf = (ent) help;
- key(h)->set_cmp(help_dim);
- }
-
- void range_tree::rdrot(bb_item p, bb_item q)
-
- {
- bb_item h = p->sohn[left];
- bb_item g = h->sohn[right];
- int help_dim = key(h)->cmp_dim();
- key(h)->set_cmp(key(h)->dimension()-dim+1);
-
- DDUMP("rdrot "<< (int)(key(p))) ;
- if (q) DDUMP(" Vater " << (int)(key(q)));
- DDUMP("\n");
-
- p->sohn[left] = g->sohn[right];
- h->sohn[right] = g->sohn[left];
- g->sohn[right] = p;
- g->sohn[left] = h;
- if (!q) root=g;
- else
- { if (tuple_cmp(key(h),key(q))>0)
- q->sohn[right] =g ;
- else
- q->sohn[left] = g ; }
- p->gr=p->sohn[left]->groesse()+p->sohn[right]->groesse();
- h->gr=h->sohn[left]->groesse()+h->sohn[right]->groesse();
- g->gr=p->groesse()+h->groesse();
- // update nodelists
- list(range_tree_item) L;
- range_tree_item x;
- range_tree* help = (range_tree*)g->inf;
-
- g->inf = p->inf;
-
- bb_item s = p->sohn[left];
- if (s->blatt())
- inf(h)->del_tuple(key(s));
- else
- { L = inf(s)->all_tuples();
- forall(x,L) inf(h)->del_tuple(x);
- L.clear();
- }
-
- s = h->sohn[right];
- if (s->blatt())
- help->del_tuple(key(s));
- else
- { L = inf(s)->all_tuples();
- forall(x,L) help->del_tuple(x);
- L.clear();
- }
-
- s = p->sohn[right];
- if (s->blatt())
- help->insert_tuple(key(s));
- else
- { L = inf(s)->all_tuples();
- forall(x,L) help->insert_tuple(x);
- }
-
- p->inf = (ent) help;
- key(h)->set_cmp(help_dim);
- }
-
- // ------------------------------------------------------------
- // check(x,y,z)
- // check if a tuple x lies between y and z
- // some coordinates are already checked
-
- bool range_tree::check(tuplep x, tuplep y, tuplep z)
-
- { bool found=true;
- int help_dim = x->cmp_dim();
-
- for (int i=x->dimension()-dim+1;i<=x->dimension();i++)
- { x->set_cmp(i);
- if ((tuple_cmp(x,y)<0)||(tuple_cmp(x,z)>0))
- { x->set_cmp(help_dim);
- return false;
- }
- }
- x->set_cmp(help_dim);
- return found;
- }
-
-
- //-------------------------------------------------------------------
- // insert_tuple
- // insert a tuple into a range_tree:
- // - insert tuple according to first coordinate in main tree (bb-alpha)
- // - insert tuple according to second coordinate in all nodetrees
- // on the path of the main tree from the root to the tuple
-
- range_tree_item range_tree::insert_tuple(tuple* x)
-
- { bb_tree_item inserted;
- tuplep y;
- int help_dim = x->cmp_dim();
- x->set_cmp(x->dimension()-dim+1);
-
- DPRINT("insert tuple " << (int)x << " in " << dim << " dimension ") ;
- DPRINT("and comparedimension " << x->cmp_dim() << "\n");
-
- if (inserted=rm_tree::lookup(x))
- {
- tuplep y=key(inserted);
- clear_inf((ent&)y); // clear tuple and change inf
- y->info() = x->info();
- copy_inf((ent&)y);
- clear_tuple(x);
- delete x;
-
- return y;
- }
-
- if (dim==1)
- { bb_tree_item t,father;
- inserted = sinsert(x,0);
-
- if (!st.empty())
- st.pop(); // pop father of leaf
-
- // rebalancieren
- while (!st.empty())
- { t=st.pop();
- father = st.empty() ? 0 : st.top();
- t->gr++;
- float i = t->bal();
-
- DDUMP("rebal cur=" << (int)(key(t)) << " groesse= " << t->groesse() << " bal= " << i << " in Dimension 1\n");
-
- tuplep help = key(t);
- int help_dimt = help->cmp_dim();
- help->set_cmp(help->dimension());
- if (i < alpha)
- if (t->sohn[right]->bal()<=d) bb_tree::lrot(t,father);
- else bb_tree::ldrot(t,father);
- else if (i>1-alpha)
- if (t->sohn[left]->bal() > d ) bb_tree::rrot(t,father);
- else bb_tree::rdrot(t,father);
- help->set_cmp(help_dimt);
- }
- x->set_cmp(help_dim);
-
- return key(inserted);
- }
-
- else
- { bb_tree_item it,it1;
- range_tree* t = new_range_tree(dim-1);
-
- it = sinsert(x,t);
- inserted = it ;
- DDUMP(" bei leerem Baum ");
- t->insert_tuple(x);
- // rebalance tree and insert
- // tuple into nodelists
-
- if (!st.empty()) // insert correct tuple
- { it1=st.pop(); // node needs no rebalancing
- DDUMP("bei " << (int)(key(it1)) << " " );
- if (it==bb_tree::max())
- { inf(it1)->insert_tuple(x);
- x->set_cmp(x->dimension()-dim+1);
- }
- else
- { y= key(succ(it));
- inf(it1)->insert_tuple(y);
- y->set_cmp(y->dimension()-dim+1);
- }
- }
-
- while (!st.empty())
- { it=st.pop();
- DDUMP("bei " << (int)(key(it)) << " " );
- inf(it)->insert_tuple(x);
- it1 = st.empty() ? 0 : st.top();
- it->gr++;
- float i = it->bal();
- DDUMP("rebal cur=" << (int)(key(it)) << " groesse= " << it->groesse() << " bal= " << i << " in dimension " << dim << "\n");
-
- if (i < alpha)
- if (it->sohn[right]->bal()<=d) lrot(it,it1);
- else ldrot(it,it1);
- else if (i>1-alpha)
- if (it->sohn[left]->bal() > d ) rrot(it,it1);
- else rdrot(it,it1);
- }
- x->set_cmp(help_dim);
- return key(inserted);
- }
- }
-
- //-------------------------------------------------------------------
- // delete
- // delete a tuple in a range_tree:
- // - delete tuple in all nodetrees on the path of the main tree
- // from the root to the tuple
- // - delete tuple in main tree
-
- void range_tree::del(tuplep x)
-
- {
- tuplep y = del_tuple(x);
- if (y)
- { clear_tuple(y);
- delete y;
- }
- }
-
- tuplep range_tree::del_tuple(tuplep x)
-
- {
- DPRINT("delete tuple " << (int)x << " in " << dim << " dimension\n");
-
- tuplep deleted;
- int help_dim = x->cmp_dim();
- x->set_cmp(x->dimension()-dim+1);
- if (dim==1)
- { bb_item p,father;
- p = sdel(x);
- if (p)
- {
- deleted=key(p);
- delete (p);
- if (!st.empty())
- delete (st.pop());
- while (!st.empty())
- { p = st.pop();
- father = st.empty() ? 0 : st.top() ;
- p->gr--;
- float i=p->bal();
- DDUMP("rebal cur=" << (int)(key(p)) << " groesse= " << p->groesse() << " bal= " << i << " in dimension " << dim << "\n");
-
- tuplep help = key(p);
- int help_dimp = help->cmp_dim();
- help->set_cmp(help->dimension());
- if (i<alpha)
- if (p->sohn[right]->bal() <= d) bb_tree::lrot(p,father);
- else bb_tree::ldrot(p,father);
- else if (i>1-alpha)
- if(p->sohn[left]->bal() > d) bb_tree::rrot(p,father);
- else bb_tree::rdrot(p,father);
- help->set_cmp(help_dimp);
- }
- }
- x->set_cmp(help_dim);
- return deleted;
- }
-
- else
- { if (empty()) return 0;
- if (size()==1) // only one tuple
- { DDUMP("delete only element\n");
- tuplep y=key(root);
- if ( tuple_cmp(x,y) == 0 )
- { delete(inf(root));
- bb_tree::clear();
- return y;
- }
- }
-
- bb_item it,it1;
-
- x->set_cmp(x->dimension()-dim+1);
-
- it1 = sdel(x);
- if (!it1) return 0; // tuple not in tree
- deleted = key(it1);
-
-
- bb_item it2 = pred(it1);
- // delete nodelist of it1 or pred(it1)
- it = st.pop();
-
- if (tuple_cmp(x,key(bb_tree::max()))>=0)
- { DDUMP("old maximum deleted\n"); // old maximum deleted
- delete(inf(it1));
- inf(it)->del_tuple(x);
- it2->inf = it->inf;
- }
- else
- delete(inf(it));
-
- DDUMP((int)(key(it1)) << " geloescht\n" );
-
- delete it;
- delete it1;
- // rebalance tree
- // and delete tuple out of nodelists
- while (!st.empty())
- {
- it=st.pop();
- inf(it)->del_tuple(x);
-
- it1 = st.empty() ? 0 : st.top() ;
- it->gr--;
-
- float i=it->bal();
- DDUMP("rebal cur=" << (int)(key(it)) << " groesse= " << it->groesse() << " bal= " << i << " in dimension " << dim << "\n");
- if (i<alpha)
- if (it->sohn[right]->bal() <= d) lrot(it,it1);
- else ldrot(it,it1);
- else if (i>1-alpha)
- if(it->sohn[left]->bal() > d) rrot(it,it1);
- else rdrot(it,it1);
- }
-
- x->set_cmp(help_dim);
- return deleted;
- }
- }
-
- //-------------------------------------------------------------------
- // query
- // returns all tuples x in the range_tree with
- // lower.project(i) <= x.project(i) <= upper.project(i)
- // for x.cmp_dim() <= i <= dim
- // by:
- // - perform for all tuples x with
- // lower.project(1) <= x.project(1) <= upper.project(1)
- // a query in a (d-1) dimensional Range-tree
-
- void range_tree::query_tuples(tuplep lower, tuplep upper, dlist& L)
- {
- DPRINT("query in dimension " << dim << " on " << (int)(key(root)) << "\n");
-
- L.clear();
-
- if (size()==0) return;
-
- int help_diml = lower->cmp_dim();
- int help_dimu = upper->cmp_dim();
-
- lower->set_cmp(lower->dimension()-dim+1);
- upper->set_cmp(upper->dimension()-dim+1);
-
- bb_tree_item it;
- tuplep y,y1;
-
- L.clear();
-
- if (size()==0) return;
-
- if (dim==1) // one - dimensional tree
- { it=locate(lower);
- while( it && (tuple_cmp(upper,key(it)) >= 0) )
- { DDUMP((int)(key(it)) << "betrachtet\n");
- L.append(key(it));
- it = succ(it);
- }
- lower->set_cmp(help_diml);
- upper->set_cmp(help_dimu);
- return;
- }
-
- // >= 2 dimensional tree
- it=root;
- if (size()==1) // no recursive calls
- {
- if (check(key(it),lower,upper)) L.append(key(it));
- lower->set_cmp(help_diml);
- upper->set_cmp(help_dimu);
- return;
- }
-
- // look for nodetrees
- // necessary: access to nodes of bb_tree
- bb_tree_item it1=root;
- while ((it==it1)&&(!it->blatt()))
- { y=key(it);
- y1=key(it1);
- DDUMP(" same path " << (int)y1 << "\n");
- lower->set_cmp(lower->dimension()-dim+1);
- upper->set_cmp(upper->dimension()-dim+1);
- if ( tuple_cmp(lower,y)<=0 ) it=it->sohn[left];
- else it=it->sohn[right];
- if ( tuple_cmp(upper,y1)<=0 ) it1=it1->sohn[left];
- else it1=it1->sohn[right];
- }
- // now paths to lower and upper part
- // or it is a leaf
- y=key(it);
- if (it->blatt())
- {
- if (check(y,lower,upper)) L.append(y);
-
- if(it!=it1) // it leaf, it != it1 => search on upper path
- { list(range_tree_item) L1;
- while (!it1->blatt())
- { lower->set_cmp(lower->dimension()-dim+1);
- upper->set_cmp(upper->dimension()-dim+1);
- y1=key(it1);
- DDUMP(" upper path " << (int)y1 << "\n");
- if ( tuple_cmp(upper,y1)<=0 ) it1=it1->sohn[left];
- else
- { bb_item it2=it1->sohn[left];
- if (!it2->blatt())
- info(it2)->query_tuples(lower,upper,L1);
- else
- if (check(key(it2),lower,upper)) L1.append(key(it2));
- L.conc(L1);
- it1=it1->sohn[right];
- }
- }
- if (check(key(it1),lower,upper)) L.append(key(it1));
- }
- lower->set_cmp(help_diml);
- upper->set_cmp(help_dimu);
- return;
- }
-
- // it no leaf => paths parted
- list(range_tree_item) L1;
- while (!it->blatt())
- { y=key(it);
- DDUMP(" lower path " << (int)y << "\n");
- lower->set_cmp(lower->dimension()-dim+1);
- upper->set_cmp(upper->dimension()-dim+1);
- if ( tuple_cmp(lower,y)>0 ) it=it->sohn[right];
- else
- { bb_item it2=it->sohn[right];
- if (!it2->blatt())
- info(it2)->query_tuples(lower,upper,L1);
- else
- if (check(key(it2),lower,upper)) L1.append(key(it2));
- L.conc(L1);
- it=it->sohn[left];
- }
- }
- if (check(key(it),lower,upper)) L.append(key(it));
-
- while (!it1->blatt())
- { y1=key(it1);
- DDUMP(" upper path " << (int)y1 << "\n");
- lower->set_cmp(lower->dimension()-dim+1);
- upper->set_cmp(upper->dimension()-dim+1);
- if ( tuple_cmp(upper,y1)<=0 ) it1=it1->sohn[left];
- else
- { bb_item it2=it1->sohn[left];
- if (!it2->blatt())
- info(it2)->query_tuples(lower,upper,L1);
- else
- if (check(key(it2),lower,upper)) L1.append(key(it2));
- L.conc(L1);
- it1=it1->sohn[right];
- }
- }
- if (check(key(it1),lower,upper)) L.append(key(it1));
-
- lower->set_cmp(help_diml);
- upper->set_cmp(help_dimu);
- return;
- }
-
- //-------------------------------------------------------------------
- // all_tuples
- // returns all range_tree_items x in the range_tree
-
- list(range_tree_item) range_tree::all_tuples()
-
- {
- DPRINT("all_tuples of " << int(this) << " in dimension " << dim << "\n");
-
- bb_item it;
- list(range_tree_item) L;
-
- init_iterator();
- while (it=rm_tree::move_iterator())
- L.append(key(it));
-
- return L;
-
- }
-
-
- //--------------------------------------------------------------------
- // Minima & Maxima
-
- range_tree_item range_tree::min(int i)
- { if (i>dim || i<1)
- return 0;
- else
- { range_p r=this;
- while (--i) r=(range_p)r->root->inf;
- return key(((bb_tree*)r)->min());
- }
- }
-
- range_tree_item range_tree::max(int i)
- { if (i>dim || i<1)
- return 0;
- else
- { range_p r=this;
- while (--i) r=(range_p)r->root->inf;
- return key(((bb_tree*)r)->max());
- }
- }
-
- //--------------------------------------------------------------------
- // Clear & Destruktor
- //
-
-
- void range_tree::clear_tuple(tuplep& y)
- {
- DPRINT("clear von " << (int)y << "\n");
- clear_key((ent&)y);
- clear_inf((ent&)y);
- }
-
- void range_tree::del_tree(bb_item p)
- {
- if (!p->blatt())
- {
- delete inf(p);
- del_tree(p->sohn[left]);
- del_tree(p->sohn[right]);
- }
- else
- if (p==bb_tree::max())
- delete inf(p);
-
- delete(p);
-
- }
-
- void range_tree::clear()
- { range_tree_item it;
- list(range_tree_item) L=all_tuples();
- forall(it,L)
- {
- clear_tuple(it);
- delete it;
- }
-
- if (dim==1)
- bb_tree::clear();
- else
- if (root)
- del_tree(root);
-
- root=0;
- anzahl=0;
- first=0;
- }
-
-
- range_tree::~range_tree()
- {
-
- DPRINT("Destruktor in Dimension " << dim << "\n");
-
- if (root)
- { del_tree(root);
- root = 0;
- }
-
- }
-
-
- //--------------------------------------------------------------------
-