c++ - 在 C++ 中使用多重函数合并两个链表

标签 c++ list linked-list find-occurrences

我需要通过使用“多重性”定义对从输入传递的两个无序多重集进行并集:元素的多重性,也称为绝对频率,是元素“x”在无序中出现的次数多重集's'。 在 multiSetUnion 中,元素的多重性是其在两个多重集中的多重性的最大值。

我已经正确实现了 int multiplicity(const Elem e, const MultiSet& s) 函数(返回多重集中出现的次数)。

多重集是单链表。

这是我想出的算法:

for as long as the first list isn't empty
   if elem of the first list (multiset) is not in the second list (multiset)
      add elem in unionlist
   if elem of the first list (multiset) is in the second list (multiset)
      if multiplicity of elem is bigger in the first list than in the second one
         add elem in unionlist as many times as its multiplicity in list1
      if multiplicity of elem is bigger in the second list than in the first one
         add elem in unionlist as many times as its multiplicity in list2  
analyze the second element of the first list 

这是我的算法实现,但是当两个列表都不为空并且我不知道为什么时它会给我错误:

MultiSet multiset::multiSetUnion(const MultiSet& s1, const MultiSet& s2)
{
    if (isEmpty(s1) && isEmpty(s2))
        return emptySet;
    if (isEmpty(s1) && !isEmpty(s2))
        return s2;
    if (!isEmpty(s1) && isEmpty(s2))
        return s1;
    MultiSet s3 = emptySet;    
    MultiSet aux2 = s2;            //THE FUNCTION DOESN'T WORK FROM HERE ON
    for (MultiSet aux1 = s1; !isEmpty(aux1); aux1 = aux1->next) { 
        if (!isIn(aux1->elem, aux2))
            insertElemS(aux1->elem, s3);
        if (isIn(aux1->elem, aux2)) {
            if (multiplicity(aux1->elem, aux1) > multiplicity(aux1->elem, aux2)) {
                for (int n = 0; n < multiplicity(aux1->elem, aux1); ++n)
                    insertElemS(aux1->elem, s3);
            }
            else {
                for (int m = 0; m < multiplicity(aux1->elem, aux2); ++m)
                    insertElemS(aux1->elem, s3);
            }
        }
    }
    return s3;
}

有人能指出我哪里做错了吗?我是否忘记了算法中的某些内容,或者这是一个实现问题?

编辑:这是我如何实现函数 IsIn(const Elem x, MultiSet& s) 和 multiplicity(const Elem e, MultiSet& s):

bool isIn(const Elem x, MultiSet& s) {
    if (s->elem == x) return true;
    while (!isEmpty(s)) {
        if (s->elem!=x)
            s = s->next;
        else    return true;
    }
    return false;
}

int multiset::multiplicity(const Elem e, const MultiSet& s)
{
    if (isEmpty(s))    return 0;
    int count = 0;
    MultiSet aux = s;
    while (!isEmpty(aux)) {
        if (aux->elem==e) {
            ++count;
        }
        aux = aux->next;
    }
    return count;
}

不幸的是,我不能使用 vector 库(或任何 STL 库)。 我提出的算法是解决方案的一半(我遇到问题的部分)。 我没有收到任何具体错误,但程序只是停滞了(它应该打印第一个、第二个和两个多重集的并集——打印函数是正确的,直接在 main 中调用;至于现在我只得到当一个或两个多集为空时正确输出)并返回:“进程返回 -1073741819”(我目前正在 Windows 上调试)。

最佳答案

考虑以下示例:

MultiSet s1({7, 7});
MultiSet s2({5});

如果您现在遍历 s1:

1st iteration:        7    7
                      ^
                     aux1

2nd iteration:        7    7
                           ^
                          aux1

如果 s1 中有多个相等的元素,您会不止一次地发现它们,最终导致添加多重性的平方(或者两个多重性的乘积,如果 s2 中的一个更大) .

另一方面,由于 5 不包含在 s1 中,您也不会尝试在 s2 中查找它——尽管如此,它仍然存在。 .

要解决第一个问题,您需要检查当前元素是否已包含在 s3 中,如果是,则跳过它。

要解决第二个问题,您还需要遍历 s2,添加所有尚未包含在 s3 中的元素。

尽管如此,最终结果的性能会很差(应该介于 O(n²)O(n³) 之间,而不是后者).不幸的是,您选择了一种数据结构(一个简单的单链表——显然是未排序的!),它对你想要的操作提供的支持很差——尤其是你选择的算法。

如果您对两个列表进行排序,则可以创建一个具有线性运行时间的算法。它的工作方式与合并排序中的合并步骤类似:

while(elements available in both lists):
    if(left element < right element):
        append left element to s3
        advance left
    else
        append right element to s3
        if(left element == right element):
            advance left // (too! -> avoid inserting sum of multiplicities)
        advance right
append all elements remaining in left
append all elements remaining in right
// actually, only in one of left and right, there can be elements left
// but you don't know in which one...

在插入期间保持列表排序非常简单:

while(current element < new element):
    advance
insert before current element // (or at end, if no current left any more)

但是,当您直接公开列表的节点时,您总是处于插入不会从头元素开始的危险之中——并且您的排序顺序可能会被破坏。

你应该适当封装:

  • 将您当前的 MultiSet 重命名为 e。 G。 'Node' 并创建一个新类 MultiSet
  • 使节点类成为新集合类的嵌套类。
  • 列表的所有修饰符只能是集合类的成员。
  • 您可以公开节点类,但用户不能修改它。然后它将只是作为一种迭代器。

关于c++ - 在 C++ 中使用多重函数合并两个链表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56597222/

相关文章:

c++ - 返工 make 文件以将 obj 放入不同的位置

Python:计算列表中每对值的值

c - 如何在c中的链表内创建链表

css - 列表元素内 float 元素的技巧

r - as.list.Date(R 编程语言)中的潜在错误

rest - Neo4j - 如何通过 Cypher over REST 并行插入链表?

c - 在C中的特定位置添加链表中的节点

c++ - 模板类的困难

c++ - Qt 4.8 - 更新 QGraphicsScene 时显示 “loading” 动画

OO 中的 C++ 隐式转换