想象一下,元组中有n组元素。例如,元组可能是
std::tuple<topBottomStr, topBottomStr, topBottomStr> or
std::tuple<fraction, fraction, fraction>
所以也许有一些代表“topbottomthings”的模板
template<typename T>
class TopBottomThing
{
private:
T top;
T bottom;
};
关键在于元组中的内容具有顶部和底部的概念。我的问题是,我需要一个返回
的函数std::vector<std::tuple<TopBottomThing>> ArrangeTopBottomThingFunc(std::vector<std::tuple<TopBottomThing>> tup)
返回值中的项目
std::vector<std::tuple<TopBottomThing>> retVal;
的排列方式是每个连续条目的TopBottomThing,std::vector<n>
的底部与std::vector<n + 1>
的顶部匹配,匹配std::vector<n + 2>
等的底部,或 std::vector<n>
的顶部与std::vector<n + 1>
的顶部匹配,或 std::vector<n>
的底部与std::vector<n + 1>
的底部匹配。只保证一个案例作为对函数的约束。如果输入向量的长度为n,则保证0匹配或n-1匹配。
例如,如果std::vector<std::tuple<TopBottomThing>>
tup表示标准分数:
2/3 4/5 3/2,
使用std::vector<tup>
作为输入的ArrangeTopBottomThingFunc将返回按此标准排序一个std :: vector,如下所示:
[0] = 3/2 [1] = 2/3 [2] = 4/5(两个匹配上/下)
如果std :: tuple tup有这些分数:
4/7 3/2 1/2
[0] = 3/2 [1] = 1/2 [2] = 4/7(两个匹配底部/底部)
或
4/5 7/8 4/6
[0] 4/5 [1] = 4/6 [2] = 7/8(两场比赛顶/顶)
或退化案例
4/5 6/3 2/7(不匹配)
会按照给定的顺序返回。
或者说std :: tuple tup表示像这样的字符串
“Straberry / Banana”“蓝莓/猕猴桃”“Kiwi / Banana”
[0] =“Kiwi / Banana”[1] =“Straberry / Banana”[2] =“蓝莓/猕猴桃”
三个(n)顶部或底部中的至少两个保证匹配。如果算法适用于任何长度的
,那将是很好的std::vector<std::tuple<TopBottomThing>> input.
它只是对std :: vector进行排序和返回,其顶部/顶部,底部/底部或顶部/底部按升序排列。以这种方式不匹配的其余部分只需按任何顺序添加。
最后,如果调用函数通过返回这样的枚举来理解事物的排序方式会很好:
enum class WHICHSORT { NO_MATCHES, BOTH_TOP, BOTH_BOTTOM, MIXED_TOP_BOTTOM };
答案 0 :(得分:1)
如果我正确理解您的问题,我想您要说的是,您要确定所有TopBottomThing的顶部与其他条目匹配,或者底部与其他条目匹配。然后你想用min(顶部,底部)对那些TopBottomThing进行排序。
这是我用来做这样的事情的算法。创建一个std :: map,它存储从类型T(从TopBottomThing的定义)到size_t的映射。迭代您的输入,并为每个TopBottomThing添加顶部以及底部(但仅当与顶部不同)项目添加到地图。添加新条目时,将值初始化为零。否则,增加现有值。
下一步是创建两个向量:一个用于保存匹配某些东西的TopBottomThing,另一个用于那些不匹配的向量。再次遍历TopBottomThing列表,并从地图中选择max(map [top],map [bottom])。如果该最大值至少为1,则结果与至少一个其他条目匹配,因此将其添加到匹配向量。否则,将其添加到非匹配向量。之后,对匹配向量进行排序,然后附加非匹配向量,并返回该结果。代码如下:
#include <algorithm>
#include <iostream>
#include <map>
#include <random>
#include <vector>
using namespace std;
template<class T>
class TopBottom {
public:
T top;
T bottom;
TopBottom(T _top, T _bottom) : top(_top), bottom(_bottom) {
}
};
void print(vector<TopBottom<int>> myThings) {
for (auto topBottom = myThings.begin(); topBottom != myThings.end(); ++topBottom) {
cout << (topBottom == myThings.begin() ? "(" : " ");
cout << topBottom->top << '/' << topBottom->bottom;
}
cout << ')';
}
template<class T>
void Arrange(vector<TopBottom<T>> &topBottoms) {
// Determine the number of TopBottom's with each value for either top or bottom
map<T, size_t> countOfObjects;
for (auto topBottom = topBottoms.cbegin(); topBottom != topBottoms.cend(); ++topBottom) {
++countOfObjects[topBottom->top];
if (topBottom->top != topBottom->bottom) {
++countOfObjects[topBottom->bottom];
}
}
// Split the input into two lists; one with things that match, and the remainder
vector<TopBottom<T>> matches;
vector<TopBottom<T>> nonMatches;
for (auto topBottom = topBottoms.cbegin(); topBottom != topBottoms.cend(); ++topBottom) {
auto matchingObjectCount = max(countOfObjects[topBottom->top],
countOfObjects[topBottom->bottom]) - 1;
(0 < matchingObjectCount ? matches : nonMatches).push_back(*topBottom);
}
// Here you can sort the matches however you want
// Populate the result
topBottoms.clear();
topBottoms.insert(topBottoms.end(), matches.cbegin(), matches.cend());
topBottoms.insert(topBottoms.end(), nonMatches.cbegin(), nonMatches.cend());
}
int main(int argc, char *argv[]) {
vector<TopBottom<int>> myThings;
mt19937 rng;
for (auto i = 0; i < 20; ++i) {
myThings.clear();
myThings.push_back(TopBottom<int>(rng() % 10, rng() % 10));
myThings.push_back(TopBottom<int>(rng() % 10, rng() % 10));
myThings.push_back(TopBottom<int>(rng() % 10, rng() % 10));
myThings.push_back(TopBottom<int>(rng() % 10, rng() % 10));
print(myThings);
cout << " => ";
Arrange(myThings);
print(myThings);
cout << endl;
}
cin.get();
return 0;
}
运行此代码会生成以下输出:
(2/2 5/4 1/4 5/9) => (5/4 1/4 5/9 2/2)
(3/8 5/5 6/0 0/9) => (6/0 0/9 3/8 5/5)
(4/9 6/7 9/9 9/3) => (4/9 9/9 9/3 6/7)
(6/6 3/6 1/0 9/2) => (6/6 3/6 1/0 9/2)
(8/9 5/6 3/3 8/7) => (8/9 8/7 5/6 3/3)
(6/4 0/5 6/7 4/5) => (6/4 0/5 6/7 4/5)
(2/7 3/8 6/0 6/2) => (2/7 6/0 6/2 3/8)
(7/6 6/4 1/9 8/6) => (7/6 6/4 8/6 1/9)
(0/2 2/2 3/1 2/5) => (0/2 2/2 2/5 3/1)
(9/9 6/1 0/9 8/8) => (9/9 0/9 6/1 8/8)
(3/8 0/9 3/6 3/2) => (3/8 3/6 3/2 0/9)
(9/0 4/9 5/4 6/7) => (9/0 4/9 5/4 6/7)
(1/2 4/0 9/1 5/8) => (1/2 9/1 4/0 5/8)
(0/2 8/1 7/1 8/6) => (8/1 7/1 8/6 0/2)
(8/7 4/6 9/2 0/8) => (8/7 0/8 4/6 9/2)
(5/4 3/7 9/3 5/5) => (5/4 3/7 9/3 5/5)
(5/2 0/1 6/0 1/8) => (0/1 6/0 1/8 5/2)
(0/4 5/8 6/4 0/2) => (0/4 6/4 0/2 5/8)
(0/3 6/9 5/5 8/5) => (5/5 8/5 0/3 6/9)
(8/5 5/8 1/7 3/3) => (8/5 5/8 1/7 3/3)
答案 1 :(得分:0)
只需使用std :: sort:
template<typename T>
bool MIXED_TOP_BOTTOM(const TopBottom<T>& v1, const TopBottom<T>&v2)
{
if( v1.bottom == v2.top )
return true;
return false;
}
...
std::vector<TopBottom<int> > data;
data.push_back(TopBottom<int>(2, 3));
data.push_back(TopBottom<int>(4, 5));
data.push_back(TopBottom<int>(3, 2));
std::sort(data.begin(), data.end(), MIXED_TOP_BOTTOM<int>);
产生
3/2 2/3 4/5