⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _dlist.c

📁 数据类型和算法库LEDA 数据类型和算法库LEDA
💻 C
字号:
/*******************************************************************************
+
+  LEDA  3.0
+
+
+  _dlist.c
+
+
+  Copyright (c) 1992  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 6600 Saarbruecken, FRG     
+  All rights reserved.
+ 
*******************************************************************************/



#include <LEDA/impl/dlist.h>
#include <ctype.h>


#define SWAP(a,b) { register dlink* x = *a; *a = *b; *b = x; }

#define MIN_D 16 

//------------------------------------------------------------------------------
// Members of class dlist: base class for all lists
//------------------------------------------------------------------------------


dlist::dlist()      
{ h=0; 
  t=0;
  count=0;
  iterator=0; 
}

dlist::dlist(GenPtr 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) { append(p->e); 
              x.copy_el(p->e); /* copy list using copy_el of x !! */
              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(GenPtr& x) const 
{ if (iterator) 
  { x = iterator->e; 
    return true; 
   } 
  return false; 
 }

bool dlist::next_element(GenPtr& 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(GenPtr& 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(GenPtr x) const  /* linear search */
{ dlink* p = h;
  while ( p && (p->e != x)) p = p->succ; 
  return p;
} 

int dlist::rank(GenPtr 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;
} 

GenPtr dlist::pop()    
{ if (iterator!=0) error_handler(1,"pop: deletion while iterator is active");
  dlink* x=h; 
  GenPtr p;
  if (count==0) return 0;
  if (--count) { h = h->succ; h->pred = 0; }
  else  h = t = 0;
  p = x->e;
  delete x;
  return p;
}

GenPtr dlist::Pop()    
{ if (iterator!=0) error_handler(1,"Pop: deletion while iterator is active");
  dlink* x=t; 
  GenPtr p;
  if (count==0) return 0;
  if (--count) { t = t->pred; t->succ = 0; }
  else  h = t = 0;
  p = x->e;
  delete x;
  return p;
}

dlink* dlist::insert(GenPtr 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;
}


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;

}


GenPtr 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)  return pop();

  if (loc==t)  return Pop();

  dlink*  p = loc->pred;
  dlink*  s = loc->succ;
  GenPtr x = loc->e;
  p->succ = s;
  s->pred = p;
  count--;

  delete loc;
  return x;
}

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_PTR f) const
{ if (h==0) return 0;
  dlink* m=h;
  dlink* p=m->succ;

  if (f) 
     while (p)
     { if (f(p->e,m->e) > 0) m=p;
       p=p->succ;
      }
  else
     while (p)
     { if (cmp(p->e,m->e) > 0) m=p;
       p=p->succ;
      }

  return m;
}

dlink* dlist::min(CMP_PTR f) const
{ if (h==0) return 0;
  dlink* m=h;
  dlink* p=m->succ;

  if (f)
     while (p)
     { if (f(p->e,m->e) < 0) m=p;
       p=p->succ;
     }
  else 
     while (p)
     { if (cmp(p->e,m->e) < 0) m=p;
       p=p->succ;
      }

  return m;
}


void dlist::apply(APP_PTR apply)
{ register dlink* p = h;
  while (p)
  { apply(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);
    x = A[j];
    A[j] = A[r];
    A[r] = x;
   }

  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, ORD_PTR ord)
{ if (iterator!=0) 
        error_handler(3,"bucket_sort: modification while iterator is active");

  int n = j-i+1;

  register list_item* bucket= new list_item[n+1];
  register list_item* stop = bucket + n;
  register list_item* p;

  register list_item q;
  register list_item x;

  for(p=bucket;p<=stop;p++)  *p = 0;

  while (h) 
  { x = h; 
    h = h->succ;
    int k = ord(x->e);
    if (k >= i && k <= j) 
     { p = bucket+k-i;
       x->succ = *p;
       if (*p) (*p)->pred = x;
       *p = x;
      }
    else 
       error_handler(4,"bucket_sort: value out of range") ;
   }

 for(p=bucket; *p==0 && p<stop; p++);
  
 h = *p;

 if (h) 
 { for(q=h;q->succ; q = q->succ);
   h->pred = 0;
   p++;
  }

 while(p<stop) 
 { if (*p)
   { q->succ = *p;
     (*p)->pred = q;
     while(q->succ) q = q->succ;
    }
   p++;
  }

 t = q;

 delete bucket;
}

void dlist::quick_sort(dlink** l, dlink** r)
{ // use virtual cmp function

  register dlink** i = l+(r-l)/2; //random()%(r-l);
  register dlink** k;
 
  if (cmp((*i)->e,(*r)->e)>0) SWAP(i,r);

  SWAP(l,i);
 
  GenPtr s = (*l)->e;
 
  i = l;
  k = r;

  for(;;)
  { while (cmp((*(++i))->e,s)<0);
    while (cmp((*(--k))->e,s)>0);
    if (i<k) SWAP(i,k) else break;
   }

  SWAP(l,k);

  if (k > l+MIN_D) quick_sort(l,k-1);
  if (r > k+MIN_D) quick_sort(k+1,r);
}
        
void dlist::quick_sort(dlink** l, dlink** r, CMP_PTR usr_cmp)
{ // use parameter usr_cmp

  register dlink** i = l+(r-l)/2; //random()%(r-l);
  register dlink** k;
 
  if (usr_cmp((*i)->e,(*r)->e)>0) SWAP(i,r);

  SWAP(l,i);
 
  GenPtr s = (*l)->e;
 
  i = l;
  k = r;

  for(;;)
  { while (usr_cmp((*(++i))->e,s)<0);
    while (usr_cmp((*(--k))->e,s)>0);
    if (i<k) SWAP(i,k) else break;
   }

  SWAP(l,k);

  if (k > l+MIN_D) quick_sort(l,k-1,usr_cmp);
  if (r > k+MIN_D) quick_sort(k+1,r,usr_cmp);
}
        

void dlist::int_quick_sort(dlink** l, dlink** r)
{ // use built-in < and > operators for integers

  register dlink** i = l+(r-l)/2; //random()%(r-l);
  register dlink** k;
 
  if ((*i)->e > (*r)->e) SWAP(i,r);

  SWAP(l,i);
 
  GenPtr s = (*l)->e;
 
  i = l;
  k = r;

  for(;;)
  { while ((*(++i))->e < s);
    while ((*(--k))->e > s);
    if (i<k) SWAP(i,k) else break;
   }

  SWAP(l,k);

  if (k > l+MIN_D) int_quick_sort(l,k-1);
  if (r > k+MIN_D) int_quick_sort(k+1,r);
}


void dlist::insertion_sort(dlink** l, dlink** r, dlink** min_stop, 
                               CMP_PTR usr_cmp)
{
  register dlink** min=l;
  register dlink** run;
  register dlink** p;
  register dlink** q;

  for (run = l+1; run <= min_stop; run++)
      if (usr_cmp((*run)->e,(*min)->e) < 0) min = run;

  SWAP(min,l);

  if (r == l+1) return; 

  for(run=l+2; run <= r; run++)
  { for (min = run-1; usr_cmp((*run)->e,(*min)->e) < 0; min--);
    min++;
    if (run != min) 
    { dlink* save = *run;
      for(p=run, q = run-1; p > min; p--,q--) *p = *q;
      *min = save;
     }
   }
}


void dlist::insertion_sort(dlink** l, dlink** r, dlink** min_stop)
{
  register dlink** min=l;
  register dlink** run;
  register dlink** p;
  register dlink** q;

  for (run = l+1; run <= min_stop; run++)
      if (cmp((*run)->e,(*min)->e) < 0) min = run;

  SWAP(min,l);

  if (r == l+1) return; 

  for(run=l+2; run <= r; run++)
  { for (min = run-1; cmp((*run)->e,(*min)->e) < 0; min--);
    min++;
    if (run != min) 
    { dlink* save = *run;
      for(p=run, q = run-1; p > min; p--,q--) *p = *q;
      *min = save;
     }
   }
}


void dlist::int_insertion_sort(dlink** l, dlink** r, dlink** min_stop)
{
  register dlink** min=l;
  register dlink** run;
  register dlink** p;
  register dlink** q;

  for (run = l+1; run <= min_stop; run++)
      if ((*run)->e < (*min)->e) min = run;

  SWAP(min,l);

  if (r == l+1) return; 

  for(run=l+2; run <= r; run++)
  { for (min = run-1; (*run)->e < (*min)->e; min--);
    min++;
    if (run != min) 
    { dlink* save = *run;
      for(p=run, q = run-1; p > min; p--,q--) *p = *q;
      *min = save;
     }
   }
}




void dlist::sort(CMP_PTR f)
{ if (iterator!=0)
      error_handler(1,"sort: modification while iterator is active");

  if (count<=1) return;    // nothing to sort

  dlink** A = new dlink*[count+2];

  register dlink*  loc = h;
  register dlink** p;
  register dlink** stop = A+count+1;

  dlink** left  = A+1;
  dlink** right = A+count;
  dlink** min_stop = left + MIN_D;

  if (min_stop > right) min_stop = right;

min_stop = right;

  for(p=A+1; p<stop; p++)
  { *p = loc;
    loc = loc->succ;
   }


  if (f)
    { quick_sort(left,right,f);
      insertion_sort(left,right,min_stop,f);
     }
  else  
    if (int_type())
      { int_quick_sort(left,right);
        int_insertion_sort(left,right,min_stop);
       }
    else
      { quick_sort(left,right);
        insertion_sort(left,right,min_stop);
       }

  *A = *stop = 0;

  for (p=A+1;p<stop;p++) 
  { (*p)->succ = *(p+1);
    (*p)->pred = *(p-1);
   }

  h = A[1];
  t = A[count];

  delete A;
}


dlist& dlist::operator=(const dlist& x)
{ iterator=0;
  clear();

  dlink* p = x.h;         
                                
  while (p) { append(p->e);
              copy_el(p->e);
              p = p->succ;
             }
  return *this;
}


dlist dlist::operator+(const dlist& x)  // concatenation
{
 dlist y = x;
  dlink* p = t;
  while (p) { y.push(p->e);    
              x.copy_el(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;
   }

  deallocate_list(h,t,sizeof(dlink));
  iterator=h=t=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 << string("%c",space);
        print_el(l->e,out); 
        l = l->succ;
       }
  }
  out.flush();
}


void dlist::read(istream& in, string s, char delim)
{ char c;
  GenPtr x;
  cout << s;
  clear();
  for(;;)
  { while (in.get(c) && isspace(c) && c!=delim);
    if (!in || c==delim) break;
    in.putback(c);
    read_el(x,in); 
    append(x);
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -