C ++ array_put ()

0

Привет, у меня вопрос о C++ бесконечных массивах. Эта функция array_put(), создавая новый массив, является лучшим способом увеличить размер массива? Может быть, есть более быстрые способы, чем это? :(

Здесь я использую и не знаю об этом...

#include <windows.h>
#include <iostream>
#include <sstream>

using namespace std;

// ============================================================
//                       ALERT WINDOW
// ============================================================
void alert(string value, string title = "Warning")
{
    MessageBox(NULL, value.c_str(), title.c_str(), MB_OK);
}
// ============================================================


// ============================================================
//                     INTEGER TO STRING
// ============================================================
string integer_to_string(int value)
{
    ostringstream stream;
    stream<<value<<flush;

    return stream.str();
}
// ============================================================

// ============================================================
//                          ARRAY PUT
// ============================================================
typedef struct ARRAY{
    int* data;
    int length = 0;
} array;

void array_put(array &array_data, int value)
{
    int* new_array = new int[array_data.length+1];
    if (array_data.length != 0){new_array = array_data.data;}

    new_array[array_data.length] = value;

    array_data.data = new_array; array_data.length++;
}
// ============================================================


// ============================================================
//                ARRAY PRINT (REQ: ARRAY PUT)
// ============================================================
string array_print(array array_data)
{
    string out = "";
    out += "array_length: " + integer_to_string(array_data.length) + "\n";
    for (int i=0;i < array_data.length;i++)
    {
        out += "[" + integer_to_string(i) + "] = " + integer_to_string(array_data.data[i]) + "\n";
    }
    return out;
}
// ============================================================

int main()
{
    array array_data;
    array_put(array_data, 120);
    array_put(array_data, 170);

    string result = array_print(array_data);
    alert(result);

    return 0;
}
  • 1
    Вы можете использовать std :: vector, который автоматически (или вручную) будет обрабатывать перераспределение, если потребуется больший размер.
Теги:
arrays

4 ответа

1

Другие уже указали на ошибки в вашем коде и указали на то, что вы, вероятно, должны использовать vector вместо домашнего решения. Однако никто до сих пор не ответил на ваш вопрос, существует ли более быстрый метод.

Предполагая, что вы обычно добавляете более одного элемента в один и тот же массив, это действительно не оптимально: как есть (после исправления ошибок), вы перераспределите массив для каждой отдельной записи с копированием всех ранее сохраненных данных. Поскольку эти данные будут расти с каждым элементом, вы получите квадратичную сложность вставок (количество копий, которое должно быть сделано, пропорционально квадрату числа вставленных элементов) и линейное число дорогостоящих перераспределений.

Лучшая стратегия состоит в том, чтобы всегда выделять определенную долю числа существующих элементов в качестве новых элементов и отслеживать, сколько из этих элементов фактически является частью массива, и сколько из них уже предварительно выделено для добавления новых элементов позже. Это уменьшает количество перераспределений, тем больше ваш массив уже и в конечном итоге дает вам амортизированную постоянную сложность (в среднем количество копий, которые необходимо выполнить, пропорционально количеству вставленных элементов) и логарифмическое число дорогостоящие перераспределения.

Действительно, это именно то, что делает vector.

0

Функция array_put просто неверна. Например, в вашей функции есть утечка памяти. Сначала вы выделили память и назначили ее адрес new_array, а в следующем объявлении вы переназначили new_array. Таким образом, адрес выделенной памяти был потерян.

Я думаю, что вместо этого

void array_put(array &array_data, int value)
{
int* new_array = new int[array_data.length+1];
 if (array_data.length != 0){new_array = array_data.data;}

new_array[array_data.length] = value;

array_data.data = new_array; array_data.length++;
}

вы имели в виду следующее

void array_put( array &array_data, int value )
{
    int *data  = new int[array_data.length+1];

    std::copy( array_data.data, array_data.data + array_data.length, data );
    data[array_data.length] = value;

    delete [] array_data.data;

    array_data.data = data;
    ++array_data.length; 
}

Конечно, было бы лучше, если бы вы использовали стандартный класс std::vector вместо того, чтобы вручную выделять массив.

0

В отличие от вашего решения, которое не работает, увеличение размера на 1 каждый раз означает, что для добавления N элементов потребуются копии O (N * N) - вы копируете 1 элемент, затем 2, затем 3 и т.д.

Просто используйте vector. Он работает, и гарантированно добавить элемент в постоянное время в среднем.

0

В коде есть несколько проблем. Прежде всего

new_array = array_data.data;

не копирует содержимое старого массива в новый массив, он просто назначает указатель, поэтому после этого new_array совпадает с array_data.data. Вы можете использовать memcpy здесь:

memcpy(new_array, array_data.data, sizeof(int)*array_data.length);

Вам также необходимо освободить старые данные массива перед тем, как назначить новое хранилище, чтобы избежать утечек, поэтому:

delete [] array_data.data;
array_data.data = new_array;

После того, как ваш код будет работать правильно, вы можете подумать о распределении большего объема хранилища, чтобы избежать выделения нового массива в каждом массиве.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню