/*
     File:         heap.h
     Author:       Andrew W. Moore
     Created:      14th February 1992
     Description:  The heap for A-Star search.
*/

#ifndef HEAP_H
#define HEAP_H

#include "amut.h"
#include "amma.h"

typedef struct heap_struct
{
/* Must be initialized before calling get_heap_ready().. */
  int max_size;
  bool (*is_better_than)(void *, void *);   /* (heapitem1,heapitem2) */
  int (*heap_index_of)(void *);     /* (heapitem) */
  void (*set_heap_index)(void *, int);   /* (heapitem,index) */

/* Initialized by get_heap_ready() .. */
  void **data;
  int size;
} heap;

/****** PQUEUES (Even easier to use than heaps *********/

typedef struct pqelt_struct
{
  int heap_index;
  int input;
  double priority;
} pqelt;

typedef pqelt *pqelt_ptr;

typedef struct pqueue_struct
{
  heap heap;
  pqelt_ptr *pqelts;
} pqueue;

void *find_and_remove_best ( heap *hp );

void note_changed_value ( heap *hp, void *x );

void add_to_heap ( heap *hp, void *new_x );

void get_heap_ready ( heap *hp );

int heap_size ( heap *hp );

void pq_empty ( pqueue *pq );

pqueue *pq_create ( int max_input );

void free_pqueue(pqueue *pq);

bool pq_is_empty ( pqueue *pq );

int pq_size ( pqueue *pq );

int pq_pop_best ( pqueue *pq );

void pq_insert ( pqueue *pq, int i, double pri );

bool pq_contains ( pqueue *pq, int input );

double pq_priority ( pqueue *pq, int input );

double priority_of_best ( pqueue *pq );

/* sheap is a modern (but not randomly accessible) heap. */

typedef struct sheap
{
  heap *hp;
} sheap;

/* Makes a sheap (Simple HEAP) structure with initially nothing
   in the queue */
sheap *mk_sheap(void);

/* Makes a sheap with initially nothing in the queue, but you give it
   a max_size argument which tells the sheap the max number of things you
   will be putting into it */
sheap *mk_sheap_given_max_size(int max_size);

/* Adds the given pointer to the heap with the given priority.
   Notice that it directly stores the pointer...it does not
   make a copy of the thing in "data". This means that the caller
   must not deallocate (or otherwise hurt) whatever it is that "data"
   points to until after we're done with using the sheap, or until
   "data" has been removed from the sheap. */
void add_to_sheap(sheap *sh,void *data,double priority);

/* The number of items on the sheap */
int sheap_size(sheap *sh);

/* The following three operations all refer to the "next_to_pop"
   item, which is the item with the smallest value of "priority". Ties are
   broken by some arbitrary rule that may depend on order of insertion. */

/* The priority of the item "next_to_pop" item on the heap (i.e. the
   item that has minimum priority). Note that this "next_to_pop" item is
   NOT popped by this operation. */
double sheap_minimum_priority(sheap *sh);

/* The data pointer of the "next_to_pop" item on the heap (i.e. the
   item that has minimum priority). Note that this "next_to_pop" item is
   NOT popped by this operation. */
void *sheap_data_with_minimum_priority(sheap *sh);

/* This deletes the lowest priority item. No memory is freed. */
void sheap_remove_minimum_priority(sheap *sh);

/* Frees the sheap and all memory that it used, except does not
   do anything with the defunct data items that had been stored within it.
   Thus if a data item had been stored in the heap, it is the callers
   responsibility to eventually clean up the memory for that data item. */
void free_sheap(sheap *sh);

int sheap_max_size(sheap *sh);

/***************** Begin intheap *******************/

/* An intheap is the structure of choice if you wish to work with
   a set of integers (which we'll call a set of codes) in which
   each code has a priority. 

   So the structure represents a set of zero or more pairs

      (code0,priority0)
      (code1,priority1)
         :
      (code[N-1],priority[n-1])

   You can add any (code,priority) pair to this set in time log(n)

   You can find out which code has the lowest priority value in time O(1)

   You can find what that lowest priority is in time O(1)

   You can remove the (code,priority) pair with the lowest priority
   value in time O(log n)
*/

typedef struct intheap
{
  heap *hp;
} intheap;

/* Makes a intheap (Integer HEAP) structure with initially nothing
   in the queue.  

   The intheap will dynamically cope with however many items you add to
   it. It is thus slightly more flexible but slightly (very slightly)
   slower to use than mk_intheap_given_max_size() below.
*/
intheap *mk_intheap(void);

/* Use this function if you know what the eventual maximum number of
   elements in the heap will be (i.e. the value of n in the example above).

   The intheap initially contains no elements (i.e. n = 0)
 */
intheap *mk_intheap_given_max_size(int max_size);

intheap *mk_copy_intheap( intheap *ih);

/* Adds the given (code,priority) pair to the heap. */
void add_to_intheap(intheap *ih,int code,double priority);

/* The number of items on the intheap */
int intheap_size(intheap *ih);

/* The following three operations all refer to the "next_to_pop"
   item, which is the item with the smallest value of "priority". Ties are
   broken by some arbitrary rule that may depend on order of insertion. */

/* The priority of the item "next_to_pop" item on the heap (i.e. the
   item that has minimum priority). Note that this "next_to_pop" item is
   NOT popped by this operation. */
double intheap_minimum_priority(intheap *ih);

/* The code of the "next_to_pop" item on the heap (i.e. the
   code that has minimum priority). Note that this "next_to_pop" item is
   NOT popped by this operation. */
int intheap_code_with_minimum_priority(intheap *ih);

/* This deletes the lowest priority item */
void intheap_remove_minimum_priority(intheap *ih);

/* Frees the intheap and all memory that it used */
void free_intheap(intheap *ih);

#endif /* #ifndef HEAP_H */
