最佳阵列推送

时间:2013-04-08 21:50:14

标签: c arrays

我想创建一些带有两个参数的函数:int元素和输入数组。我希望这个函数将元素参数放在数组的第一个位置,用单个索引放大数组,最后将输入数组放在推送元素之后。

为了说明这一点,假设我的输入数组为{1,2,3},并且当参数为5时传递元素。输出应为{5,1,2,3}。

如何以最佳方式做到这一点?

我出来了这个功能:

void push(int el, int **arr)
{
    int *arr_temp = *arr;

    *arr = NULL;
    *arr = (int*) malloc(sizeof(int)*(n - 1));

    (*arr)[0] = el;
    for(int i = 0; i < (int)n - 1; i++)
    {
        (*arr)[i + 1] = arr_temp[i];
    }
}

它有效,但是,它不是我写的最快的功能,它减慢了整个程序。有更好的方法吗?

我的猜测是做(*arr)[1] = arr_temp之类的事情,但它没有用,我不确定C是否有可能做这样的事情。

2 个答案:

答案 0 :(得分:2)

不是使用原始数组,最好将数组包装在struct中:

typedef struct
{
    size_t elementsAllocated;
    size_t elementsUsed;
    int* buffer;
} vector;

然后你的推送功能看起来像:

vector* push_front(vector* v, int item)
{
    if (elementsUsed == elementsAllocated)
    {
        // Time to grow the buffer.
        int elementsAllocated = v->elementsAllocated * 2;
        if (elementsAllocated <= v->elementsAllocated)
        {
            abort(); // Overflow occurred.
        }

        int* buffer = realloc(v->buffer, elementsAllocated * sizeof *buffer);
        if (buffer == NULL)
        {
            abort();
        }

        // Shift the existing data over.
        memmove(buffer + elementsAllocated - v->elementsUsed,
                buffer + v->elementsAllocated - v->elementsUsed,
                v->elementsUsed * sizeof *buffer);
        v->buffer = buffer;
        v->elementsAllocated = elementsAllocated;
    }

    // Prepend the new item.
    int* p = v->buffer + v->elementsAllocated - v->elementsUsed - 1;
    *p = item;
    v->elementsUsed++;
    return p;
}

如果您可以将项目附加到数组的末尾而不是在开头之前添加,那么这将会非常简单。请注意,上面的代码是完全未经测试的,可能包含一个错误,但核心思想是:

  • 内存分配很昂贵。分配比您需要的内存更多的内存,然后写入已分配但未使用的空间。这样可以减少重新分配缓冲区和复制数据以转移缓冲区的次数。
  • 通过以更大的步长增长缓冲区,最大限度地减少缓冲区的增长次数。

答案 1 :(得分:0)

正如评论中所建议的那样,您可能只想附加到数组,然后使用一个小的结构和函数来让您访问所需的元素,就像数组被预先添加一样。你似乎有重新调整大小,所以我只是建议一些反转的示例代码。这是未经测试的,因为我现在没有坐在我旁边的unix盒子以便于测试 - 注意我的C有点生锈。

typedef struct{
    int* array;
    int size;
} prependArray;

void accessElement(int element, prependArray myArray) {
    return myArray.array[size-element-1];
}

这样,您还可以分配比您需要的更大的数组。在“prependArray”中保留一个int,列出您上次重新分配的大小。当有人试图添加项目时,请检查您是否达到了该限制;如果有,请在添加新值之前调整列表大小。如果您要添加大量数字,这可以节省分配时间。

您可能希望在这种想法上查找“向量”数据结构。