gpt4 book ai didi

c++ - 在 C++ 中使用 std::algorithm 输出 `std::multiset` 的唯一元素及其频率(无循环)

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:53:11 24 4
gpt4 key购买 nike

我在 C++ 中有以下 multiset:

template<class T>
class CompareWords {
public:
bool operator()(T s1, T s2)
{
if (s1.length() == s2.length())
{
return ( s1 < s2 );
}
else return ( s1.length() < s2.length() );
}
};
typedef multiset<string, CompareWords<string>> mySet;
typedef std::multiset<string,CompareWords<string>>::iterator mySetItr;
mySet mWords;

我想在集合中打印一次 std::string 类型的每个唯一元素,然后在我想打印的元素旁边打印它在列表中出现的次数(频率),就像你一样可以看到仿函数“CompareWord”保持集合排序。

提出解决方案here ,但这不是我需要的,因为我正在寻找不使用 (while,for,do while) 的解决方案。

我知道我可以使用这个:

//gives a pointer to the first and last range or repeated element "word"
auto p = mWords.equal_range(word);
// compute the distance between the iterators that bound the range AKA frequency
int count = static_cast<int>(std::distance(p.first, p.second));

但我不能完全想出一个没有循环的解决方案?

最佳答案

与其他解决方案不同的是,它只遍历列表一次。这很重要,因为遍历像 std::multimap 这样的结构是相当高的开销(节点是不同的分配)。

没有明确的循环,但尾端递归将被优化为一个循环,我调用一个将运行循环的算法。

template<class Iterator, class Clumps, class Compare>
void produce_clumps( Iterator begin, Iterator end, Clumps&& clumps, Compare&& compare) {
if (begin==end) return; // do nothing for nothing
typedef decltype(*begin) value_type_ref;
// We know runs are at least 1 long, so don't bother comparing the first time.
// Generally, advancing will have a cost similar to comparing. If comparing is much
// more expensive than advancing, then this is sub optimal:
std::size_t count = 1;
Iterator run_end = std::find_if(
std::next(begin), end,
[&]( value_type_ref v ){
if (!compare(*begin, v)) {
++count;
return false;
}
return true;
}
);
// call our clumps callback:
clumps( begin, run_end, count );
// tail end recurse:
return produce_clumps( std::move(run_end), std::move(end), std::forward<Clumps>(clumps), std::forward<Compare>(compare) );
}

以上是一个比较通用的算法。这是它的用法:

int main() {
typedef std::multiset<std::string> mySet;
typedef std::multiset<std::string>::iterator mySetItr;

mySet mWords { "A", "A", "B" };

produce_clumps( mWords.begin(), mWords.end(),
[]( mySetItr run_start, mySetItr /* run_end -- unused */, std::size_t count )
{
std::cout << "Word [" << *run_start << "] occurs " << count << " times\n";
},
CompareWords<std::string>{}
);
}

live example

迭代器必须引用排序序列(关于比较器),然后 block 将连同它们的长度一起传递给第三个参数。

多重集中的每个元素都将使用上述算法恰好访问一次(作为比较函数的右侧参数)。 block 的每个开始都将作为左侧参数(包括长度为 1 的 block )额外访问( block 的长度)次。将恰好执行 N 次迭代器增量,并且不超过 N+C+1 次迭代器比较(N=元素数,C= block 数)。

关于c++ - 在 C++ 中使用 std::algorithm 输出 `std::multiset` 的唯一元素及其频率(无循环),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25471569/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com