• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Tree with splits, merges (joins), and subranges

Status
Not open for further replies.
Level 31
Joined
Jul 10, 2007
Messages
6,306
Coded this while working on boolean expression and solved the big problem I needed, so I don't need all of this code. Putting it up in case anyone wants to use any of it for anything. It's actually pretty neat ;). You can join nodes (any), split nodes apart, join at a node introducing a new node, and then print the ranges of the parent nodes.

The base of the tree is a list. The list is split up into partitions, these being the leaves of the tree. Any partition can be iterated over (specific partition).

JASS:
private struct Node extends array
            thistype root
            
            thistype left
            thistype right
            
            thistype next
            thistype prev
            thistype sentinel
            
            boolexpr expression
            
            implement Alloc
            
            method toString takes nothing returns string
                local thistype i = prev
                local string s = ""
                if (i == 0) then
                    set i = this
                endif
                loop
                    if (s == "") then
                        set s = I2S(i)
                    else
                        set s = s + ", " + I2S(i)
                    endif
                    exitwhen sentinel == i or i == this or i == 0
                    set i = i.next
                endloop
                
                return s
            endmethod
            
            static method create takes nothing returns thistype
                return allocate()
            endmethod
            
            private method destroy takes nothing returns nothing
                if (left == 0) then
                    call DestroyBoolExpr(expression)
                    set expression = null
                else
                    set left = 0
                    set right = 0
                    
                    set root = 0
                    
                    set next = 0
                    set prev = 0
                endif
                
                call deallocate()
            endmethod
            
            method destroySub takes nothing returns nothing
                if (left == 0) then
                    call DestroyBoolExpr(expression)
                    set expression = null
                else
                    call left.destroySub()
                    call right.destroySub()
                    
                    set left = 0
                    set right = 0
                    
                    set root = 0
                    
                    set next = 0
                    set prev = 0
                endif
                
                call deallocate()
            endmethod
            
            private method delink takes nothing returns nothing
                local thistype left = this.left
                local thistype right = this.right
                
                if (left == 0) then
                    if (prev != 0) then
                        set prev.next = next
                        set prev = 0
                    endif
                    if (next != 0) then
                        set next.prev = prev
                        set next = 0
                    endif
                else
                    loop
                        exitwhen left.left == 0
                        set left = left.left
                    endloop
                    
                    loop
                        exitwhen right.right == 0
                        set right = right.right
                    endloop
                    
                    if (left.prev != 0) then
                        set left.prev.next = right.next
                        set left.prev = 0
                    endif
                    if (right.next != 0) then
                        set right.next.prev = left.prev
                        set right.next = 0
                    endif
                endif
            endmethod
            
            private method link takes Node left, Node right returns nothing
                if (left.left == 0) then
                    if (right.left == 0) then
                        set left.next = right
                        set right.prev = left
                        set this.prev = left
                        set this.next = right
                        set this.sentinel = right
                    else
                        set left.next = right.prev
                        set right.prev.prev = left
                        set this.prev = left
                        set this.next = right.next
                        set this.sentinel = right.next
                    endif
                elseif (right.left == 0) then
                    set left.next.next = right
                    set right.prev = left.next
                    set this.prev = left.prev
                    set this.next = right
                    set this.sentinel = right
                else
                    set left.next.next = right.prev
                    set right.prev.prev = left.next
                    set this.prev = left.prev
                    set this.next = right.next
                    set this.sentinel = right.next
                endif
            endmethod
            
            private method relink takes nothing returns nothing
                if (this == 0) then
                    return
                endif
                
                loop
                    if (left.left == 0) then
                        if (right.left == 0) then
                            set this.prev = left
                            set this.next = right
                            set this.sentinel = right
                        else
                            set this.prev = left
                            set this.next = right.next
                            set this.sentinel = right.next
                        endif
                    elseif (right.left == 0) then
                        set this.prev = left.prev
                        set this.next = right
                        set this.sentinel = right
                    else
                        set this.prev = left.prev
                        set this.next = right.next
                        set this.sentinel = right.next
                    endif
                    
                    set this = root
                    exitwhen this == 0
                endloop
            endmethod
            
            private method replaceRootChild takes thistype newChild returns nothing
                set newChild.root = root
                
                if (root != 0) then
                    if (this == root.left) then
                        set root.left = newChild
                    else
                        set root.right = newChild
                    endif
                    
                    call root.relink()
                endif
            endmethod
            
            static method mergeRight takes Node left, Node right returns Node
                local Node this = Node.create()
                
                call link(left, right)
                
                call right.replaceRootChild(this)
                
                set this.left = left
                set this.right = right
                set left.root = this
                set right.root = this
                
                loop
                    set expression = Or(left.expression, right.expression)
                    set this = root
                    exitwhen this == 0
                    call DestroyBoolExpr(expression)
                endloop
                
                return this
            endmethod
            
            static method mergeLeft takes Node left, Node right returns Node
                local Node this = Node.create()
                
                call link(left, right)
                
                set this.left = left
                set this.right = right
                set left.root = this
                set right.root = this
                
                call left.replaceRootChild(this)
                
                loop
                    set expression = Or(left.expression, right.expression)
                    set this = root
                    exitwhen this == 0
                    call DestroyBoolExpr(expression)
                endloop
                
                return this
            endmethod
            
            static method merge takes Node left, Node right returns Node
                local Node this = Node.create()
                
                call link(left, right)
                
                set this.left = left
                set this.right = right
                set left.root = this
                set right.root = this
                
                set expression = Or(left.expression, right.expression)
                
                return this
            endmethod
            
            method splitLeft takes nothing returns Node
                local thistype left = this.left
                
                if (left == 0) then
                    return this
                endif
                
                call replaceRootChild(right)
                call destroy()
                
                call left.delink()
                
                return left
            endmethod
            
            method splitRight takes nothing returns Node
                local thistype right = this.right
                local thistype left = this.left
                
                if (right == 0) then
                    return this
                endif
                
                call replaceRootChild(left)
                call destroy()
                
                call right.delink()
                
                return right
            endmethod
        endstruct
 
Status
Not open for further replies.
Top