Skip to content
Snippets Groups Projects
Components.h 2.69 KiB
Newer Older
  • Learn to ignore specific revisions
  • Jan Brož's avatar
    Jan Brož committed
    /*
     * Kruskal.cpp
     *
     *   Created on: Mar 26, 2016
     *       Author: Jan Broz
     */
    
    #include <unordered_map>
    
    #include <graph/common/Node.h>
    
    namespace graph {
    
    /// class solving "Union-Find" problem
    class Components {
    
     protected:
    
    	/// wrapper over the node containing identification of parent and height of subtree
    	struct SetNode {
    		Node parent;
    		int height;
    	};
    
    	std::unordered_map< Node, SetNode > nodes;
    
     public:
    
    	/// marks a node as a single-element component
    	void MakeSet( Node node )
    	{
    		nodes[ node ].parent = node;
    		nodes[ node ].height = 0;
    	}
    
    	/// returns a reprezentative of the component in which is the given node
    	Node Find( Node node )
    	{
    		if (node != nodes[ node ].parent)
    			nodes[ node ].parent = Find( nodes[ node ].parent ); // shorten the path to root for next use
    		return nodes[ node ].parent;
    	}
    
    	/// unifies 2 acyclic components
    	void Union( Node node1, Node node2 )
    	{
    		Link( Find( node1 ), Find( node2 ) );
    	}
    
     protected:
    
    	void Link( Node root1, Node root2 )
    	{
    		// connect smaller into bigger to limit the final depth
    		if (nodes[ root1 ].height < nodes[ root2 ].height) {
    			nodes[ root1 ].parent = root2;
    		} else {
    			nodes[ root2 ].parent = root1;
    			// if the trees are equaly high, connecting them increases the height by 1
    			if (nodes[ root1 ].height == nodes[ root2 ].height)
    				nodes[ root1 ].height++;
    		}
    	}
    
    };
    
    /// class solving "Union-Find" problem (version indexed by integers)
    class Components2 {
    
     protected:
    
    	/// wrapper over the node containing identification of parent and height of subtree
    	struct SetNode {
    		uint parent;
    		int height;
    	};
    
    	SetNode * _nodes;
    
     public:
    
     	Components2( uint nodeCount )  { _nodes = new SetNode [nodeCount]; }
     	~Components2()                 { delete [] _nodes; }
    
    	/// marks a node as a single-element component
    	void MakeSet( uint node )
    	{
    		_nodes[ node ].parent = node;
    		_nodes[ node ].height = 0;
    	}
    
    	/// returns a reprezentative of the component in which the given node is
    	uint Find( uint node )
    	{
    		if (node != _nodes[ node ].parent)
    			_nodes[ node ].parent = Find( _nodes[ node ].parent ); // shorten the path to root for next use
    		return _nodes[ node ].parent;
    	}
    
    	/// unifies 2 acyclic components
    	void Union( uint node1, uint node2 )
    	{
    		Link( Find( node1 ), Find( node2 ) );
    	}
    
     protected:
    
    	void Link( uint root1, uint root2 )
    	{
    		// connect smaller into bigger to limit the final depth
    		if (_nodes[ root1 ].height < _nodes[ root2 ].height) {
    			_nodes[ root1 ].parent = root2;
    		} else {
    			_nodes[ root2 ].parent = root1;
    			// if the trees are equaly high, connecting them increases the height by 1
    			if (_nodes[ root1 ].height == _nodes[ root2 ].height)
    				_nodes[ root1 ].height++;
    		}
    	}
    
    };
    
    } // namespace graph