// Copyright (C) 2011  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#undef DLIB_DISJOINT_SUBsETS_SIZED_ABSTRACT_Hh_
#ifdef DLIB_DISJOINT_SUBsETS_SIZED_ABSTRACT_Hh_

#include <vector>
#include "../algs.h"

namespace dlib
{

// ----------------------------------------------------------------------------------------

    class disjoint_subsets_sized 
    {
        /*!
            INITIAL VALUE
                - size() == 0
                - get_number_of_sets() == 0

            WHAT THIS OBJECT REPRESENTS
                This object represents a set of integers which is partitioned into
                a number of disjoint subsets.  It supports the two fundamental operations
                of finding which subset a particular integer belongs to as well as
                merging subsets.  It also allows you to find out how big each subset is.  It 
                is therefore essentially the same thing as dlib::disjoint_subsets, except
                it also keeps track of the size of each subset.
        !*/
    public:

        void clear (
        ) noexcept;
        /*!
            ensures
                - #size() == 0
                - #get_number_of_sets() == 0
                - returns this object to its initial value
        !*/

        void set_size (
            unsigned long new_size
        );
        /*!
            ensures
                - #size() == new_size
                - #get_number_of_sets() == new_size
                - for all valid i:
                    - #find_set(i) == i
                      (i.e. this object contains new_size subsets, each containing exactly one element)
                    - #get_size_of_set(i) == 1
        !*/

        size_t size (
        ) const noexcept;
        /*!
            ensures
                - returns the total number of integer elements represented
                  by this object.
        !*/

        unsigned long find_set (
            unsigned long item
        ) const;
        /*!
            requires
                - item < size()
            ensures
                - Each disjoint subset can be represented by any of its elements (since
                  the sets are all disjoint).  In particular, for each subset we define
                  a special "representative element" which is used to represent it.
                  Therefore, this function returns the representative element for the
                  set which contains item.
                - find_set(find_set(item)) == find_set(item)
                - Note that if A and B are both elements of the same subset then we always
                  have find_set(A) == find_set(B).
        !*/

        unsigned long merge_sets (
            unsigned long a,
            unsigned long b
        );
        /*!
            requires
                - a != b
                - a < size()
                - b < size()
                - find_set(a) == a
                  (i.e. a is the representative element of some set)
                - find_set(b) == b
                  (i.e. b is the representative element of some set)
            ensures
                - #find_set(a) == #find_set(b)
                  (i.e. merges the set's containing a and b)
                - #get_size_of_set(#find_set(a)) == get_size_of_set(a) + get_size_of_set(b)
                - #get_number_of_sets() == get_number_of_sets() - 1
                - returns #find_set(a)
        !*/

        unsigned long get_number_of_sets (
        ) const noexcept;
        /*!
            ensures
                - returns the current number of different subsets.
        !*/

        unsigned long get_size_of_set(
                unsigned long item
        ) const;
        /*!
            requires
                - item < size()
                - find_set(item) == item
                  (i.e. item is the representative element of some set)
            ensures
                - returns the number of elements which belongs to the set where item is the representative element.
        !*/
    };

// ----------------------------------------------------------------------------------------

}

#endif // DLIB_DISJOINT_SUBsETS_ABSTRACT_Hh_
