我正在尝试编写一种以交替方式合并双向链表的方法。因此,如果我们有两个int列表(0,1,2,3)和(4,5,6),我们只有一个(0,4,1,5,2,6,3)的最终列表。每个列表都有一个head,一个tail,一个next和一个prev指针。
它试图弄清楚从哪里开始或如何起作用,这让我很伤心。我试图在纸上追踪它,但没有进展。
有人能引导我朝正确的方向前进吗?什么是“描绘”或计划它的好方法,因为我甚至不知道从哪里开始。
答案 0 :(得分:2)
创建第三个空列表(称为“结果列表”)。
循环,其中一个列表中仍有剩余元素:
使用C ++ std::list
容器看起来像这样(这个算法略有不同,因为在主循环之外处理“额外”元素更容易一些):
template <typename T>
std::list<T> merge_lists(const std::list<T>& a, const std::list<T>& b)
{
std::list<T> r;
while (!a.empty() && !b.empty())
{
r.splice(r.end(), a, a.begin());
r.splice(r.end(), b, b.begin());
}
r.splice(r.end(), a, a.begin(), a.end());
r.splice(r.end(), b, b.begin(), b.end());
return r;
}
答案 1 :(得分:1)
采取以下步骤,沿着每条线向下,用箭头表示移动。例如,在第一步之后,0已从A中删除,最终只有一项:
List: A final B 0 --> 0 4 <-- 4 1 --> 1 5 <-- 5 2 --> 2 6 <-- 6 3 --> 3
std :: list的一个例子:
std::list<int> A, B;
A.push_back(0); A.push_back(1); A.push_back(2); A.push_back(3);
B.push_back(4); A.push_back(5); A.push_back(6);
std::list<int> final;
for (std::list<int>::iterator a, b;
(a = A.begin()) != A.end() and (b = B.begin()) != B.end();)
{
final.splice(final.end(), A, a);
final.splice(final.end(), B, b);
}
for (std::list<int>::iterator x; (x = A.begin()) != A.end();) {
final.splice(final.end(), A, x);
}
for (std::list<int>::iterator x; (x = B.begin()) != B.end();) {
final.splice(final.end(), B, x);
}
提取splice可以清除一些东西,但更重要的是,您应该能够为您的(显然是自定义的)列表类型编写下面的move_back,然后使用它与std :: list:
// Moves pos from source into dest; returns what was the position after
// pos in the source list.
template<class List>
typename List::iterator move_back(List &dest, List &source,
typename List::iterator pos)
{
typename List::iterator next = pos;
++next;
dest.splice(dest.end(), source, pos);
return next;
}
template<class List>
void move_back(List &dest, List &source) {
dest.splice(dest.end(), source, source.begin(), source.end());
}
void example() {
std::list<int> A, B;
A.push_back(0); A.push_back(1); A.push_back(2); A.push_back(3);
B.push_back(4); A.push_back(5); A.push_back(6);
std::list<int> final;
for (std::list<int>::iterator a = A.begin(), b = B.end();
a != A.end() and b != B.end();)
{
a = move_back(final, A, a);
b = move_back(final, B, b);
}
move_back(final, A);
move_back(final, B);
}
答案 2 :(得分:1)
如果您不想更改输入列表,则可以复制第一个列表,然后从其他位置的第二个列表中插入新列表元素。
#include <iostream>
#include <list>
#include <iterator>
int main(int argc, char* argv[])
{
typedef std::list<int> list;
list a; // and fill it ...
list b; // and fill that too ...
list c(a);
for( list::iterator p(++c.begin()), i(b.begin()); i != b.end(); ++i ) {
p = ++ ++ c.insert(p, *i);
}
return 0;
}
同样令人感兴趣的是Boost Zip Iterator。它允许您同时迭代两个或更多容器。因此,您可以创建一个空列表,并行迭代两个输入列表,并将每个列表中的一个元素插入到新列表中。