<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DZone Snippets: Dr_saturn's Code Snippets</title>
    <link>http://snippets.dzone.com/posts</link>
    <pubDate>Sun, 27 Jul 2008 03:45:15 GMT</pubDate>
    <description>DZone Snippets: Dr_saturn's Code Snippets</description>
    <item>
      <title>Disjoint Set Class in Ruby</title>
      <link>http://snippets.dzone.com/posts/show/5124</link>
      <description>A disjoint Set can be used for creating minimal spanning trees.&lt;br /&gt;The union-find algorithm is fast, faster than linked lists for some uses. &lt;br /&gt;See: &lt;a href = "http://en.wikipedia.org/wiki/Disjoint-set_data_structure"&gt;Wikipedia Disjoint Set&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It's fast and simple. Just add a DisjointSetNode object to the &lt;br /&gt;objects that you want to create a tree of. &lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# This is a disjoint set implementing union-find&lt;br /&gt;# It can be used for generating a minimal spanning&lt;br /&gt;# tree using Kruskal's algorithm.&lt;br /&gt;# http://en.wikipedia.org/wiki/Kruskal's_algorithm&lt;br /&gt;&lt;br /&gt;class DisjointSetNode&lt;br /&gt;  attr_accessor :parent, :rank&lt;br /&gt;&lt;br /&gt;  def initialize&lt;br /&gt;    @parent = self&lt;br /&gt;    @rank = 0&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  # An optimised union by rank. Attaches smaller tree to larger.&lt;br /&gt;  def union(other)&lt;br /&gt;    self_root = self.find&lt;br /&gt;    other_root = other.find&lt;br /&gt;    if self_root.rank &gt; other_root.rank&lt;br /&gt;      other_root.parent = self_root&lt;br /&gt;    elsif self_root.rank &lt; other_root.rank&lt;br /&gt;      self_root.parent = other_root&lt;br /&gt;    elsif self_root != other_root&lt;br /&gt;      other_root.parent = self_root&lt;br /&gt;      self_root.rank += 1&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def find&lt;br /&gt;    if self.parent === self&lt;br /&gt;      self&lt;br /&gt;    else&lt;br /&gt;      self.parent = self.parent.find&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;end   # class DisjointSetNode&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Some simple test code:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;require 'disjointsetnode'&lt;br /&gt;require 'test/unit'&lt;br /&gt;require 'test/unit/ui/console/testrunner'&lt;br /&gt;&lt;br /&gt;    class DisjointSetTest &lt; Test::Unit::TestCase&lt;br /&gt;      N_Nodes = 1000&lt;br /&gt;&lt;br /&gt;      def setup&lt;br /&gt;        @nodes = Array.new&lt;br /&gt;        (1..N_Nodes).each do |node|&lt;br /&gt;        @nodes &lt;&lt; DisjointSetNode.new&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      # def teardown&lt;br /&gt;      # end&lt;br /&gt;&lt;br /&gt;      def test_creation&lt;br /&gt;        @nodes.each do |node|&lt;br /&gt;          assert !node.nil?, "A Node is nil!"&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      def test_initial_values&lt;br /&gt;        @nodes.each do |node|&lt;br /&gt;          assert node.parent === node, "self #{node}, parent #{node.parent} not equal."&lt;br /&gt;          assert node.rank == 0, " A node's rtank is not 0."&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      def test_union&lt;br /&gt;        # Join all nodes in sequence&lt;br /&gt;        @nodes.each do |node|&lt;br /&gt;          if !@lastnode.nil?&lt;br /&gt;            node.union(@lastnode)&lt;br /&gt;            node_f = node.find&lt;br /&gt;            lnode_f = @lastnode.find&lt;br /&gt;            assert node_f == lnode_f, "Join not completed: node_f: #{node_f}, lnode_f: #{lnode_f}"&lt;br /&gt;          end&lt;br /&gt;          @lastnode = node&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      def test_random_union&lt;br /&gt;        (1..N_Nodes-1).each do |n|&lt;br /&gt;          node = @nodes[n]&lt;br /&gt;          other = @nodes[rand(N_Nodes-1)]&lt;br /&gt;          node.union(other)&lt;br /&gt;          node_f = node.find&lt;br /&gt;          onode_f = other.find&lt;br /&gt;          assert node_f == onode_f, "Join not completed: node_f: #{node_f}, onode_f: #{onode_f}"&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;# This runs the tests for ya! &lt;br /&gt;Test::Unit::UI::Console::TestRunner.run(DisjointSetTest)&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Sun, 10 Feb 2008 02:49:59 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/5124</guid>
      <author>dr_saturn (Stuart Coyle)</author>
    </item>
  </channel>
</rss>
