简体   繁体   English

如何映射/索引向量(整数)以便快速访问和比较c ++

[英]How to map/ index vectors(of integers) for fast access and comparison c++

I have a vector of vector of int that grows very large (intentional). 我有一个int矢量向量增长非常大(有意)。

vector<vector<int>> coinGroups;

In each step of my algorithm, I attempt to combine each (vector of int) with each other one. 在我的算法的每一步中,我尝试将每个(int的向量)彼此组合。 For a combine to pass and be added to the vector vector for the next loop iteration, it has to pass three criteria, two of which are super fast and not relevant here, but the one that is slow is my issue: 对于要传递并被添加到向量矢量以进行下一个循环迭代的组合,它必须通过三个标准,其中两个是超快速且在这里不相关,但是慢的是我的问题:

Head has to match tail: 头必须匹配尾巴:

//bool match = equal(coinGroups.at(i).begin()+1, coinGroups.at(i).end(), coinGroups.at(ii).begin());

Visually this compares (a,b,c,d) to (e,f,g,h) as b==e && c==f && d==g 在视觉上,这将(a,b,c,d)与(e,f,g,h)比较为b == e && c == f && d == g

*I tried map with the vector of int as the key... but that was super slow (i assume i did it wrong) *我尝试使用int的向量作为关键...但这是超级慢的(我假设我做错了)

Here is a standalone .cpp if anyone needs it or if it makes more sense: 这是一个独立的.cpp,如果有人需要它或更有意义:

arguments are nothing (defaults to 12 12) or two space separated integers greater than 3 (forewarning this algo is O(n!) complexity) 参数什么都不是(默认为12 12)或两个空格分隔的整数大于3(预警这个算法是O(n!)复杂度)

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <map>
#include <sstream>

using namespace std;

//min clock size 3
vector<vector<int>> placeCoins(int _clockSize, vector<int> _coins)
{
    int totalCheckedCombos = 0;
    vector<vector<int>> coinGroups;
    vector<int> coinSet = _coins;
    sort(coinSet.begin(), coinSet.end());
    coinSet.erase(unique(coinSet.begin(), coinSet.end()), coinSet.end());

    map<int, int> coinCounts;
    for (int i = 0; i < coinSet.size(); i++)
    {
        coinCounts[coinSet.at(i)] = count(_coins.begin(), _coins.end(), coinSet.at(i));
    }

    cout << "pairs" << endl;
    //generate fair pairs of coins
    for (int i = 0; i < coinSet.size(); i++)
    {
        for (int ii = 0; ii < coinSet.size(); ii++)
        {
            if ((coinSet.at(i) + coinSet.at(ii)) % _clockSize != 0)
            {
                if (i == ii)
                {
                    if (coinCounts[coinSet.at(i)] > 1)
                    {
                        coinGroups.push_back({ coinSet.at(i),coinSet.at(ii) });
                    }
                }
                else
                {
                    coinGroups.push_back({ coinSet.at(i),coinSet.at(ii) });
                }
            }
        }
    }

    cout << "combine" << endl;
    //iteratively combine groups of coins
    for (int comboSize = 3; comboSize < _clockSize; comboSize++)
    {
        totalCheckedCombos += coinGroups.size();
        vector<vector<int>> nextSizeCombos;
        for (int i = 0; i < coinGroups.size(); i++)
        {
            for (int ii = 0; ii < coinGroups.size(); ii++)
            {
                //check combo to match

                //cleaner but slower due to inability to breakout early on compare check
                //bool match = equal(coinGroups.at(i).begin()+1, coinGroups.at(i).end(), coinGroups.at(ii).begin());

                bool match = true;
                for (int a = 0; a < comboSize - 2; a++)
                {
                    if (coinGroups.at(i).at(a+1) != coinGroups.at(ii).at(a))
                    {
                        match = false;
                        break;
                    }
                }

                //check sum
                if (match)
                {
                    vector<int> tempCombo = coinGroups.at(i);
                    int newVal = coinGroups.at(ii).at(coinGroups.at(ii).size()-1);
                    tempCombo.push_back(newVal);
                    if (coinCounts[newVal] >= count(tempCombo.begin(), tempCombo.end(), newVal))
                    {
                        if (accumulate(tempCombo.begin(), tempCombo.end(), 0) % _clockSize != 0)
                        {
                            nextSizeCombos.push_back(tempCombo);
                        }
                    }
                }
            }
        }

        if (nextSizeCombos.size() == 0)
        {
            //finished, no next size combos found
            break;
        }
        else
        {
            cout << nextSizeCombos.size() << endl;
            coinGroups = nextSizeCombos;
        }
    }
    cout << "total combos checked: " << totalCheckedCombos << endl;
    return coinGroups;
}

//arguments are _clockSize _coinCount
//The goal of this algorithm is to create combos of stepSizeTokens (coins) which fill a loop of register locations (clock)
int main(int argc, char *argv[]) {
    int clockSize = 12;
    int coinCount = 12;

    if (argc >= 2)
    {
        std::istringstream iss(argv[1]);
        if (!(iss >> clockSize))
        {
            cout << "argument 1 invalid" << endl;
            cout << "press enter to end program" << endl;
            cin.get();
            return 0;
        }
        std::istringstream iss2(argv[2]);
        if (!(iss2 >> coinCount))
        {
            cout << "argument 2 invalid" << endl;
            cout << "press enter to end program" << endl;
            cin.get();
            return 0;
        }
    }

    if (clockSize < 3) { clockSize = 3; }

    vector<int> coins = {};
    cout << "coin list:" << endl;
    for (int i = 0; i < coinCount; i++)
    {
        int tempCoin = rand() % (clockSize - 1) + 1;
        cout << tempCoin << " , ";
        coins.push_back(tempCoin);
    }
    cout << endl;


    vector<vector<int>> resultOrders = placeCoins(clockSize, coins);

    cout << "max combo size: " << resultOrders.at(0).size() << endl;
    cout << "number of max combos found: " << resultOrders.size() << endl;

    cout << "press enter to end program" << endl;
    cin.get();
}

My question : Is there a storage object and or strategy by which I could label all unique combos before entering the n^2 loops so that I could just compare labels instead of memberwise combos? 我的问题 :在进入n ^ 2循环之前,是否有存储对象和策略可以标记所有独特的组合,以便我可以只比较标签而不是成员组合? *each member of coinGroups would have a tail and head combo to be labeled/indexed so that I would not have to iterate through all the items in the combo more than once for each member. * coinGroups的每个成员都有一个尾部和头部组合被标记/索引,这样我就不必为每个成员多次迭代组合中的所有项目。

You can go with a tree-like structure. 你可以采用树状结构。

The tree works like this: Every edge is labeled by a coin. 树的工作方式如下:每条边都用硬币标记。 The leaves of the tree store references to all members of your vector which have a tail that matches the trace from the root to that leave. 树存储的叶子引用了向量的所有成员,这些成员的尾部与从根到该离开的跟踪相匹配。

In the pre-processing, you create that tree by going through all vectors and try to traverse the tree, if not possible extend the tree. 在预处理中,您通过遍历所有向量创建该树并尝试遍历树,如果不可能扩展树。

In the main routine, you simply try to traverse the tree for every head of a vector. 在主例程中,您只需尝试遍历向量的每个头部的树。

The resulting complexity for both is O(N * M * deg), with deg being the maximal out-degree of the nodes in that tree, which is smaller than the amount of different coins, N being the amount of vector and M the size of the tail/head. 由此得到的复杂度为O(N * M * deg),其中deg是该树中节点的最大出度,小于不同硬币的数量,N是向量的数量,M是大小尾部/头部。 Assuming that M and deg do not rise with bigger inputs, this is O(N). 假设M和deg不随较大输入而上升,则为O(N)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM