dim as integer newCost, herehere = 0do cls newCost = 0 print "Frontier Pointer = ";frontpointer print "Last one was at:";here if frontpointer > 0 then for i as integer = 1 to frontpointer print "#";i;" = (";frontier(i,0);")" next i end if print print "Enter Number to ADD, or negative to DEL that pointer" input "Number:",newCost select case newCost case is > 0 here = FrontierAdd(0,0,newCost) case is < 0 ' if negative then newcost is the pointer, not the cost here = FrontierDel(abs(newCost)) end select

loop until newCost = 0end

I realize using the 'SWAP' function is a slow way of exchanging variable values... and opening a space for inserting a new member of the list could be done with memcpy or some such fast bulk memory mover....

ADD elementAccess the lowest(highest) elementDEL an elementFIND an element

You're confusing a sorted heap with a priority queue. You can't 'find' an item in a priority queue, since the only value that makes sense is the top of the heap. The rest will be unordered and finding something just amounts to a linear search (thus defeating the purpose of the queue). The only operations allowed in a 'pure' priority queue are pushing and popping of values. And you can also of course peek the TOH without popping it (using the top() method here):

There's no need to instantiate or extend this class, as it is used by the internal heap only. '/ type QueueElement public: declare constructor( _ byval as integer, _ byval as any ptr, _ byval as DisposeCallback = Null )

destructor QueueElement() /' Invoke the callback if it exists for disposal of the 'value' field if required. '/ if( _ m_disposeCallback <> Null ) then m_disposeCallback( m_value ) end if end destructor

property QueueElement.value() as any ptr return( m_value ) end property

/' This is the base class for the Priority Queue class.

The class represents a Queue data structure, implemented here as a Binary Heap. Look at these links for more info: https://en.wikipedia.org/wiki/Priority_queue https://en.wikipedia.org/wiki/Heap_(data_structure) https://en.wikipedia.org/wiki/Binary_heap '/ type Queue public: '' Public enumeration to express the priority order we want enum PriorityOrder Ascending Descending end enum

constructor Queue( _ byval aSize as uinteger ) /' Note that the default priority order is set to 'Descending' since this property is usually understood as 'the higher the value, the higher the priority' '/ this.constructor( _ aSize, _ PriorityOrder.Ascending ) end constructor

Note that we're using a 1-based array instead of a more common 0-based one. This makes a lot of things easier down the road, especially adding an element: since we're declaring the element count as unsigned, leaving a bit of space at the root of the heap we don't have to check for underflow conditions during the sifting. '/ m_size = _ iif( _ aSize < 1, _ 1, _ aSize ) m_priorityOrder = aPriorityOrder

redim _ m_elements( 1 to m_size )

m_count = 0 m_initialSize = m_size m_lowerBound = 1 end constructor

destructor Queue() '' Delete all elements if the heap for _ i as integer = 1 to m_count delete( m_elements( i ) ) next end destructor

sub Queue.resize( byval newSize as uinteger ) /' Resizes the internal array used as the heap.

The algorithm works like this: When you instantiate the list, the initial size is recorded, and is used to determine when the list is resized, and by how much. In this case, the array grows every time the number of items exceed the initial value by half, and shrinks every time that the previous size is exceeded also by half.

This way, you'll always have a 'window', centered around the current item count. Hence, most of the resizing will happen during bulk addition or deletion operations, not when there's a relatively balanced number of them. '/ newSize = _ iif( _ newSize < m_initialSize, _ m_initialSize, _ newSize )

Whenever one adds an element to a binary heap, the heap has to be rebalanced (a process known as 'sifting') to leave it in a valid state. The procedure starts at the tail and proceeds towards the root.

Look here for a reference on how this is implemented: https://en.wikipedia.org/wiki/Heap_(data_structure)#Implementation '/ '' This will hold the added element dim as QueueElement ptr newElement

/' Swap positions if the considered element's priority is *lower* than that of its parent '/ needSwap = true end if

case PriorityOrder.Descending if( _ m_elements( elementPosition )->priority > _ m_elements( parentPosition )->priority ) then /' Swap positions if the considered element's priority is *higher* than that of its parent '/ needSwap = true end if end select /' Swap the considered element with its parent and update the element's position to that of its parent to continue the sifting. '/ if( _ needSwap ) then swap _ m_elements( elementPosition ), _ m_elements( parentPosition ) elementPosition = parentPosition else '' No need to swap, element is already at the correct position exit do end if else '' Element is already at the root, end the sifting exit do end if loop

/' Returns the newly enqueued element

This allows to cache the element for fast lookups if needed. Be careful how you use this! '/ return( newElement ) end function

function Queue.pop() as any ptr /' Dequeues (removes) an element from the heap

The heap has to be sifted also when removing elements, this time starting from the head (the root) element and proceeding towards the tail. '/

if( _ m_count > 0 ) then '' Fetch the 'value' at the root of the heap dim as any ptr elementValue = m_elements( 1 )->value

/' Here, the element at the root of the heap is successively checked against its two siblings to swap their positions if necessary. The current element position is set at the root of the heap to start the sifting. '/ dim as uinteger _ elementPosition = 1, _ _ '' The computed positions of both siblings of the considered element child1Position, child2Position, _ _ '' The potentially new position the element could take newPosition

'' Flag to determine if we swap the element or not dim as boolean needSwap /' If there's still elements remaining in the heap, we need to reorder them to account for the removal of it's previous root element. The sifting direction depends on how the class was instantiated (in 'Ascending' or 'Descending' priority order). '/

'' Check if the element has one or two siblings if( _ child1Position <= m_count ) then if( _ child2Position <= m_count ) then /' The element has two siblings, see which of the two we need to swap according to the desired priority order, and record its position. '/ select case as const m_priorityOrder case PriorityOrder.Ascending '' Set the new potential position to the *lowest* of the two siblings newPosition = _ iif( _ m_elements( child1Position )->priority < m_elements( child2Position )->priority, _ child1Position, _ child2Position )

case PriorityOrder.Descending '' Set the new potential position to the *highest* of the two siblings newPosition = _ iif( _ m_elements( child1Position )->priority > m_elements( child2Position )->priority, _ child1Position, _ child2Position ) end select else '' Only one sibling left, always record its position newPosition = child1Position end if

case PriorityOrder.Descending needSwap = _ iif( _ m_elements( elementPosition )->priority < m_elements( newPosition )->priority, _ true, _ false ) end select /' If needed, swap the considered element's position with the new position computed above, and set the current element position to the new one to continue the sifting from there. '/ if( _ needSwap ) then swap _ m_elements( elementPosition ), _ m_elements( newPosition ) elementPosition = newPosition else '' Element is already in its correct position exit do end if else '' Element bubbled to the tail of the heap exit do end if loop

'' Return the root element value return( elementValue ) end if

'' If there's no elements in the heap, return a null pointer return( Null ) end function

function Queue.top() as any ptr /' Peeks the top value field of the root of the heap, without removing it.

If you specified a dispose callback for elements in the heap, be careful not to delete them manually using this method or you'll crash the app when the heap is deleted (since it'll invoke a function pointer on an element that's not there anymore).

It will return a null pointer if the heap is empty. '/ if( _ m_count > 0 ) then return( m_elements( 1 )->value ) else return( Null ) end if end function end namespaceend namespace

As you can see, it has nothing to do with maintaining the whole heap sorted, only a few elements are sorted upon insertion and retrieval. The implementation shown here is fully abstract, meaning that it stores a pointer to something (in your case, the cells the pathing algorithm is considering in its 'open' list). Here I just cast the priority to a pointer to store it, for demonstration purposes.

You can also specify a callback in case you need to also dispose of the elements stored upon popping them (not very useful in this case, IMO, but the possibility is there anyway, to maintain orthogonality with other data structures in my framework).

IMHO the fastest way to get a sorted list is to implement it as a chained list of UDTs. I've already done something similar, but for strings, not for integers. To give you an idea what I'm talking of, here a quick and dirty 1st approach:

So....in a Priority Queue, you can only access one item - the 'top' of the queue... and it will be either the smallest (or largest) value depending on how the Queue is set up, right? So, a Priority Queue is useful for pathfinding (djistras, A*, etc), but maintaining a sorted list/heap might be what I want for a Timer Event List - because there might be a need to find and remove a member within the list, not just accessing the lowest value event each time.

grindstone,in comparing the two methods, your method has the same slow time as mine for finding a particular member, but yours has trivial time to 'insert' a new member at any location. Could yours (I am awful with pointer stuff) be made so that a Binary Search could be used to find a member? I guess it would need a new, sorted list (by referenced value) of the pointers, right?

The functions that I want fast (trivial) are:accessing/deleting the Least most value (done)ADDing a new value (search/find location(slow), insert(mine=slow, grindstone=fast))DELeting a particular value (search/find location(slow), delete(mine=slow,grindstone=fast)

I am assuming a Binary Search function would be fast enough to speed up the ADD/DEL functions to acceptable levels

leopardpm wrote:So....in a Priority Queue, you can only access one item - the 'top' of the queue... and it will be either the smallest (or largest) value depending on how the Queue is set up, right? So, a Priority Queue is useful for pathfinding (djistras, A*, etc), but maintaining a sorted list/heap might be what I want for a Timer Event List - because there might be a need to find and remove a member within the list, not just accessing the lowest value event each time.

Indeed. Priority queues are used to retrieve the lowest F-cost node from the open list in algorithms such as A* (see here). For the other application, you might want to use another, different data structure as other members suggested here.

I am assuming a Binary Search function would be fast enough to speed up the ADD/DEL functions to acceptable levels

That depends on the data, mostly. You can use a hash table implementation that indexes into buckets of priority queues, for example. That will address all the speed requirements you need, at the usual tradeoff of speed vs. memory, of course.

grindstone wrote:Like I said, my posted code is only a 1st approach (quick and dirty). I once implemented a search tree for strings, including a fast search function. Please give me some time to recode.

What do you want to get fast: A certain index or a certain value?

value

So, finding, adding, deleting any value , and , accessing the first value (smallest or largest value)