我需要使用以下接口实现mergesort算法:
template <typename T, typename Comp>
void mergesort(T begin, T end, Comp comp);
其中开始和结束 - 类型为T,comp的某个容器的元素的迭代器是比较元素的函数,这些元素存储在容器中。和
template <typename T, typename Comp>
void merge(T beginLeft, T endLeft, T beginRight, T endRight,
T beginResult, Comp comp);
是合并两个已排序容器( beginLeft 和 endLeft - 第一个容器的迭代器, beginRight 和 endRight <的功能/ em> - 第二个),结果应该是新合并容器 beginResult 的开头的迭代器。
应该看起来像this。
我为合并排序编写了递归函数,它调用了合并的过程。
template <typename T, typename Comp>
void mergesort(T begin, T end, Comp comp)
{
if (begin == std::prev(end))
{
return;
}
T middle = begin + std::distance(begin, end) / 2;
mergesort<T, Comp>(begin, middle, comp);
mergesort<T, Comp>(middle, end, comp);
merge<T, Comp>(begin, middle, middle, end, begin, comp);
}
template <typename T, typename Comp>
void merge(T beginLeft, T endLeft, T beginRight, T endRight,
T beginResult, Comp comp)
{
while (beginLeft != endLeft && beginRight != endRight)
{
if (comp(*beginLeft, *beginRight))
{
*beginResult = *beginLeft;
++beginResult;
++beginLeft;
}
else
{
*beginResult = *beginRight;
++beginResult;
++beginRight;
}
}
while (beginLeft != endLeft)
{
*beginResult = *beginLeft;
++beginResult;
++beginLeft;
}
while (beginRight != endRight)
{
*beginResult = *beginRight;
++beginResult;
++beginRight;
}
}
函数 merge 正常工作,但我不太明白, mergesort 应该如何工作。我应该传递什么参数
merge<T, Comp>(begin, middle, middle, end, /?...?/, comp);
如果我在那里只传递开始,那么排序的结果是不正确的。或者我应该通过一些临时容器。但是,如果我只有迭代器的类型并且不知道元素的类型,我该如何创建呢?
我将非常感谢你的帮助。谢谢!
- ADDED ---
合并示例:
vector<int> vec1;
vector<int> vec2;
vector<int> vec3(6);
vec1.push_back(1);
vec1.push_back(3);
vec1.push_back(5);
vec2.push_back(2);
vec2.push_back(4);
vec2.push_back(6);
merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), vec3.begin(), std::less<int>());
for (int i = 0; i < vec3.size(); ++i)
{
std::cout << vec3[i] << std::endl;
}
输出为:1 2 3 4 5 6
答案 0 :(得分:2)
您肯定无法使用begin
存储结果。您仍在阅读begin
并合并,因此通过写入,您将覆盖可能仍未读取的数据。
您需要临时内存才能将结果写入,然后复制回原始内存。内存可以是任何类型,只要你可以通过它获得迭代器。说一句std::vector
。
但是存在一个根本问题。您在merge
中将所有五个迭代器的类型都设置为T
,但至少beginResult
的类型应该是可能不同的迭代器。否则,正如您所观察到的,您无法知道要使用的临时容器。
正如您自己链接的那样,std::merge
的模板为left
,right
和result
迭代器提供了不同的迭代器类型。
注意:要分配临时内存,您需要知道T
是迭代器的元素类型。这只是由T::value_type
完成的。请参阅here。
答案 1 :(得分:0)
这样的事情应该有效:
template<class BiDirIt, class Compare = std::less<typename std::iterator_traits<BiDirIt>::value_type>>
void merge_sort(BiDirIt first, BiDirIt last, Compare cmp = Compare())
{
auto const N = std::distance(first, last);
if (N < 2) return;
auto middle = first + N / 2;
merge_sort(first, middle, cmp);
merge_sort(middle, last, cmp);
std::inplace_merge(first, middle, last, cmp);
}
答案 2 :(得分:0)
您可以这样创建矢量:
init
在辅助函数中,然后调用您的排序例程:
std::vector<std::iterator_traits<T>::value_type> result;
然后,一旦您的函数返回结果,您可以将结果复制到用户提供的迭代器表示的向量。