合并链接列表时输出错误

时间:2014-10-28 23:38:46

标签: c++ data-structures linked-list

目前,我有以下函数来合并两个类型为mylist的已排序链接列表。目前,还有一些我到目前为止无法查明和修复的错误。该函数基本上应该做的是,让我们说A = 1 2 3B = 3 4 5。然后,当我合并两者时(假设两个列表都已排序),A将变为1 2 3 3 4 5B将变为null

目前,例如,当我尝试A = 1 2 3B = 4 5 6并合并两者时,A变为6B变为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 = 4A = 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;

}

2 个答案:

答案 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());
}