比较C中的两个数组值

时间:2019-03-22 17:17:28

标签: c search logic

我正在用C语言编写一个学校项目的程序,该程序比较两个数组的值,并根据用户输入的内容给出特定的结果。基本上,我的输出值为两个, correctPosition correctValue

例如,

correctValue 是在 valuesArray 中但不在 inputArray 中正确位置的值;值“ 4”位于 valuesArray 的索引1处,但位于 inputArray 的索引2处。

correctPosition 是一个在 valuesArray inputArray 中相同索引处的值。例如;值“ 3”位于 valuesArray inputArray

的索引1处

如果两个数组之间的x值匹配,则它可以是correctValue或correctPosition。这是一个视觉表示:

data want;
  set have;
  array V varr1-varr3;
  array L[3] _temporary_;

  * save first rows values in temporary array for use in other rows;
  if _n_ = 1 then 
    do index = 1 to dim(V);
      L[index] = V[index];
    end;

  * … for example … ;

  array delta_from_1st [3];  * array statement implicitly creates three new variables that become part of PDV and get output;
  do index = 1 to dim(V);
    delta_from_1st[index] = V[index] - L[index];
  end;      
run;

这是我为此编写的代码:

valuesArray: 2 3 3
------------------
inputArray:  1 2 3
Answer: correctPosition = 1, correctValue = 1.

inputArray:  2 1 3
Answer: correctPosition = 2, correctValue = 0.

inputArray:  2 3 3
Answer: correctPosition = 3, correctValue = 0.

问题在于,对于输入1 2 3,它首先需要1并检入valuesArray却找不到任何内容,因此结果保持为0。然后在第二次迭代中x = 1时,它需要2并检查其是否在数组,而不是正确的索引,因此correctValue计数器变为1。现在在最后一次迭代中,x = 2,它花费3,并经过循环并在索引2处找到FIRST值“ 3”,因为之前从未访问过,因此最终结果将变为correctPosition = 0,correctValue =2。如果我将输入写为2 3 3,那么它可以正常工作,并且输出是correctPosition = 3,correctValue =0。我该如何解决这个问题,我缺少什么在这里?

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

正如我在评论中写道,我建议使用另一种方法。您在算法上有点不整洁,因为从逻辑上讲,positionMatch贡献者的评估涉及将每个输入值与恰好一个对应的其他位置进行比较,而valueMatch贡献者的评估涉及将每个输入值与整个董事会进行比较。

如果分开,这些将更干净。如果您不得不担心处理非常大的电路板,那么将这两个步骤分开可以产生一种解决方案,该解决方案的成本与电路板的尺寸成线性比例,而不是与电路板的平方成线性关系。具体来说,我建议的方法是

  1. 扫描两个数组一次以计算positionMatch计数,并为每个数组构建每个符号出现次数的直方图。

  2. 扫描两个直方图,为每个符号计算两个直方图中该符号的最小数量之和。这样会得出正确数字的总数,但不会区分正确位置的数字和错误位置的数字。

  3. 从(2)中计算出的总和中减去(1)中计算出的positionMatch,得出correctNumber

但是,您应该能够调整当前代码以计算正确的结果。缺少的主要内容是避免使用应该提供valuesArray的{​​{1}}元素来代替提供positionMatch。但这是可以测试的情况。当您检测到匹配项(correctNumber时,根据inputArray[x] == valuesArray[y] && visitedMatch[y] == 0是否存在,您目前仅行使两种选择之一。为了正确计算计数,您应该使用三个:

  • 如果x == y,则递增x == y并从内部循环中断开。 (您也可以标记访问过的职位,但不必这样做。)
  • 否则,如果positionMatch,则不执行任何操作inputArray[y] == valueArray[y]的元素已经或将对valueArray做出贡献,因此不应对positionMatch做出贡献。只需继续下一次内循环迭代即可。
  • 其他增量correctNumber,标记了位置correctNumber,并从内循环中脱离了

或者,您可以调整当前的方法来模拟我建议的方法,而无需实际构建物理直方图。需要进行这些更改:

  • 在外循环中,确定是否递增y。继续以任何一种方式进入内循环。
  • 在内部循环中,忽略是否positionMatch,而是递增x == y并在找到匹配项时标记访问的位置。这是计算和评估直方图的替代方法。
  • 最后,在报告结果之前,从correctNumber中减去positionMatch

答案 1 :(得分:1)

另一种解决方案,比John Bollinger算法更简单:

  • 计算精确匹配数,并指出在两个数组中要忘记的位置

  • 对于 inputArray 中的每个非遗忘位置,请查找 valuesArray

    的非遗忘位置中的值
    • 如果是首次发现 correctNumber 增量,并在 valuesArray 中指出该位置以供忘记
    • 如果找到但不是第一次发现,只需在 valuesArray 中指明该位置即可

实现可以是(因为我现在很懒,我通过预处理器标识符 I 给出了_inputArray的值,请参见编译)

#include <stdio.h>

#define SZ 3

int main() {
  int valuesArray[SZ] = { 2,3,3 };
  int inputArray[SZ] = { I };
  int correctNumber = 0, positionMatch = 0;
  int x, y;
  int forgetValues[SZ] = { 0 }; /* useless to give more value because want 0 for the others */
  int forgetInput[SZ] = { 0 }; /* useless to give more value because want 0 for the others */

  /* count the exact matches */
  for (x = 0; x < SZ; x += 1) {
    if (inputArray[x] == valuesArray[x]) {
      positionMatch += 1;
      printf("correct match %d index %d\n", inputArray[x], x);
      forgetValues[x] = forgetInput[x] = 1; /* do not consider that position later */
    }
  }

  /* count correct values */
  for (x = 0; x < SZ; x += 1) {
    if (!forgetInput[x]) {
      int v = inputArray[x];
      int found = 0;

      for(y = 0; y < SZ; y += 1) {
        if (!forgetValues[y] && (valuesArray[y] == v)) {
          if (!found) {
            /* first time, count it */
            correctNumber += 1;
            found = 1;
            printf("correct value %d index %d / %d\n", v, x, y);
          }
          forgetValues[y] = 1; /* do not consider it later */
        }
      }
    }
  }

  printf("correctPosition = %d, ", positionMatch);
  printf("correctValues = %d\n", correctNumber);
  return 0;
}

编译和执行;

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall -DI=1,2,3 c.c
pi@raspberrypi:/tmp $ ./a.out
correct match 3 index 2
correct value 2 index 1 / 0
correctPosition = 1, correctValues = 1
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall -DI=2,1,3 c.c
pi@raspberrypi:/tmp $ ./a.out
correct match 2 index 0
correct match 3 index 2
correctPosition = 2, correctValues = 0
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall -DI=2,3,3 c.c
pi@raspberrypi:/tmp $ ./a.out
correct match 2 index 0
correct match 3 index 1
correct match 3 index 2
correctPosition = 3, correctValues = 0