目前,我有以下函数来合并两个类型为mylist
的已排序链接列表。目前,还有一些我到目前为止无法查明和修复的错误。该函数基本上应该做的是,让我们说A = 1 2 3
和B = 3 4 5
。然后,当我合并两者时(假设两个列表都已排序),A
将变为1 2 3 3 4 5
,B
将变为null
。
目前,例如,当我尝试A = 1 2 3
和B = 4 5 6
并合并两者时,A
变为6
,B
变为4
}。我知道算法存在问题,但我还没能确定和修复。我是编程新手。任何帮助将不胜感激!
void mylist::merge(mylist& b)
{
if (!this->isSorted() || !b.isSorted())
cout << "error" << endl;
Node* ptr1 = b.head;
Node* prev_a = NULL;
Node* curr_a = head;
Node* curr_b = ptr1;
while (curr_b) {
if (curr_a && head < ptr1) {
prev_a=curr_a;
curr_a = curr_a->next;
}
else {
Node* b_next = curr_b->next;
curr_b->next = curr_a;
if (prev_a) prev_a->next = curr_b;
else head = curr_b; // curr_b is first element in 'a'
if (curr_a) {
prev_a = curr_a;
curr_a = curr_a->next;
}
curr_b = b_next;
}
}
return;
}
编辑:
我已经提到了以下更改,但在合并A = 6
&amp;之后我仍然得到B = 4
和A = 1 2 3
B = 4 5 6
。
void mylist::merge(mylist& b)
{
if (!this->isSorted() || !b.isSorted())
cout << "error" << endl;
Node* ptr1 = b.head;
Node* prev_a = NULL;
Node* curr_a = head;
Node* curr_b = ptr1;
while (curr_b) {
if (curr_a && head->key < ptr1->key) {
prev_a=curr_a;
curr_a = curr_a->next;
}
else {
Node* b_next = curr_b->next;
curr_b->next = curr_a;
if (prev_a) prev_a->next = curr_b;
else head = curr_b; // curr_b is first element in 'a'
prev_a = curr_a;
curr_b = b_next;
}
return;
}
答案 0 :(得分:3)
1)排序问题:
在您的指示中
if (curr_a && head < ptr1) { // argh !!!
你比较两个指向Node
的指针(即它们的地址),而不是指向的值。
2)极端情况(适用于您的测试数据):
如果列表b
的第一个元素大于列表a
的任何元素(假设您已更正问题#1),那么您将循环直到curr_a
为空,没有设置prev_a
。然后,您将在a的头部插入b的元素(以相反的顺序)
3)首先在列表a中间合并:
在正常合并中,您可以遍历列表a
,直到列表b
的第一个元素小于a
的元素。目前仍未设置prev_a
。因此,您将b
的当前元素的下一个元素连接到a
的当前元素(这是正常的),但是,当prev_a
为NULL时,您将将a
的头部连接到b
的当前元素,从而在a
中放弃当前元素之前的整个元素链。
解决方案的步骤:
如果是由老师给出的作业:
while (curr_b) {
if (curr_a && curr_a->key < curr_b->key) { // assuming data is stored in the node and has a comparator defined
prev_a = curr_a; // keep track of it (WAS MISSING)
curr_a = curr_a->next;
}
else {
Node* b_next = curr_b->next;
curr_b->next = curr_a;
if (prev_a) prev_a->next = curr_b;
else head = curr_b;
prev_a = curr_b; // THE ELEMENT you've inserted is now prev_a
// curr_a SHALL not change since the next element of b can also be smaller than it
curr_b = b_next;
}
}
如果是实际代码,您应该考虑标准<list>
容器及其现有的merge()
函数; - )
编辑: 我刚刚意识到还有另一个问题,并且还更新了上面循环中的else部分。而且我意识到我是如此专注于密钥比较,我没有注意到使用了错误的指针,因此它在所有测试用例中都没有成功!
答案 1 :(得分:0)
比较'头&lt; ptr1'毫无意义。这些是指针,而不是价值观。
ptr1似乎与curr_b
多余你似乎从寻找A的尾巴开始。为什么不把它作为一个独立的功能呢?
继续这种分而治之的方法,我会创建测试列表是否为空的函数,从列表中弹出头部返回它弹出的内容,以及一个向末尾附加内容的函数。那么你的最终答案是:
mylist::merge(mylist &b) {
while (!b.empty())
push_back(b.pop_front());
}