Branch: Tag:

2015-09-10

2015-09-10 13:45:09 by Henrik Grubbström (Grubba) <grubba@grubba.org>

ADT.Heap: Added ADT.Heap.Element.

This adds one level of indirection, but is needed to get a
reasonable performance in code that needs to call adjust().

Also corresponding updates to ADT.Priority_queue.

Also removes the LFUN::`==() operator from ADT.Priority_queue.elem,
as it doesn't serve any purpose.

4:   //! always be greater than or equal to the value of its parent node.   //! Thus, the top node of the heap will always hold the smallest value.    - #define SWAP(X,Y) do{ mixed tmp=values[X]; values[X]=values[Y]; values[Y]=tmp; }while(0) + //! Heap element. + class Element (mixed value) + { +  int pos;    - protected array values=allocate(10); +  constant is_adt_heap_element = 1; +  +  protected int `<(mixed other) { return value < other; } +  protected int `>(mixed other) { return value > other; } + } +  + #define SWAP(X,Y) do{ mixed tmp=values[X]; (values[X]=values[Y])->pos = X; (values[Y]=tmp)->pos = Y; }while(0) +  + protected array(Element) values=allocate(10);   protected int num_values;      #ifdef ADT_HEAP_DEBUG   void verify_heap()   { -  for(int e=1; e<num_values; e++) +  for(int e=0; e<num_values; e++) { +  if (!values[e] || !values[e]->is_adt_heap_element) +  error("Error in HEAP: Position %d has no element.\n", e); +  if (values[e]->pos != e) +  error("Error in HEAP: Element %d has invalid position: %d.\n", +  e, values[e]->pos);    if(values[(e-1)/2] > values[e])    error("Error in HEAP (%d, %d) num_values=%d\n",    (e-1)/2, e, num_values);    } -  + }   #else   #define verify_heap()   #endif
72:   //! Push an element onto the heap. The heap will automatically sort itself   //! so that the smallest value will be at the top.   //! + //! @returns + //! Returns an element handle, which can be used with + //! @[adjust()] and @[remove()]. + //!   //! @seealso   //! @[pop()], @[remove()] - void push(mixed value) + Element push(mixed value)   { -  +  Element ret; +  if (objectp(value) && value->is_adt_heap_element) { +  ret = value; +  } else { +  ret = Element(value); +  }    if(num_values >= sizeof(values))    values+=allocate(10+sizeof(values)/4);    -  values[num_values++]=value; +  (values[num_values] = ret)->pos = num_values++;    adjust_up(num_values-1);    verify_heap(); -  +  return ret;   }      //! Takes a value in the heap and sorts it through the heap to maintain   //! its sort criteria (increasing order). - void adjust(mixed value) + //! + //! @param value + //! Either the element handle returned by @[push()], or the pushed + //! value itself. + //! + //! @returns + //! Returns the element handle for the value (if present in the heap), + //! and @expr{0@} (zero) otherwise. + Element adjust(mixed value)   { -  int pos=search(values, value); -  if(pos>=0) +  int pos; +  if (objectp(value) && value->is_adt_heap_element) { +  pos = value->pos; +  } else { +  pos = search(values->value, value); +  } +  Element ret; +  if(pos>=0) { +  ret = values[pos];    if(!adjust_up(pos))    adjust_down(pos); -  +  }    verify_heap(); -  +  return ret;   }      //! Removes and returns the item on top of the heap,
109:    if(!num_values)    error("Heap underflow!\n");    -  ret=values[0]; -  if(sizeof(values) > 1) -  { +  ret = values[0]->value;    num_values--; -  values[0]=values[num_values]; -  values[num_values]=0; +  if(num_values) +  { +  (values[0] = values[num_values])->pos = 0;    adjust_down(0);       if(num_values * 3 + 10 < sizeof(values))    values=values[..num_values+10];    } -  +  values[num_values]=0;    verify_heap();    return ret;   }
150:    if (!num_values)    return UNDEFINED;    -  return values[0]; +  return values[0]->value;   }      //! Remove a value from the heap.
162:   //! @[push()], @[pop()]   void remove(mixed value)   { -  int pos = search(values, value); +  int pos; +  if (objectp(value) && value->is_adt_heap_element) { +  pos = value->pos; +  } else { +  pos = search(values->value, value); +  }    if ((pos < 0) || (pos >= num_values)) return;       values[pos] = values[--num_values];