- Joined
- Jul 10, 2007
- Messages
- 6,306
This will talk about what an indexed array, stack, queue, and dequeue are as well as introduce how they work and how to use them.
Requires knowledge of struct syntax.
Indexed Array
Requires knowledge of struct syntax.
Indexed Array
The Linked ListAn indexed array is an array that uses a counter and prevents holes in data.
JASS:integer array a integer acount = 0 set acount = acount + 1 set a[acount] = 1 set acount = acount + 1 set a[acount] = 2 set acount = acount + 1 set a[acount] = 3 set acount = acount + 1 set a[acount] = 4 set acount = acount + 1 set a[acount] = 5 set acount = acount + 1 set a[acount] = 6 set acount = acount + 1 set a[acount] = 7 set a[3] = 0 //hole
To prevent the hole from occurring, an indexed array will overwrite the value of the removed index with the value from the last index and decrease the counter. Essentially, it will remove the last index and shove whatever value is in that last index into the target index.
JASS:integer array a integer acount = 0 set acount = acount + 1 set a[acount] = 1 set acount = acount + 1 set a[acount] = 2 set acount = acount + 1 set a[acount] = 3 set acount = acount + 1 set a[acount] = 4 set acount = acount + 1 set a[acount] = 5 set acount = acount + 1 set a[acount] = 6 set acount = acount + 1 set a[acount] = 7 set a[3] = a[acount] //shove 7 into a[3] set acount = acount - 1 //remove 7
However, because of this, the order is not maintained.
Before-
JASS:a[1]=1 a[2]=2 a[3]=3 a[4]=4 a[5]=5 a[6]=6 a[7]=7 //end
After-
JASS:a[1]=1 a[2]=2 a[3]=7 a[4]=4 a[5]=5 a[6]=6 //end
Indexed arrays are useful as to allocate new memory a counter can be increased. However, if data order is a necessity, they shouldn't be used. Furthermore, looping through an indexed array in JASS is slower than looping through what is called a linked list as JASS math is so slow. Indexed arrays also take up minimal memory.
Indexed arrays are also only useful for single types (pretty much like an advanced array).
JASS:struct IndexedArray extends array readonly static thistype size = 0 integer value static method create takes nothing returns thistype set size = size + 1 return size endmethod method destroy takes nothing returns nothing set value = size.value set size = size - 1 endmethod endstruct
A linked list is a list containing a set of pointers that point to each other.
In an indexed array, the previous and next slots are always known.
JASS:a[1] //previous a[2] a[3] //next
Simply incrementing the index by 1 will get the next. Decrementing the index by 1 will get the previous. Linked lists don't require that values be right next to each other, so they have to actually point to their next and possibly previous.
JASS://0 is treated as the head in this case //a head is the node that is used to store the list //a head can retrieve the first value on the list as well as possibly the last previous[0]=2021 next[0]=1 previous[1]=0 next[1]=3 //next points to 3 previous[3]=1 //previous points to 1 next[3]=2021 //next points to 2021 previous[2021]=3 //previous points to 3 next[2021]=0 //next points to 0
When looping through it, rather than incrementing/decrementing by 1 like in a normal loop, the pointers are used.
JASS:local integer current = next[0] loop exitwhen current == 0 //exitwhen back at the head //do some code set current = next[current] //go to the next value //above would be equivalent to //set current = current + 1 //for looping through arrays endloop
In a doubly linked list, values can easily be removed while maintaining order.
JASS:set next[previous[3]]=next[3] set previous[next[3]]=previous[3]
The above would make 1 point to 2021 and 2021 point to 1 (link them up), removing 3 from the list altogether (nothing points to it).
A list where each node on it points to its previous and its next is called a doubly linked list (two pointers). A singly linked list would look like this.
JASS:next[1]=3 next[3]=2021 next[2021]=0
Singly linked lists can only be looped through forward. Furthermore, because the previous node of any given value is unknown, only the first node on the list can be removed.
For removal, this is required
set next[1]=2021 //removes 3
When looping, if the current node were to be 3, there'd be no way to know which node was before it to perform the link. How would one retrieve 1 when they were at 3?
JASS:local integer current = 3 local integer prev //??? don't know the value because there is no pointer local integer nex = next[current] //there is a pointer for this though
A static list is where the head is always equal to 0. A dynamic list is where the head can be anything. Dynamic lists may compare to the head to exit a loop or may compare to some boolean called end (comparing a boolean is faster than comparing a large number, so booleans are good for loops when using dynamic lists).
There are also circular lists
JASS:set next[3]=5 set next[5]=8 set next[8]=11 set next[11]=3 //points back to first //3->5->8->11->3->5->8->11->3, etc
Looping through the above would continue to loop forever.
Stack
QueueA stack is a type of singly linked list. They are used to add and remove values from the beginning of the list. The common methods for them are push (add) and pop (remove).
FILO (first in last out)
Push
JASS:next[0] = 5 //first node is 5 next[3] = next[0] //next[3] is now 5 next[0] = 3 //first node is now 3 //3->5 next[8]=next[0] //next[8] is now 3 next[0]=8 //first node is now 8 //8->3->5 //etc, etc
Pop
JASS:next[0]=next[next[0]] //first node is now first node's next //next[next[0]] is next[8], which is 3 //this means that the first node is now 3 //3->5 next[0]=next[next[0]] //first node is now first node's next //next[next[0]] is next[3], which is 5 //this means that the first node is now 5 //5 next[0]=next[next[0]] //first node is now first node's next //next[next[0]] is next[5], which is 0 //this means that the first node is now 0, which is the head //the list is now empty //
Static Stack
JASS:struct Stack extends array constant thistype head = 0 readonly thistype next method push takes nothing returns nothing set next = head.next //make this node point to the first node on list set head = this //make head point to this endmethod static method pop takes nothing returns nothing set head.next = head.next.next endmethod endstruct
Structs normally use static stacks for recycling.
JASS:struct MyStack extends array private static integer instanceCount = 0 private static integer array recycle static method create takes nothing returns thistype local thistype this if (recycle[0] == 0) then //0 is head, so recycle[0] is the first node set instanceCount = instanceCount + 1 return instanceCount endif set this = recycle[0] set recycle[0] = recycle[this] //remove first node by setting head to its next return this endmethod method destroy takes nothing returns nothing set recycle[this] = recycle[0] //make next point to first node on stack set recycle[0] = this //update first node endmethod endstruct
Dynamic Stack
There are two types of dynamic stacks. The first type is where the head is just another node (first node on list, treated as a pointer to the list).
The next type is where the head is entirely its own thing.
The first type of dynamic list is more limited by total instances as instances are cut down by the head pointer (4000 lists with 1 node each would be 8000 nodes because the head is also a node). The second type is less limited (4000 lists with 1 node each would be 4000 nodes because the head is its own thing).
First Type
JASS:struct Stack extends array private static integer instanceCount = 0 readonly thistype next //use 0 as head for recycle stack static method create takes nothing returns thistype local thistype this if (thistype(0).next == 0) then set instanceCount = instanceCount + 1 set this = instanceCount else set this = thistype(0).next set thistype(0).next = next set next = 0 endif return this endmethod method push takes nothing returns thistype local thistype node if (thistype(0).next == 0) then set instanceCount = instanceCount + 1 set node = instanceCount else set node = thistype(0).next set thistype(0).next = node.next endif set node.next = next set next = node return node endmethod method pop takes nothing returns thistype local thistype node = next set next = node.next //recycle the node set node.next = thistype(0).next set thistype(0).next = node return node endmethod method destroy takes nothing returns nothing local thistype last = this loop exitwhen last.next == 0 set last = last.next endloop set last.next = thistype(0).next set thistype(0).next = this endmethod endstruct
Second Type
JASS:struct Stack extends array private static integer instanceCount = 0 private static integer nodeCount = 0 readonly thistype next //use 0 as head for recycle stack private static integer array recycle readonly thistype first static method create takes nothing returns thistype local thistype this if (recycle[0] == 0) then set instanceCount = instanceCount + 1 set this = instanceCount else set this = recycle[0] set recycle[0] = recycle[this] set first = 0 endif return this endmethod method push takes nothing returns thistype local thistype node if (thistype(0).next == 0) then set nodeCount = nodeCount + 1 set node = nodeCount else set node = thistype(0).next set thistype(0).next = node.next endif set node.next = first set first = node return node endmethod method pop takes nothing returns thistype local thistype node = first set first = node.next //recycle the node set node.next = thistype(0).next set thistype(0).next = node return node endmethod method destroy takes nothing returns nothing local thistype last = first loop exitwhen last.next == 0 set last = last.next endloop //recycle set of nodes set last.next = thistype(0).next set thistype(0).next = first //recycle head set recycle[this] = recycle[0] set recycle[0] = this endmethod endstruct
DequeueA queue is a singly linked list that has a pointer to its first and last nodes. They are used to add values to the end of the list and remove values from the front.
FIFO (first in first out)
The pointer to the first node is just head.first or head.next, and the pointer to the last node is head.last.
Static Queue
JASS:struct Queue extends array constant thistype head = 0 readonly thistype next readonly static thistype last = 0 method push takes nothing returns nothing set last.next = this set last = this set next = 0 endmethod static method pop takes nothing returns nothing set head.next = head.next.next if (head.next = 0) then set last = head endif endmethod endstruct
Dynamic Queue
First Type
JASS:struct Queue extends array private static integer instanceCount = 0 readonly thistype next //use 0 as head for recycle stack readonly thistype last static method create takes nothing returns thistype local thistype this if (thistype(0).next == 0) then set instanceCount = instanceCount + 1 set this = instanceCount else set this = thistype(0).next set thistype(0).next = next set next = 0 set last = this endif return this endmethod method push takes nothing returns thistype local thistype node if (thistype(0).next == 0) then set instanceCount = instanceCount + 1 set node = instanceCount else set node = thistype(0).next set thistype(0).next = node.next endif set last.next = node set last = node set node.next = 0 return node endmethod method pop takes nothing returns thistype local thistype node = next set next = node.next if (next == 0) then set last = this endif //recycle the node set node.next = thistype(0).next set thistype(0).next = node return node endmethod method destroy takes nothing returns nothing set last.next = thistype(0).next set thistype(0).next = this endmethod endstruct
Second Type
JASS:struct Queue extends array private static integer instanceCount = 0 private static integer nodeCount = 0 readonly thistype next //use 0 as head for recycle stack private static integer array recycle readonly thistype first readonly thistype last static method create takes nothing returns thistype local thistype this if (recycle[0] == 0) then set instanceCount = instanceCount + 1 set this = instanceCount else set this = recycle[0] set recycle[0] = recycle[this] set first = 0 set last = 0 endif return this endmethod method push takes nothing returns thistype local thistype node if (thistype(0).next == 0) then set nodeCount = nodeCount + 1 set node = nodeCount else set node = thistype(0).next set thistype(0).next = node.next endif if (last == 0) then set first = node else set last.next = first endif set last = node set next = 0 return node endmethod method pop takes nothing returns thistype local thistype node = first set first = node.next if (first == 0) then set last = 0 endif //recycle the node set node.next = thistype(0).next set thistype(0).next = node return node endmethod method destroy takes nothing returns nothing //recycle set of nodes if (last != 0) then set last.next = thistype(0).next set thistype(0).next = first endif //recycle head set recycle[this] = recycle[0] set recycle[0] = this endmethod endstruct
A dequeue is known as a double ended queue. It is a doubly linked list where each node on the list points to its previous and next nodes. They can do FIFO (first in first out) and LILO (last in last out). Furthermore, any node on it can be removed.
Static Dequeue
JASS:struct Dequeue extends array constant thistype head = 0 readonly thistype next readonly thistype previous //anywhere on the list method add takes thistype node returns nothing set node.previous = this set node.next = next set next.previous = node set next = node endmethod method remove takes nothing returns nothing set previous.next = next set next.previous = previous endmethod endstruct
Dynamic Dequeues
First Type
Dynamic dequeues of the first type may either terminate with the head or with a boolean value. I prefer a boolean value as it makes the loops a bit faster.
Dequeues of the first type are always circular-
JASS:head = 5 5.next = 6 6.next = 7 7.next = head
The loops look something like this
JASS:local thistype cur = head.next loop exitwhen cur == head //code set cur = cur.next endloop
JASS:local thistype cur = head.next loop exitwhen cur.end //code set cur = cur.next endloop
JASS:struct Dequeue extends array private static integer instanceCount = 0 readonly thistype next //use 0 as head for recycle stack readonly thistype previous readonly boolean end static method create takes nothing returns thistype local thistype this if (thistype(0).next == 0) then set instanceCount = instanceCount + 1 set this = instanceCount else set this = thistype(0).next set thistype(0).next = next set next = this set previous = this endif set end = true return this endmethod method add takes nothing returns thistype local thistype node if (thistype(0).next == 0) then set instanceCount = instanceCount + 1 set node = instanceCount else set node = thistype(0).next set thistype(0).next = node.next endif set node.next = next set node.previous = this set next.previous = node set next = node return node endmethod method remove takes nothing returns nothing set previous.next = next set next.previous = previous //recycle the node set next = thistype(0).next set thistype(0).next = this endmethod //where destroy is head method destroy takes nothing returns nothing set previous.next = thistype(0).next set thistype(0).next = this set end = false endmethod endstruct
Second Type
JASS:struct Dequeue extends array private static integer instanceCount = 0 private static integer array recycle readonly thistype next //use 0 as head for recycle stack readonly thistype previous readonly thistype first readonly thistype last static method create takes nothing returns thistype local thistype this if (thistype(0).next == 0) then set instanceCount = instanceCount + 1 set this = instanceCount else set this = recycle[0] set recycle[0] = recycle[node] set first = 0 set last = 0 endif return this endmethod //-where add before //where add after //0 add to end method add takes thistype where returns thistype local thistype node if (thistype(0).next == 0) then set nodeCount = nodeCount + 1 set node = nodeCount else set node = thistype(0).next set thistype(0).next = node.next endif if (first == 0) then set first = node set last = node set node.next = 0 set node.previous = 0 else if (where == 0) then set where = last endif if (where > 0) then if (where == last) then set node.next = 0 set last = node else set node.next = where.next set where.next.previous = node endif set where.next = node set node.previous = where else set where = -where if (where == first) then set node.previous = 0 set first = node else set node.previous = where.previous set where.previous.next = node endif set where.previous = node set node.next = where endif endif return node endmethod method remove takes thistype node returns nothing if (previous == 0) then set first = next else set previous.next = next endif if (next == 0) then set last = previous else next.previous = previous endif //recycle the node set next = thistype(0).next set thistype(0).next = this endmethod //takes list method destroy takes nothing returns nothing //recycle set of nodes if (last != 0) then set last.next = thistype(0).next set thistype(0).next = first endif //recycle head set recycle[this] = recycle[0] set recycle[0] = this set first = 0 set last = 0 endmethod endstruct
Last edited: