基于每3个元素的位置从数组中删除元素

时间:2018-06-21 13:32:02

标签: c arrays if-statement indices array-difference

我创建了一个名为elements_n的数组,该数组的元素为0N-1,其中N为2。下面的数字是名为{{1 }}:

elements_n

我还有一个名为0 1 的数组,其中包含以下元素:

Arr

如果数组0 1 3 1 2 4 的前3个元素中的任何一个等于Arr的第一个元素elements_n,我想从名为{的数组中删除该元素{1}}。然后,我对数组0的后三个元素重复相同的过程。因此,为了更好地说明自己,我将使用以下示例:

将数组Arr的前3个元素(分别为0、1、3和3)与Arr的第一个元素(即0)进行比较。由于Arr。我从数组elements_n中删除了Arr[0] == elements_n[0]

比较数组Arr[0]的后三个元素1、2、4与Arr的第二个元素1。因为Arr。我从数组elements_n中删除了Arr[3] == elements_n[1]。因此,应该在数组Arr[3]中保留的元素是:

Arr

当我用C编程实现自己的代码时,最终结果如下:

Arr

而不是:

1 3 2 4

这是我实现的代码:

 1       3       3       2       2       4

4 个答案:

答案 0 :(得分:1)

您可以尝试类似的方法(未经测试)。

shift()

答案 1 :(得分:0)

您需要跟踪从数组中删除了多少个元素。
我的解决方案:

#include <stdio.h>
#include <stddef.h>
#include <assert.h>
#include <string.h>

size_t fancy_delete_3(const int elems[], size_t elemssize, int arr[], size_t arrsize)
{
    assert(elems != NULL);
    assert(arr != NULL);
    assert(arrsize%3 == 0);
    assert(elemssize*3 == arrsize);
    // we need to count the removed elements, to know how much we need to shift left
    size_t removed = 0;
    // for each element in elems
    for (size_t i = 0; i < elemssize; ++i) {
        // check the three correponding elements in arr
        for (size_t j = i*3; j < (i+1)*3; ++j) {
            assert(j >= removed);
            const size_t pos = j - removed;
            // if elems[i] matches any of the corresponding element in arr
            if (elems[i] == arr[pos]) {
                // remove element at position pos
                assert(arrsize >= pos + 1);
                // I don't think this can ever overflow
                memmove(&arr[pos], &arr[pos + 1], (arrsize - pos - 1) * sizeof(int));
                ++removed;
                // array is one element shorter, so we can just decrease the array size
                assert(arrsize > 0);
                --arrsize;
            }
        }
    }
    // we return the new size of the array
    return arrsize;
}

#define __arraycount(x) sizeof(x)/sizeof(x[0])

int main()
{
    int elements_n[] = {0,1};
    int arr[] = {0,1,3, 1,2,4};
    size_t newsize = fancy_delete_3(elements_n, __arraycount(elements_n), arr, __arraycount(arr));

    printf("arr size=%zu {", newsize);
    for (size_t i = 0; i < newsize; ++i)
        printf("%d,", arr[i]);
    printf("}\n");

    return 0;
}

答案 2 :(得分:0)

关于如何执行删除,您有几个相关的问题。首先,不清楚您是否了解您实际上无法从C数组中删除任何内容。您可以找到的最接近的方法是用其他方法覆盖。通常,通过将删除的一个元素之后的每个元素向前移动并减小数组的 logical 长度,可以实现从数组中进行伪删除。 * 选择了这种方法,但是(问题1)您错过了维护或更新逻辑数组长度的操作。

由于逻辑上将数组细分为段,因此您的问题变得更加复杂了,而且您似乎不欣赏您的段是可变长度的原因,如上所述删除元素时缩小。这是由于以下事实:从一个组中删除元素不会更改元素到其他组的分配。您可以在position_groups中使用一种机制来显然地跟踪组的大小,从这个意义上说,它的名称似乎不合适。与跟踪和更新整个阵列的逻辑长度一样,您将需要跟踪和更新组的长度。

最后,您似乎在这里出现了一个错误的错误:

              for (int j = index - 1; j < position_indices[count]-1; j++)

如果更好地命名position_indices(请参见上文),则会更清楚,但要认识到它实际上包含的是每个组的 size ,以及indexj代表组内的索引,因此迭代的边界条件应改为j < position_indices[count]。但是,这没有什么意义,因为无论如何您都需要一种不同的方法。

建议,然后:

  1. 从组中删除元素时,请向上移动数组的整个尾部,而不仅仅是向上移动组的尾部。
  2. 为此,在执行删除操作时,请同时更新组大小和逻辑数组大小,并记住这也会影响每个后续组的起始位置
  3. 检查或输出结果时,请记住不要理会超出数组逻辑端的数组元素。

* “逻辑数组大小”表示包含有意义数据的(前导)元素的数量。在您的情况下,逻辑数组大小最初与物理数组大小相同,但是每次删除元素(并因此向上移动尾部)时,逻辑大小都会减小一。

答案 3 :(得分:0)

您从未真正“删除”任何元素,只是向下移动了 每个3组的第二和第三元素。然后,当 打印,您遍历了整个数组。

数组只是连续的内存块,因此您需要一个 不同的策略。您可以使用以下方法遍历原始数组 两个索引,一个作为通用索引计数器,另一个作为 转换后的广告位的索引。如果当前元素是 与相应的elements_n项目不同,请将其复制到 次要指标并增加它。

如果没有什么与elements_n项相等,则只需 将数组元素重新分配给自己。但是,尽快 一个是平等的,您将利用以下优势转移他们 跟踪新尺寸。

此外,计算相应的elements_n项很简单 将当前索引除以3的问题,因此您甚至不需要 一个额外的变量。

#include <stdio.h>
#define N 2

int main()
{
    unsigned elements_n[N] = { 0, 1 };
    unsigned Arr[N*3] = { 0, 1, 3, 1, 2, 4 };
    int i, j;

    for (i = 0, j = 0; i < N*3; i++)
        if (Arr[i] != elements_n[i/3])
            Arr[j++] = Arr[i];

    for (i = 0; i < j; i++)
        printf(" %d", Arr[i]);
    printf("\n");

    return 0;
}