【问题标题】:Comparing multiple arrays to find their similarity in C比较多个数组以找到它们在 C 中的相似性
【发布时间】:2022-01-10 18:44:13
【问题描述】:

我是 C 的初学者,我正在尝试找出一种解决方案来比较多个数组并根据哪些元素相同来找出它们的相似度百分比。

例如,我们有以下名为 Library 的结构体,其中填充了 Articles:

typedef struct
{
  int articleId;
  int count;
  int bibliography[3];
} Article;

typedef struct
{
  Article **articles;
  int count;
  int allocated;
} Library;

一个已填充的库的示例如下:

articleId   bibliography
000         [222,111]
111         [333,222]
222         [111]
333         [222,111]

我的目标是找出所有文章及其参考书目之间的相似性,无论它们的顺序如何。换句话说,哪些文章引用了相同的文章?

我所说的相似性是什么意思:当比较两个数组时,我们检查另一个数组中具有相等整数的整数的数量。然后我们把这个数字除以更大的数组的长度,得到我们的相似度。

例如,000 和 333 的相似度为 100%,222 和 333 的相似度为 50%,111 和 222 的相似度为 0%,以此类推。

我特别有麻烦,因为数组都有不同的长度。有没有人有任何想法?我的方法将包括嵌套 for 循环,但我不确定这是否是正确的方向。

我尝试在我的代码中构造算法:

    double citationSimilarity (Library *lib)
{
    int currentCitation[3];
    int comparingCitation[3];
    int[] similarityResults;

    int similar = 0; //amount of similar citations
    double similarity = 0;
    int total = 0; //highest total amount of citations

    for(int i = 0; i < lib->count; i ++){
      for(int j = 1; j < lib->count; j ++){
              similar = 0;
      similarity = 0;
        for(int k = 0; k < lib->articles[i]->count; k ++){
          for(int l = 0; l < lib->articles[j]->count; l ++){
            currentCitation[k] = lib->articles[i]->bibliography[k];
            comparingCitation[l] = lib->articles[j]->bibliography[l];
            if(lib->articles[i]->articleId != lib->articles[j]->articleId){
            if(currentCitation[k] == comparingCitation[l]){
                similar++;
                if(similar != 0){
                    similarity = (double)similar / (double)getLargerBibliography(lib->articles[j]->count, lib->articles[i]->count);
                }
              printf ("Great success! %d and %d have the similarity %lf \n",lib->articles[i]->articleId, lib->articles[j]->articleId, similarity);
            }
            }
          }
        }
      }
   }
}



int getLargerBibliography (int bib_a, int bib_b)
{

int max;
int min;


  if (bib_a >= bib_b)
  {
    max = bib_a;
    min = bib_b;
  }
  else
  {
    max = bib_b;
    min = bib_a;
  }

  return max;

}

【问题讨论】:

  • 您既没有对“相似”的含义给出可行的定义(即 222 和 333 是 100% 相似还是 50% 或其他什么,更重要的是,为什么?),您也没有发布任何证据表明您自己正在努力解决这个问题。
  • 也许你想计算对的edit distance。例如,您可以计算Levenshtein distance 或其Longest Common Subsequence 的长度(不要与最长公共子串混淆)。
  • 您好,感谢您的cmets。我试图克服的第一个困难是如何准确地比较多个不同长度的数组?那已经对我有很大帮助了。我试图在问题中更仔细地定义我的问题。

标签: arrays c loops compare


【解决方案1】:

使用合并比较两个数组

  1. 对第一个数组的元素进行排序(以下称为array1)。
  2. 对第二个数组(以下称为array2)的元素进行排序。
  3. 将i 设置为0。
  4. 将j 设置为0。
  5. 将count 设置为0。
  6. 虽然i 小于array1 中的元素数,并且
    而j 小于array2 中的元素数,
    1. 如果array1[i]小于array2[j],
      1. 递增i。
    2. 否则,
      1. 如果array1[i]大于array2[j],
        1. 递增j。
      2. 否则,
        1. 递增count。
        2. 递增i。
        3. 递增j。
  7. 找出array1的长度和array2的长度中的最大值。
  8. 将count 除以两个数组长度中的最大值。

这支持数组中的重复元素。

复杂性因使用的排序算法而异。使用通用排序算法,比较每一对需要 O(1) 额外的内存和 O(N log N) 时间。但是,如果值是真正的整数,则可以实现 O(N) 排序,但会消耗一些内存。无论哪种方式,每个数组只需要执行一次排序,而不是每次比较时执行一次,因此排序成本是摊销的。


使用集差比较两个数组

这是一个 O(N) 内存和 O(N) 时间的解决方案,甚至适用于非整数键。循环的每次通过都更昂贵,因此可能需要很大的 N 才能获得任何收益。

  1. 创建一个集合。 (可以使用关联数组。)
  2. 对于其中一个数组中的每个值,
    1. 将其添加到集合中。
      (如果使用关联数组,则使用值作为键,并使用任何值作为值。)
  3. 对于另一个数组中的每个值,
    1. 如果值在先前创建的集合中,
      1. 计数加一。
  4. 求第一个数组的长度。
  5. 求第二个数组的长度。
  6. 找出两个数组长度中最大的一个。
  7. 将计数除以两个数组长度中的最大值。

由于它不会破坏集合,您可以预先为每个数组创建并在比较不同的数组对时重复使用它!

这不支持重复元素,但可以很简单地适应。

【讨论】:

  • 用更简单的算法更新了我的答案。
  • 非常感谢您抽出宝贵时间!我确实离我的目标更近了。我已经用我当前的代码更新了我的问题
  • 你的版本比我的慢得多,而且数组越长,它就越慢。考虑 100 个元素的数组。我的排序需要大约 208 次比较,数组比较最多需要 200 次比较。你的需要10,000。这意味着对于 100 个元素的数组,我的速度大约快 25 倍。从角度来看,这就是 2 分钟和 5 秒之间的差异。
猜你喜欢
  • 1970-01-01
  • 2017-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-29
  • 2020-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多