MergeSort.使用迭代程序实现

MergeSort. Implementation with Iterators

本文关键字:程序 实现 迭代 MergeSort      更新时间:2023-10-16

我需要用以下接口实现mergesort的算法:

template <typename T, typename Comp>
void mergesort(T begin, T end, Comp comp);

其中beginend-某个T类型容器的元素的迭代器,comp-是比较存储在容器中的元素的函数。和

template <typename T, typename Comp>
void merge(T beginLeft, T endLeft, T beginRight, T endRight,
T beginResult, Comp comp);

是合并两个排序容器的函数(beginLeftendLeft-第一个容器的迭代器,beginRightendRight-第二个),结果应该是新合并容器beginResult的开始迭代器。

它应该是这样的。

我已经为合并排序编写了递归函数,它调用合并过程。

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工作正常,但我不太明白mergesor应该如何工作。我应该向提出什么论点

merge<T, Comp>(begin, middle, middle, end, /?...?/, comp);

如果我只通过开始,那么排序的结果是不正确的。或者我应该把一些临时集装箱送到那里。但是,如果我只有迭代器的类型,而不知道元素的类型,我该如何创建它呢?

我将感谢你的帮助。非常感谢。

--已添加--

合并示例:

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

当然不能使用begin来存储结果。您仍在读取begin并进行合并,因此通过向其写入,您将覆盖可能仍未读取的数据。

您需要临时内存来将结果写入其中,然后将其复制回原始内存。内存可以是任何类型,只要你能在上面找到迭代器。比如说std::vector

不过,这是一个根本问题。merge中所有五个迭代器的类型都是T,但至少beginResult的类型应该是可能不同的迭代器。否则,正如您所观察到的,您就不知道要使用什么临时容器。

由于您已经链接了自己,std::merge的模板对于leftrightresult迭代器具有不同的迭代器类型。


注意:要分配临时内存,您需要知道T是其迭代器的元素类型。这只是由T::value_type完成的。请参见此处。

这样的东西应该可以工作:

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);
}

您可以这样创建向量:

std::vector<std::iterator_traits<T>::value_type> result;

在助手函数中,然后调用您的排序例程:

merge_sort(first, last, result.begin());

然后,一旦函数返回结果,就可以将结果复制到由用户提供的迭代器表示的向量中。