【问题标题】:Efficient way to match two arrays匹配两个数组的有效方法
【发布时间】:2016-12-02 19:12:53
【问题描述】:

我有 2 个数组,一个是输入 pins names,另一个是他们的 actual numbers

const char *pins[]={"d1","d2","d3","d4","d5","o1","o2","o3","o4"};
const int pinsNumbers[9]={1,2,19,4,14,6,12,15,17};

当我得到一个输入 "d3" 时,我想找到对应的 - 19

  1. 有没有更有效的方法来保存这些“匹配”?
  2. 如何使用输入循环遍历引脚阵列并尽可能高效地找到匹配项?

【问题讨论】:

  • 比什么更有效的方法?你还没有实现任何东西。
  • 有效的保存方法。我也想知道如何以一种好的方式实现它。
  • 使用地图而不是 2 个数组。
  • 没有实际限制就没有“有效的解决方案”。 pins 数组有多长?您多久会查询一次密码?
  • 正如@m0skit0 所写,您需要一个从字符串到整数的映射。它通常使用哈希表(平均为O(1))或二分查找(平均为O(logN))来完成。但如果它是一个相当短的数组,您可以简单地遍历 pins 数组并找到索引。

标签: c arrays search binary-search


【解决方案1】:

如果阵列引脚是有序的(否则您可以使用例如qsort对其进行排序)然后您可以使用演示程序中显示的以下方法

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int cmp( const void *a, const void *b )
{
    const char *lhs = *( const char ** )a;
    const char *rhs = *( const char ** )b;

    return strcmp( lhs, rhs );
}

int main( void ) 
{
    const char *pins[]      = { "d1", "d2", "d3", "d4", "d5", "o1", "o2", "o3", "o4" };
    const int pinsNumbers[] = { 1, 2, 19, 4, 14, 6, 12, 15, 17 };

    const char *key = "d3";

    const char **p = bsearch( &key, pins, sizeof( pins ) / sizeof( *pins ), sizeof( const char * ), cmp );

    if ( p ) printf( "%d\n", pinsNumbers[p - pins] );

    return 0;
}

程序输出是

19

【讨论】:

    【解决方案2】:

    您可以像这样构造数据来模拟 C++ 映射:

    struct My_pair {
        const char* pin;
        int number;
    };
    
    const My_pair pairs[] = {
        {"d1", 1},
        {"d2", 2},
        ...
    };
    

    【讨论】:

    • 这仍然是O(N)
    • @GillBates 但至少数据结构比 OP 更不容易出错。
    • @GillBates 随时改进 :)
    • 那么这与仅循环两个数组并从一个数组中获取索引以在另一个数组中使用有什么不同?
    • @Curnelious 它效率不高,但是在您的问题中使用 2 个数组很容易出错。想象一下,您添加另一个引脚“d6”,然后您必须在正确的位置添加 pinsNumbers 数组中的引脚号,否则一切都会混淆。使用struct 解决方案,您只需在pairs 数组的初始化列表中添加另一个条目,例如{"d6", 18}
    【解决方案3】:

    尽可能简单快捷。如果您将使用两个连续的符号(例如 'a''b') - 您可以在下面的代码中计算并检查它作为组内的偏移量。 Ideone online executable code.

    #include <stdio.h>
    
    #define D1_VAL  1
    #define D2_VAL  2
    #define D3_VAL  19
    #define D4_VAL  4
    #define D5_VAL  14
    
    #define D_CNT   5
    #define D_OFS   0
    
    #define O1_VAL  6
    #define O2_VAL  12
    #define O3_VAL  15
    #define O4_VAL  17
    
    #define O_CNT   4
    #define O_OFS   D_CNT
    
    #define PIN_NUM_CNT     (D_CNT+O_CNT)
    #define PIN_GRP_CNT     2
    
    enum decode_res_e {
        DECODE_OK = 0,
        DECODE_ERR = !DECODE_OK
    };
    
    int const pin_num_tab[PIN_NUM_CNT] = {
        D1_VAL, D2_VAL, D3_VAL, D4_VAL, D5_VAL,
        O1_VAL, O2_VAL, O3_VAL, O4_VAL,
    };
    
    typedef struct { unsigned char chr, ofs, cnt; } pin_grp_t;
    
    pin_grp_t const pin_grp_tab[2] = {
        { .chr = 'd', .ofs = D_OFS, .cnt = D_CNT },
        { .chr = 'o', .ofs = O_OFS, .cnt = O_CNT },
    };
    
    int pin_to_num(int * num, unsigned char * pin)
    {
        unsigned char i = 0, tmp = pin[1] - 0x31;
        while (i < PIN_GRP_CNT) {
            if (pin_grp_tab[i].chr == pin[0]) {
                if (tmp >= pin_grp_tab[i].cnt) break;
                *num = pin_num_tab[pin_grp_tab[i].ofs + tmp];
                return DECODE_OK;
            }
            i++;
        }
        return DECODE_ERR;
    }
    
    int main(void) 
    {
        int num;
        unsigned char const inp[] = "d3";
        printf("\f%s is ",inp);
        if (pin_to_num(&num,inp) == DECODE_OK) {
            printf("%d\r\n",num);
        } else {
            printf("err\r\n");
        }
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      您可以使用binary search...只要上面的数组已排序。

      【讨论】:

      • 示例中显然没有排序。
      • @m0skit0:OP 可能不关心实际元素的索引,只关心映射。
      • @m0skit0 它们在 OP 的问题中排序,即使不是,OP 也可以对它们进行排序。
      • 这与其说是答案,不如说是评论。
      • 谢谢,但我一开始无法发表评论,因为我没有 50 个声望 :(
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-15
      • 2012-03-20
      • 1970-01-01
      • 2019-09-02
      • 1970-01-01
      相关资源
      最近更新 更多