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

📄 priority_q.h

📁 大名鼎鼎的传感器网络仿真实验室平台SENSE
💻 H
字号:
/*  *   Copyright 2003 Gilbert (Gang) Chen, Boleslaw K. Szymanski and *   Rensselaer Polytechnic Institute. All worldwide rights reserved. *   A license to use, copy, modify and distribute this software for *   non-commercial research purposes only is hereby granted, provided *   that this copyright notice and accompanying disclaimer is not *   modified or removed from the software. * *   DISCLAIMER: The software is distributed "AS IS" without any *   express or implied warranty, including but not limited to, any *   implied warranties of merchantability or fitness for a particular *   purpose or any warranty of non-infringement of any current or *   pending patent rights. The authors of the software make no *   representations about the suitability of this software for any *   particular purpose. The entire risk as to the quality and *   performance of the software is with the user. Should the software *   prove defective, the user assumes the cost of all necessary *   servicing, repair or correction. In particular, neither Rensselaer *   Polytechnic Institute, nor the authors of the software are liable *   for any indirect, special, consequential, or incidental damages *   related to the software, to the maximum extent the law permits. */#ifndef PRIORITY_QUEUE_H#define PRIORITY_QUEUE_H/*  Five Priority Queues:  SimpleQueue: Double Linked list  GuardedQueue: Derived from SimpleQueue, checks before EnQueue() and Delete()  ErrorQueue: Derived from SimpleQueue, only correct half of the time (for debugging)  HeadQueue: Implicit Heap  CalendarQueue: The fastest  Last Modified: Nov 18, 2002 by Gilbert Chen */template < class ITEM >class SimpleQueue { public:  SimpleQueue() :m_head(NULL) {};  void EnQueue(ITEM*);  ITEM* DeQueue();  void Delete(ITEM*);  ITEM* NextEvent() const { return m_head; };  const char* GetName(); protected:  ITEM* m_head;};template <class ITEM>const char* SimpleQueue<ITEM>::GetName(){  static const char* name = "SimpleQueue";  return name;}template <class ITEM>void SimpleQueue<ITEM>::EnQueue(ITEM* item){  if( m_head==NULL || item->time < m_head->time )  {    if(m_head!=NULL)m_head->prev=item;    item->next=m_head;    m_head=item;    item->prev=NULL;    return;  }      ITEM* i=m_head;  while( i->next!=NULL && item->time > i->next->time)    i=i->next;  item->next=i->next;  if(i->next!=NULL)i->next->prev=item;  i->next=item;  item->prev=i;}template <class ITEM>ITEM* SimpleQueue<ITEM> ::DeQueue(){  if(m_head==NULL)return NULL;  ITEM* item = m_head;  m_head=m_head->next;  if(m_head!=NULL)m_head->prev=NULL;  return item;}template <class ITEM>void SimpleQueue<ITEM>::Delete(ITEM* item){  if(item==NULL) return;  if(item==m_head)  {    m_head=m_head->next;    if(m_head!=NULL)m_head->prev=NULL;  }  else  {    item->prev->next=item->next;    if(item->next!=NULL)      item->next->prev=item->prev;  }}template <class ITEM>class GuardedQueue : public SimpleQueue<ITEM>{ public:  void Delete(ITEM*);  void EnQueue(ITEM*);  bool Validate(const char*);};template <class ITEM>void GuardedQueue<ITEM>::EnQueue(ITEM* item){// mwl	gcc 4.0 requires the "SimpleQueue<ITEM>::"  ITEM* i=SimpleQueue<ITEM>::m_head;  while(i!=NULL)  {    if(i==item)    {      pthread_printf("queue error: item %f(%p) is already in the queue\n",item->time,item);    }    i=i->next;  }  SimpleQueue<ITEM>::EnQueue(item);}template <class ITEM>void GuardedQueue<ITEM>::Delete(ITEM* item){  ITEM* i=SimpleQueue<ITEM>::m_head;  while(i!=item&&i!=NULL)    i=i->next;  if(i==NULL)    pthread_printf("error: cannot find the to-be-deleted event %f(%p)\n",item->time,item);  else    SimpleQueue<ITEM>::Delete(item);}template <class ITEM>bool GuardedQueue<ITEM>::Validate(const char* s){  char out[1000],buff[100];  ITEM* i=SimpleQueue<ITEM>::m_head;  bool qerror=false;  sprintf(out,"queue error %s : ",s);  while(i!=NULL)  {    sprintf(buff,"%f ",i->time);    strcat(out,buff);    if(i->next!=NULL)      if(i->next->prev!=i)      {	qerror=true;	sprintf(buff," {broken} ");	strcat(out,buff);      }    if(i==i->next)    {      qerror=true;      sprintf(buff,"{loop}");      strcat(out,buff);      break;    }    i=i->next;  }  if(qerror)    printf("%s\n",out);  return qerror;}template <class ITEM>class ErrorQueue : public SimpleQueue<ITEM>{ public:  ITEM* DeQueue(double);  const char* GetName();};template <class ITEM>const char* ErrorQueue<ITEM>::GetName(){  static const char* name = "ErrorQueue";  return name;}template <class ITEM>ITEM* ErrorQueue<ITEM> ::DeQueue(double stoptime){  //Validate("Before DeQueue()");  if(drand48()>0.5)    return SimpleQueue<ITEM>::DeQueue();  int s=0;  ITEM* e;  e=SimpleQueue<ITEM>::m_head;  while(e!=NULL&&e->time<stoptime)  {    s++;    e=e->next;  }  e=SimpleQueue<ITEM>::m_head;  s=(int)(s*drand48());  while(s!=0)  {    e=e->next;    s--;  }  Delete(e);  return e;}template < class ITEM >class HeapQueue { public:  HeapQueue();  ~HeapQueue();  void EnQueue(ITEM*);  ITEM* DeQueue();  void Delete(ITEM*);  const char* GetName();  ITEM* NextEvent() const { return num_of_elems?elems[0]:NULL; }; private:  void SiftDown(int);  void PercolateUp(int);  void Validate(const char*);          ITEM** elems;  int num_of_elems;  int curr_max;};template <class ITEM>const char* HeapQueue<ITEM>::GetName(){  static const char* name = "HeapQueue";  return name;}template <class ITEM>void HeapQueue<ITEM>::Validate(const char* s){  int i,j;  char out[1000],buff[100];  for(i=0;i<num_of_elems;i++)    if(  ((2*i+1)<num_of_elems&&elems[i]->time>elems[2*i+1]->time) ||	 ((2*i+2)<num_of_elems&&elems[i]->time>elems[2*i+2]->time) )    {      sprintf(out,"queue error %s : ",s);      for(j=0;j<num_of_elems;j++)      {	if(i!=j)	  sprintf(buff,"%f(%d) ",elems[j]->time,j);	else	  sprintf(buff,"{%f(%d)} ",elems[j]->time,j);	strcat(out,buff);      }      printf("%s\n",out);    }}template <class ITEM>HeapQueue<ITEM>::HeapQueue(){  curr_max=16;  elems=new ITEM*[curr_max];  num_of_elems=0;}template <class ITEM>HeapQueue<ITEM>::~HeapQueue(){  delete [] elems;}template <class ITEM>void HeapQueue<ITEM>::SiftDown(int node){  if(num_of_elems<=1) return;  int i=node,k,c1,c2;  ITEM* temp;          do{    k=i;    c1=c2=2*i+1;    c2++;    if(c1<num_of_elems && elems[c1]->time < elems[i]->time)      i=c1;    if(c2<num_of_elems && elems[c2]->time < elems[i]->time)      i=c2;    if(k!=i)    {      temp=elems[i];      elems[i]=elems[k];      elems[k]=temp;      elems[k]->pos=k;      elems[i]->pos=i;    }  }while(k!=i);}template <class ITEM>void HeapQueue<ITEM>::PercolateUp(int node){  int i=node,k,p;  ITEM* temp;          do{    k=i;    if( (p=(i+1)/2) != 0)    {      --p;      if(elems[i]->time < elems[p]->time)      {	i=p;	temp=elems[i];	elems[i]=elems[k];	elems[k]=temp;	elems[k]->pos=k;	elems[i]->pos=i;      }    }  }while(k!=i);}template <class ITEM>void HeapQueue<ITEM>::EnQueue(ITEM* item){  if(num_of_elems>=curr_max)  {    curr_max*=2;    ITEM** buffer=new ITEM*[curr_max];    for(int i=0;i<num_of_elems;i++)      buffer[i]=elems[i];    delete[] elems;    elems=buffer;  }          elems[num_of_elems]=item;  elems[num_of_elems]->pos=num_of_elems;  num_of_elems++;  PercolateUp(num_of_elems-1);}template <class ITEM>ITEM* HeapQueue<ITEM>::DeQueue(){  if(num_of_elems<=0)return NULL;          ITEM* item=elems[0];  num_of_elems--;  elems[0]=elems[num_of_elems];  elems[0]->pos=0;  SiftDown(0);  return item;}template <class ITEM>void HeapQueue<ITEM>::Delete(ITEM* item){  int i=item->pos;  num_of_elems--;  elems[i]=elems[num_of_elems];  elems[i]->pos=i;  SiftDown(i);  PercolateUp(i);}#define CQ_MAX_SAMPLES 25template <class ITEM>class CalendarQueue { public:  CalendarQueue();  const char* GetName();  ~CalendarQueue();  void enqueue(ITEM*);  ITEM* dequeue();  void EnQueue(ITEM*);  ITEM* DeQueue();  ITEM* NextEvent() const { return m_head;}  void Delete(ITEM*); private:  long last_bucket,number_of_buckets;  double bucket_width;          void ReSize(long);  double NewWidth();  ITEM ** buckets;  long total_number;  double bucket_top;  long bottom_threshold;  long top_threshold;  double last_priority;  bool resizable;  ITEM* m_head;  char m_name[100];};template <class ITEM>const char* CalendarQueue<ITEM> :: GetName(){  sprintf(m_name,"Calendar Queue (bucket width: %.2e, size: %ld) ",	  bucket_width,number_of_buckets);  return m_name;}template <class ITEM>CalendarQueue<ITEM>::CalendarQueue(){  long i;          number_of_buckets=16;  bucket_width=1.0;  bucket_top=bucket_width;  total_number=0;  last_bucket=0;  last_priority=0.0;  top_threshold=number_of_buckets*2;  bottom_threshold=number_of_buckets/2-2;  resizable=true;          buckets= new ITEM*[number_of_buckets];  for(i=0;i<number_of_buckets;i++)    buckets[i]=NULL;  m_head=NULL;}template <class ITEM>CalendarQueue<ITEM>::~CalendarQueue(){  delete [] buckets;}template <class ITEM>void CalendarQueue<ITEM>::ReSize(long newsize){  long i;  ITEM** old_buckets=buckets;  long old_number=number_of_buckets;          resizable=false;  bucket_width=NewWidth();  buckets= new ITEM*[newsize];  number_of_buckets=newsize;  for(i=0;i<newsize;i++)    buckets[i]=NULL;  last_bucket=0;  total_number=0;  //printf("Resize to width=%e and size=%ld\n",bucket_width,newsize);          ITEM *item;  for(i=0;i<old_number;i++)  {    while(old_buckets[i]!=NULL)    {      item=old_buckets[i];      old_buckets[i]=item->next;      enqueue(item);    }  }  resizable=true;  delete[] old_buckets;  number_of_buckets=newsize;  top_threshold=number_of_buckets*2;  bottom_threshold=number_of_buckets/2-2;  bucket_top=bucket_width*((long)(last_priority/bucket_width)+1)+bucket_width*0.5;  last_bucket = long(last_priority/bucket_width) % number_of_buckets;}template <class ITEM>ITEM* CalendarQueue<ITEM>::DeQueue(){  ITEM* head=m_head;  m_head=dequeue();  return head;}template <class ITEM>ITEM* CalendarQueue<ITEM>::dequeue(){  long i;  for(i=last_bucket;;)  {    if(buckets[i]!=NULL&&buckets[i]->time<bucket_top)    {      ITEM * item=buckets[i];      buckets[i]=buckets[i]->next;      total_number--;      last_bucket=i;      last_priority=item->time;                              if(resizable&&total_number<bottom_threshold)	ReSize(number_of_buckets/2);      item->next=NULL;      return item;    }    else    {      i++;      if(i==number_of_buckets)i=0;      bucket_top+=bucket_width;      if(i==last_bucket)	break;    }  }          /* Start Direct Search */  long smallest;  for(smallest=0;smallest<number_of_buckets;smallest++)    if(buckets[smallest]!=NULL)break;  if(smallest >= number_of_buckets)  {    last_priority=bucket_top;    return NULL;  }  for(i=smallest+1;i<number_of_buckets;i++)  {    if(buckets[i]==NULL)      continue;    else      if(buckets[i]->time<buckets[smallest]->time)	smallest=i;  }  ITEM * item=buckets[smallest];  buckets[smallest]=buckets[smallest]->next;  total_number--;  last_bucket=smallest;  last_priority=item->time;  bucket_top=bucket_width*((long)(last_priority/bucket_width)+1)+bucket_width*0.5;  item->next=NULL;  return item;}template <class ITEM>void CalendarQueue<ITEM>::EnQueue(ITEM* item){  //printf("Enqueue %f\n",item->time);  if(m_head==NULL)  {    m_head=item;    return;  }  if(m_head->time>item->time)  {    enqueue(m_head);    m_head=item;  }  else    enqueue(item);}template <class ITEM>void CalendarQueue<ITEM>::enqueue(ITEM* item){  long i;  if(item->time<last_priority)  {    i=(long)(item->time/bucket_width);    last_priority=item->time;    bucket_top=bucket_width*(i+1)+bucket_width*0.5;    i=i%number_of_buckets;    last_bucket=i;  }  else  {    i=(long)(item->time/bucket_width);    i=i%number_of_buckets;  }          /*Insert into buckets[i] */  if(buckets[i]==NULL||item->time<buckets[i]->time)  {    item->next=buckets[i];    buckets[i]=item;  }  else  {    ITEM* pos=buckets[i];    while(pos->next!=NULL&&item->time>pos->next->time)    {      pos=pos->next;    }    item->next=pos->next;    pos->next=item;  }  total_number++;  if(resizable&&total_number>top_threshold)    ReSize(number_of_buckets*2);}template <class ITEM>void CalendarQueue<ITEM>::Delete(ITEM* item){  if(item==m_head)  {    m_head=dequeue();    return;  }  long j;  j=(long)(item->time/bucket_width);  j=j%number_of_buckets;          /*remove from buckets[j] */  // the address of the pointer that points  // to the current item  ITEM** p = &buckets[j];  // the current item  ITEM* i=buckets[j];      while(i!=NULL)  {    if(i==item)    { /* got it */      (*p)=item->next;      total_number--;      if(resizable&&total_number<bottom_threshold)	ReSize(number_of_buckets/2);      return;    }    p=&(i->next);    i=i->next;  }   }template <class ITEM>double CalendarQueue<ITEM>::NewWidth(){  long i, nsamples;          if(total_number<2) return 1.0;  if(total_number<=5)    nsamples=total_number;  else    nsamples=5+total_number/10;  if(nsamples>CQ_MAX_SAMPLES) nsamples=CQ_MAX_SAMPLES;          long _last_bucket=last_bucket;  double _bucket_top=bucket_top;  double _last_priority=last_priority;          double AVG[CQ_MAX_SAMPLES],avg1=0,avg2=0;  ITEM* list,*next,*item;          list=dequeue();   long real_samples=0;  while(real_samples<nsamples)  {    item=dequeue();    if(item==NULL)    {      item=list;      while(item!=NULL)      {	next=item->next;	enqueue(item);	item=next;            }      last_bucket=_last_bucket;      bucket_top=_bucket_top;      last_priority=_last_priority;                              return 1.0;    }    AVG[real_samples]=item->time-list->time;    avg1+=AVG[real_samples];    if(AVG[real_samples]!=0.0)      real_samples++;    item->next=list;    list=item;  }  item=list;  while(item!=NULL)  {    next=item->next;    enqueue(item);    item=next;        }          last_bucket=_last_bucket;  bucket_top=_bucket_top;  last_priority=_last_priority;          avg1=avg1/(double)(real_samples-1);  avg1=avg1*2.0;          //printf("avg1: %le\n",avg1);  long count=0;  for(i=0;i<real_samples-1;i++)  {    if(AVG[i]<avg1&&AVG[i]!=0)    {      avg2+=AVG[i];      count++;    }  }  if(count==0||avg2==0)   return 1.0;          avg2 /= (double) count;  avg2 *= 3.0;          return avg2;}#endif /*PRIORITY_QUEUE_H*/

⌨️ 快捷键说明

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