如何检查C中的值是哪个数组?

时间:2016-12-15 12:37:51

标签: c arrays algorithm

假设我有三个阵列:

const uint8_t arr_1[] = {1, 4, 53 , 209};
const uint8_t arr_2[] = {54, 56, 90, 100};
const uint8_t arr_3[] = {6, 7, 8, 9, 10};

如何有效地检查给定值uint8_t val是否在其中一个数组中,如果是,则在哪一个数组中。一种方法是循环遍历所有数组,直到找到该值,但这不是非常有效。该解决方案需要扩展到更多阵列。如有必要,可以对每个数组中的值进行排序。

4 个答案:

答案 0 :(得分:3)

我将在答案中总结我对您帖子的评论。希望它对某人有用。

如果你为每个数组保持一个指针及其值范围,比如说:

struct arr_meta_data {
  const uint8_t *p_arr;
  uint8_t min;
  uint8_t max;
};

然后,您可以根据范围定义的部分顺序对struct arr_meta_data数组进行排序。

查找值是一个两步过程

  1. struct arr_meta_data数组中进行二进制搜索,以查找值可以所在的第一个数组。 O(log M)其中M是您拥有的阵列数。

  2. 在值在范围内的每个数组中前进和二进制搜索。到达数值小于最小值的数组后,您可以停止并返回找不到该值的数据。

答案 1 :(得分:2)

受到@StoryTeller的启发,我尝试使用他的方法。

我只考虑给出的3个数组构建了代码:

const uint8_t arr_1[] = {1, 4, 53 , 209};
const uint8_t arr_2[] = {54, 56, 90, 100};
const uint8_t arr_3[] = {6, 7, 8, 9, 10};

因为我不知道如何给出数据。这个想法是正确的,我假设数组总是排序。如果将来不是这种情况,那么您可以事先使用qsort对数组进行排序,平均运行时间 O(nlogn)

在下面的代码中,我使用了:

  1. stdlib.h提供的内置bsearch功能,以省去编写自己的功能。使用此二进制搜索工具仍然允许 O(logn)搜索时间,这比线性搜索消耗的 O(n)时间要好得多。
  2. 结构设置数组,用于收集有关每个数组的特定信息,例如检查[min, max]范围,以及跳过与搜索键值不在同一范围内的数组

    设定:

    typedef struct {
        const uint8_t *p_arr;
        uint8_t currsize; * size of each array */
        uint8_t max; /* Ranges */
        uint8_t min;
    } array_t;
    
    typedef struct {
        array_t *A; /* pointer to array information */
        uint8_t numarrays; /* just a buddy vairable to keep track of n arrays */
    } data_t;
    
  3. mallocfree的必要调用,为堆上的指针变量分配和释放空间。
  4. 以下是我提出的建议:

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    #define INITSIZE 3
    
    typedef struct {
        const uint8_t *p_arr;
        uint8_t currsize;
        uint8_t max;
        uint8_t min;
    } array_t;
    
    typedef struct {
        array_t *A;
        uint8_t numarrays;
    } data_t;
    
    data_t *initialize_meta_data(void);
    int check_arrays(const uint8_t arr[], const size_t n, uint8_t *key);
    void set_arrays(data_t *data, const uint8_t arr[], const size_t n, int index);
    void search_arrays(data_t *data, uint8_t key);
    int cmpfunc(const void *a, const void *b);
    
    int
    main(void) {
        const uint8_t arr_1[] = {1, 4, 53 , 209};
        const uint8_t arr_2[] = {54, 56, 90, 100};
        const uint8_t arr_3[] = {6, 7, 8, 9, 10};
    
        const size_t size1 = sizeof(arr_1)/sizeof(*arr_1);
        const size_t size2 = sizeof(arr_2)/sizeof(*arr_2);
        const size_t size3 = sizeof(arr_3)/sizeof(*arr_3);
    
        data_t *data = initialize_meta_data();
    
        data->A = malloc(data->numarrays * sizeof(*(data->A)));
    
        set_arrays(data, arr_1, size1, 0);
        set_arrays(data, arr_2, size2, 1);
        set_arrays(data, arr_3, size3, 2);
    
        /* Number to search for */
        uint8_t key = 10;
    
        search_arrays(data, key);
    
        free(data->A);
        free(data);
    
        return 0;
    }
    
    void
    search_arrays(data_t *data, uint8_t key) {
        int i;
    
        for (i = 0; i < data->numarrays; i++) {
            if ((key <= data->A[i].max) && (key >= data->A[i].min)) {
                if (check_arrays(data->A[i].p_arr, data->A[i].currsize, &key)) {
                    printf("%d found in array number: %d\n", key, i+1);
                }
            } else {
                printf("array number: %d skipped\n", i+1);
            }
        }
    }
    
    void
    set_arrays(data_t *data, const uint8_t arr[], const size_t n, int index) {
        data->A[index].p_arr = arr;
        data->A[index].currsize = n;
        data->A[index].max = data->A[index].p_arr[data->A[index].currsize-1];
        data->A[index].min = data->A[index].p_arr[0];
    }
    
    data_t
    *initialize_meta_data(void) {
        data_t *data = malloc(sizeof(*data));
        data->A = NULL;
        data->numarrays = INITSIZE;
        return data;
    }
    
    int
    check_arrays(const uint8_t arr[], const size_t n, uint8_t *key) {
        uint8_t *item;
    
        item = bsearch(key, arr, n, sizeof(*arr), cmpfunc);
    
        if (item != NULL) {
            return 1;
        }
    
        return 0;
    }
    
    int
    cmpfunc(const void *a, const void *b) {
        return (*(uint8_t*)a > *(uint8_t*)b) - (*(uint8_t*)a < *(uint8_t*)b);
    }
    

    总的来说,这个代码可以进行大量优化,你可能会对你的项目使用一种非常不同的方法,但这个想法是类似的。

    我希望它有所帮助:)。

答案 2 :(得分:0)

#include <stdio.h>
#include <stdint.h>

const uint8_t arr_1[] = {1, 4, 53 , 209};
const uint8_t arr_2[] = {54, 56, 90, 100};
const uint8_t arr_3[] = {6, 7, 8, 9, 10};

uint8_t lookup[256] = {0,};

void add_one(const uint8_t *arr, unsigned count, unsigned num)
{
unsigned uu, val;

for (uu=0; uu < count; uu++) {
        val = arr[uu];
        if (lookup[val]) fprintf(stderr
                , "Add_one(num = %u): OMG!1111! value=%u also present in array_%u\n"
                , num, val, (unsigned) lookup[val] );
        lookup[val] = num;
        }
}

void do_init(void)
{
add_one(arr_1, 4, 1);
add_one(arr_2, 4, 2);
add_one(arr_3, 6, 3);
}

int main(void)
{
unsigned idx,val;

do_init();

for (val = 0; val < 256; val++) {
        idx = lookup[val];
        if (!idx) continue;
        printf("Value %u is in arr_%u\n", val, idx);
        }

return 0;
}

答案 3 :(得分:0)

因为它是uint8_t你可以使用一个bitarray。没有排序没有循环。 此代码未经过测试,但可以看到这个想法。

uint arrEle(uint8_t val) { return val/32; }
uint arrBit(uint8_t val) { return 1<<(val%32); }

void setBit(uint32_t *arr, uint8_t val) {
    arr[arrEle(val)]|=arrBit(val);
}
uint testBit(uint32_t *arr, uint8_t val) {
    return (arr[arrEle(val)]&arrBit(val)) ? 1:0;
}
void clrBit(uint32_t *arr, uint8_t val) {
    arr[arrEle(val)]&=~arrBit(val);
}

// sorry not static initialize
const uint32_t arr_all[4][8] = {0};
const uint32_t arr_1[][8] = arr_all[0];
const uint32_t arr_2[][8] = arr_all[1];

setBit(arr_1, 1);
setBit(arr_1, 4);
setBit(arr_1, 53);
setBit(arr_1, 209);

现在您的测试非常简单:

for(i=0;i<sizeof(arr_all)/sizeof(*arr_all);i++) 
  if(testBit(arr_all[i], val)) return i;  // return the array number 0..3