1. A little know data structure I'm teaching here...
- Posted by Carlos Jose Gonzalia <gonzalia at CRIBA.EDU.AR> Mar 31, 1997
- 1060 views
Hi all, I'm using the so called "binomial queues" as an example of algorithm analysis and design in my university course here. I have programmed it for my students to see it completely specified, and thought maybe somebody would find it interesting and (who knows) useful... The idea is that binomial queues are a good implementation of priority queues because they allow you to merge 2 queues faster than the normal heap based implementations. Priority queues are fundamental to many algorithms in simulation, operating system implementation, and graph manipulation. Hope you enjoy it and let me know if some terrible bug evaded me (surely)... ----- CODE BEGINS HERE ----- ------------------------------------------------------------------------------ -- Binomial queue module -- 1997, Carlos Gonzalia, Argentina, South America -- version 0.1 -- this code is hereby put in public domain, but you take full -- responsibility for its use or modifications -- bugs, comments, questions: gonzalia at criba.edu.ar (till june 6 only) ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- General constants and functions defined for readability -- Boolean constants constant FALSE = 0 constant TRUE = 1 -- Comparison functions function lt(object x, object y) return compare(x,y)=-1 end function function gt(object x, object y) return compare(x,y)=1 end function -- Sequence functions function rest(sequence x) return x[2..length(x)] end function ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- Binomial tree data type -- Abstract definition: -- a one-node tree is a binomial tree of height 0 -- attaching to a binomial tree of height k-1 another binomial tree of -- height k-1 as rightmost son gives a height k binomial tree, if the -- heap order property is still satisfied -- (aside: a tree satisfies the heap order property if and only if for -- every node x, if x has a parent, then the key in the parent of x -- is smaller or equal to the key in x) -- Implementation: -- as a non-empty sequence, whose first element is the root of the -- binomial tree, and whose second to last elements (if they are -- present) are its binomial tree sons, also sequences, in the -- order of their increasing heights ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- root returns the key in the root of its binomial tree argument -- (note t is declared as sequence since Euphoria does not support mutual -- recursion, which would be needed for it to be a binomial_tree) function root(sequence t) return t[1] end function ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- binomial_tree returns 0 (false) if its sequence argument is not a valid -- binomial tree, and k+1 if it is, where k is the height of the tree -- (note that binomial trees are by definition non-empty) -- this function takes O(n) time in the worst case type binomial_tree(sequence x) integer previous, check_i if length(x)<=1 then return length(x) end if previous = 0 for i=2 to length(x) do check_i = binomial_tree(x[i]) if previous>=check_i or gt(root(x),root(x[i])) then return FALSE end if previous = check_i end for return length(x) end type ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- merge_tree returns the binomial tree resulting from merging its two -- binomial tree arguments -- this function always takes O(1) time function merge_tree(binomial_tree s, binomial_tree t) if lt(root(s),root(t)) then return append(s,t) else return append(t,s) end if end function ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- Binomial queue data type -- Abstract definition: -- a binomial queue is a collection of binomial trees, such that there is -- at most one tree of any possible height -- Implementation: -- as a sequence of binomial_tree's, in ascending order of their heights ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- binomial_queue returns 1 (true) or 0 (false), depending on its sequence -- argument being a valid binomial queue or not -- (note that it is perfectly possible to have an empty binomial queue) -- this function takes O(n) time in the worst case global type binomial_queue(sequence x) integer previous, check_i previous = 0 for i=1 to length(x) do check_i = binomial_tree(x[i]) if previous>=check_i then return FALSE end if previous = check_i end for return TRUE end type ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- the empty binomial queue global constant empty_binom_queue = {} ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- find_min_bq returns the minimum element in the binomial queue -- this function takes O(log n) time in the worst case -- (note that using find_min_bq on an empty binomial queue is senseless -- and causes an error) global function find_min_bq(binomial_queue q) object min min = root(q[1]) for i=2 to length(q) do if gt(min,root(q[i])) then min = root(q[i]) end if end for return min end function ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- merge_bq returns the binomial queue resulting from the merge of its two -- binomial queue arguments -- this function takes O(log n) time in the worst case global function merge_bq(binomial_queue p, binomial_queue q) binomial_queue rest_merge if length(p)=0 or length(q)=0 then return p & q elsif length(p[1])<length(q[1]) then return prepend(merge_bq(rest(p),q), p[1]) elsif length(q[1])<length(p[1]) then return prepend(merge_bq(p,rest(q)), q[1]) else rest_merge = merge_bq(rest(p),rest(q)) return merge_bq({merge_tree(p[1],q[1])},rest_merge) end if end function ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- insert_bq returns the binomial queue resulting from inserting its object -- argument into its binomial queue argument -- this function takes O(log n) time in the worst case, but O(1) in average global function insert_bq(object x, binomial_queue q) return merge_bq(q,{{x}}) end function ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- delete_min_bq returns the binomial queue resulting from deleting the -- minimum object in the queue -- (note that using delete_min_bq on an empty binomial queue is senseless -- and causes an error) -- this function takes O(log n) time in the worst case global function delete_min_bq(binomial_queue q) integer min binomial_queue except_min min = 1 for i=2 to length(q) do if gt(root(q[min]),root(q[i])) then min = i end if end for except_min = q[1..min-1] & q[min+1..length(q)] return merge_bq(rest(q[min]),except_min) end function ------------------------------------------------------------------------------ ----- CODE ENDS HERE ----- Carlos Gonzalia, Universidad Nacional del Sur, Argentina, South America gonzalia at criba.edu.ar