组合算法

参考

http://dongxicheng.org/structure/permutation-combination/

实现 (01转换法)

本人在此基础上做了扩展, 不再局限于数字, 可以是任意数据

#include <cstdio>
#include <vector>

namespace combination {

    template<typename T, typename I>
    void make_result(std::vector<std::vector<T> >& result, const std::vector<I>& iter_result)
    {
        std::vector<T> one;

        for (auto i = iter_result.begin(); i != iter_result.end(); ++i)
        {
            one.push_back(**i);
        }

        result.push_back(one);
    }

    template<typename T>
    bool is_equals(const std::vector<T>& a, const std::vector<T>& b)
    {
        const std::size_t n = a.size();

        if (n != b.size())
            return false;

        for (std::size_t i = 0; i < n; i++)
        {
            if (a[i] != b[i])
                return false;
        }

        return true;
    }

    template<typename I>
    int make_next(std::vector<I>& head, std::size_t r)
    {
        std::size_t i;

        for (i = 0; i < r - 1; i++)
        {
            if (head[i] + 1 != head[i + 1])
            {
                break;
            }
        }

        head[i]++;

        return i;
    }

    template<typename T>
    void make(std::vector<std::vector<T> >& result, const std::vector<T>& args, std::size_t r)
    {
        const std::size_t nArgs = args.size();

        if ((r == 0) || (nArgs < r))
            return;
        if (nArgs == r)
        {
            result.push_back(args);
            return;
        }

        typedef typename std::vector<T>::const_iterator pos_t;

        std::vector<pos_t> head, tail;

        head.resize(r);
        tail.resize(r);
        for (std::size_t i = 0; i < r; i++)
        {
            head[i] = args.begin() + i;
            tail[i] = args.end() - (r - i);
        }

        make_result(result, head);

        while (!is_equals(head, tail))
        {
            const std::size_t idx = make_next(head, r);

            for (std::size_t i = 0; i < idx; i++)
            {
                if (i == 0)
                {
                    head[i] = args.begin();
                }
                else
                {
                    head[i] = head[i - 1] + 1;
                }
            }

            make_result(result, head);
        }

        return;
    };
}

int main()
{
    std::vector<int> args;
    std::vector<std::vector<int> > result;

    args.push_back(1);
    args.push_back(2);
    args.push_back(3);
    args.push_back(4);
    args.push_back(5);

    combination::make(result, args, 3);
    for (auto i = result.begin(); i != result.end(); ++i)
    {
        const auto& ii = *i;

        for (auto e = ii.begin(); e != ii.end(); ++e)
        {
            printf("%d ", *e);
        }
        printf("\n");
    }

    return 0;
}

 

posted @ 2018-02-05 00:20  sid.x  阅读(160)  评论(0编辑  收藏  举报