【问题标题】:Finding the index of a value from a random dimensional array从随机维度数组中查找值的索引
【发布时间】:2016-02-25 09:31:15
【问题描述】:
int getIndex(int a[], int size, int value)
{
    int index = 0;

    while (index < size && a[index] != value)
    {
        ++index;
    }

    return (index == size ? -1 : index);
}

这是一个返回数组内值索引的方法。我想有一种方法可以对任何维度执行此操作。我怎样才能使它通用?还是根本不可能?

【问题讨论】:

  • 你能说清楚一点吗?
  • 您可以将任意大小的数组传递给此方法,前提是您将大小更改为 size_t 类型
  • “维度”是什么意思?
  • 您想在int array[10][10] 中查找索引ij
  • @DennisvonEich 那么你的意思是“对于任意数量的维度”而不是“对于任意维度”

标签: c algorithm math


【解决方案1】:

您始终可以将指针传递给多维数组的第一个元素以及其中所有元素的数量,即每个维度中大小的乘积。从那里开始,算法就像在一维数组中一样。

数组中的元素,同样也是多维数组,保证在内存中是连续的。

返回值将是单个索引;该函数不知道维度的数量及其大小。调用者必须从找到的元素的“平面”整体索引重建每个数组维度中的索引;例如对于 int arr[2][5],返回值 8 将对应于元素 arr[1][2]。 “平面”索引和多维索引元组之间的关系(当然)是双射的。

#include<stdio.h>

#define DIM1 2
#define DIM2 5

int arr[DIM1][DIM2]; // zero-initialized

 // note: for a paramater, int a[] means int *a
int getIndex(int a[], int size, int value)
{
    int index = 0;

    while (index < size && a[index] != value)
    {
        ++index;
    }

    return (index == size ? -1 : index);
}

int main() 
{
    arr[1][2] = 1;

    int index = getIndex(arr[0], DIM1*DIM2, 1);

    if(index >= 0)
    {
        int dim1 = index/DIM2;
        int dim2 = index%DIM2; // modulo resp. remainder

        printf("found a 1 at [%d][%d]\n", dim1, dim2);
    }
    else
    {
        printf("Could not find 1 in arr\n");
    }
    return 0;
}

示例会话:

$ gcc -Wall -o multi-arr multi-arr.c && ./multi-arr
found a 1 at [1][2]

【讨论】:

  • 只是一个小缺陷:如果值为 AT 索引 0,那么您仍然会打印“未找到”!
  • +1 为简单起见。但是,我建议您检查 index != -1,否则您可能会得到错误的结果,正如 Daan 指出的那样。
  • @Dennis von Eich 请查看我的答案以获得更通用的解决方案。
【解决方案2】:

通用版本。可以以任意数量的维度运行。将一维数组视为多维空间,因此可以以不同方式查看同一内存区域。

完整的例子可以在here找到。

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

int get_idx(int a[], uint32_t dims[], uint32_t dims_n, int value)
{
    size_t size;
    size_t index = 0, n;

    if (dims[0] < 1) return -1;
    size = 1;
    n = dims_n;
    while (n)
        size *= dims[--n];

    if (dims_n > size) return -1;

    while (index < size && a[index] != value)
    {
        ++index;
    }

    if (index == size)
       return  -1;
    n = 0;
    while (n < dims_n)
    {
        size /= dims[n];
        dims[n] = index / size;
        index = index % size;
        ++n;
    }
    return 0;
}

用法:

int
main(void) {
    int res;
    uint32_t dims[5];
    int a[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };

    dims[0] = 12;
    res = get_idx(a, dims, 1, 10);
    if (res == -1) goto fail;
    printf("dim1 [%u]\n", dims[0]);

    dims[0] = 2;
    dims[1] = 6;
    res = get_idx(a, dims, 2, 10);
    if (res == -1) goto fail;
    printf("dim1 [%u] dim2 [%u]\n", dims[0], dims[1]);

    dims[0] = 3;
    dims[1] = 2;
    dims[2] = 2;
    res = get_idx(a, dims, 3, 10);
    if (res == -1) goto fail;
    printf("dim1 [%u] dim2 [%u] dim3 [%u]\n", dims[0], dims[1], dims[2]);

    dims[0] = 2;
    dims[1] = 2;
    dims[2] = 2;
    dims[3] = 2;
    res = get_idx(a, dims, 4, 10);
    if (res == -1) goto fail;
    printf("dim1 [%u] dim2 [%u] dim3 [%u] dim4 [%u]\n",
                       dims[0], dims[1], dims[2], dims[3]);
    return 0;
fail:
    printf("Not found\n");
    return -1;
}

输出:

dim1 [10]

暗1 [1]暗2 [4]

暗1 [2]暗2 [1]暗3 [0]

dim1 [1] dim2 [0] dim3 [1] dim4 [0]

【讨论】:

    【解决方案3】:

    你为什么不直接返回你想要的元素的地址呢?

    int *getIndex(int a[], int size, int value)
    {
      for (int i = 0; i < size; ++i) {
        if (a[i] == value) {
          return (a + i);
        }
      }
      return (NULL);
    }
    

    你可以有任何你想要的多维数组,不再重要了。

    【讨论】:

      【解决方案4】:

      数组只不过是一堆连续存储在内存中的元素(适用于任何维度)。当然,这意味着您只能将第一个元素传递给函数,同时跟踪数组大小。这样你就可以只用一个循环遍历所有元素,而不依赖于数组维度

      填充多维数组示例:

      int matrix[50][100];
      int *iptr = NULL;
      int i = 0;
      
      // sets first matrix to: 
      // row 0:   0,   1,   2, ...,  99 
      // row 1: 100, 110, 120, ..., 199
      //        ...
      iptr = &(matrix[0][0]);
      for(i=0; i < 50*100; i++) 
      {
          *iptr = i;
          iptr++;  
      }
      

      【讨论】:

      • 我觉得int[][] matrix = new int[50][100];可能是C#语法。
      • 我来自 C# 世界,我的错 :)
      猜你喜欢
      • 1970-01-01
      • 2012-10-11
      • 2019-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-18
      • 1970-01-01
      • 2019-07-24
      相关资源
      最近更新 更多