Guest User

Untitled

a guest
Jun 18th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.33 KB | None | 0 0
  1. def heapsort(arr)
  2.  
  3. logmsg = ->(s,n=nil){puts("[HEAPSORT#{n ? "@N:#{n}" : ""}] #{s}")}
  4.  
  5. # those lambdas make it possible to build a heap
  6. # and still maintain a 1D array shape
  7. heap_children_offset = ->(i) { 2*i+1 }
  8. heap_parent = ->(i) { (i-((i+1)%2)-1)/2 }
  9. broken_heapprop = ->(i,c){ c.all?{|child|i>=child} == false }
  10.  
  11. sift_down_if_needed = lambda do |parent_i,_arr,check=true|
  12. enter_pi = parent_i # only used for logmsg
  13. sift_needed = false # only used for logmsg
  14. loop do
  15. parent = _arr[parent_i]
  16. children_o = heap_children_offset.call(parent_i)
  17. children = _arr.values_at(children_o, children_o+1).select{|i|i!=nil}
  18. break if children==[]
  19. children_mi= children_o + children.index(children.max)
  20. break unless broken_heapprop.call(parent, children)
  21. sift_needed = true
  22. logmsg.call("SIFT DOWN: arr[#{parent_i}](=#{_arr[parent_i]}) <=> arr[#{children_mi}](=#{_arr[children_mi]})", enter_pi)
  23. _arr[parent_i], _arr[children_mi] = [_arr[children_mi], _arr[parent_i]]
  24. parent_i = children_mi
  25. end
  26. sift_needed||(check&&logmsg.call("Node ##{enter_pi} OK",enter_pi))
  27. _arr
  28. end
  29.  
  30. heapify = lambda do |_arr|
  31. logmsg.call "ENTER HEAPIFY"
  32. parent_i = heap_parent.call(_arr.length-1)
  33. logmsg.call "#{parent_i+1} nodes detected"
  34. loop do
  35. logmsg.call("Checking node ##{parent_i}",parent_i)
  36. _arr = sift_down_if_needed.call(parent_i, _arr)
  37. break if parent_i == 0
  38. parent_i -= 1
  39. end
  40. logmsg.call "EXIT HEAPIFY"
  41. _arr
  42. end
  43.  
  44. logmsg.call "ENTER"
  45.  
  46. heap = Array.new heapify.call(arr) ; arr.clear
  47.  
  48. until heap == []
  49. arr.unshift heap.shift # unshift the top element of the heap into the array
  50. logmsg.call "#{heap.inspect} =(#{arr[0]})=> #{arr.inspect}"
  51. heap.unshift heap.pop # put the last heap element on top...
  52. logmsg.call "Putting last element of heap on top: #{heap.inspect}"
  53. if heap.length == 1
  54. arr.unshift heap.shift # unshift the top element of the heap into the array
  55. logmsg.call "#{heap.inspect} =(#{arr[0]})=> #{arr.inspect}"
  56. else
  57. heap = sift_down_if_needed.call(0, heap, false)
  58. end
  59. end
  60.  
  61. logmsg.call "EXIT"
  62.  
  63. return arr
  64.  
  65. end
  66.  
  67. hs_input = (0..7).to_a.shuffle
  68. puts "HEAPSORT INPUT = #{hs_input.inspect}"
  69.  
  70. hs_output = heapsort hs_input
  71.  
  72. puts "HEAPSORT OUTPUT = #{hs_output.inspect}"
Add Comment
Please, Sign In to add comment