Как удалить элемент из динамического массива c
Перейти к содержимому

Как удалить элемент из динамического массива c

  • автор:

C++ Динамический массив. Удаление элемента

P.S.
То, что ты написал — это не С++, а просто С.

#3
16:05, 28 янв 2008

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

#4
16:18, 28 янв 2008

mirat
> Почему нет?
Потому, что исходный вопрос автора был «можно мне как-нибудь так хитро вызвать delete, чтобы массив сам сделал всё как надо ?»
И с этой позиции вариант
> Можно удалить элемент, потом вручную сдвинуть все элементы с удаленной позиции на единицу.
не катит.
Вот вектор — да, целостная сущность, обладающая нужным функционалом.

#5
16:30, 28 янв 2008

по поводу
стоимость операции удаления буде линейно зависить от кол-ва элементов?

#6
16:59, 28 янв 2008

HolyDel
Из середины да, из конца — константное время.

Nikopol
Не телепат, не знаю, что автор имел в виду 🙂

#7
17:03, 28 янв 2008

Все понятно. Всем спасибо

#8
17:17, 28 янв 2008

если удалять, то уж лучше std::list использовать.

#9
17:33, 28 янв 2008

замечу только что если порядок элементов в массиве не важен то делать своп с последним элементом + pop_back => константное время удаления

  • TaurenChief
  • Постоялец

#10
17:42, 28 янв 2008
#11
17:52, 28 янв 2008
#12
18:24, 28 янв 2008

JokerR
>замечу только что если порядок элементов в массиве не важен то делать своп с последним элементом + pop_back => константное время удаления

Но размер вектора не уменьшится (резервированный в памяти)

#13
19:18, 28 янв 2008

О. Федор
А что должен? Он у вектора не уменьшится в любом случае, кроме хака со swap’ом

#14
19:21, 28 янв 2008

вообще-то это implementation-depended

Как удалить элемент из динамического массива c

***
Такая к вам просьба. Мне нужны функции для добавления/удаления
элементов массивов в Си (не C++). Я так понимаю что допустим для
добавления элемента надо сделать его копию. А это как то криво.
Уверен что у многих уже есть такие функции. Если вам не жалко
киньте мне пожалуста их на адрес antonov21@inbox.ru.
Так же нужны любые другие функции для работы с элементами массивов.
Реализующие динамическое распределение памяти для элементов и т.п.
Ну вы понимаете. Спасибо большое. Считаю этот форум очень толковым.
В Поиске найти ничего по этому поводу не смог. Поэтому спрашиваю. Еще
раз всем спасибо.
***

Спрашивал на других форумах — никто не помог.
Может здесь помогут — очень надеюсь.

Я имею ввиду функции для работы с элементами массивов (вставить элемент, добавить, удалить).
А также любые другие функции которые будут полезны при работе с массивами.
Включая динамическое распределение памяти для элементов и т.п.

Re: Добавление/удаление элементов массива в Си

От: Алексей Владимирович Миронов
Дата: 05.02.03 01:44
Оценка:

Здравствуйте, Alexey_Antonov, Вы писали:

AA>Я так понимаю что допустим для добавления элемента надо сделать его копию. А это как то криво.

Согласен. С точки зрения производительности лучше заранее заказать память «с запасом», и не перераспределять ее при каждом добавлении элемента. Если «запаса» не хватило, то при очередном добавлении стОит сделать «запас» побольше.

На «чистом C» набор функций общего назначения для работы с массивами списками, деревьями, очередями и прочим есть, например, в GTK+ (смотреть в сторону Glib).

P.S. Может, лучше все-таки на C++ с использованием STL? Просто, достаточно эффективно, широко применяется, много знающих людей, в т.ч. на этом форуме.

Re[2]: Добавление/удаление элементов массива в Си

От: VCoder http://wxbar.sf.net
Дата: 05.02.03 07:11
Оценка:

АВМ>P.S. Может, лучше все-таки на C++ с использованием STL? Просто, достаточно эффективно, широко применяется, много знающих людей, в т.ч. на этом форуме.

Я тоже советую обратить внимание на C++ с использованием STL.

С уважением,
Дмитрий.
Re[2]: Добавление/удаление элементов массива в Си

От: _wqwa
Дата: 05.02.03 13:02
Оценка:

Здравствуйте, Алексей Владимирович Миронов, Вы писали:

АВМ>На «чистом C» набор функций общего назначения для работы с массивами списками, деревьями, очередями и прочим есть, например, в GTK+ (смотреть в сторону Glib).

Вот как раз все остальное, кроме массивов в Glib есть. А их-то и нету.

Если связный список или хеш не устроит, то придется изгалиться ручками.
Так что остается применить советы Саттера (если не ошибаюсь) и выделять память с запасом, напр. 30%. При переполнении массива — выделить еще на треть больше и т.д.

Re: Добавление/удаление элементов массива в Си

От: VVV
Дата: 05.02.03 13:57
Оценка:

Здравствуйте, Alexey_Antonov, Вы писали:

..
AA>Я имею ввиду функции для работы с элементами массивов (вставить элемент, добавить, удалить).
AA>А также любые другие функции которые будут полезны при работе с массивами.
AA>Включая динамическое распределение памяти для элементов и т.п.

Конечно, такой библиотеки у меня нет, но с помощью функции realloc это очень просто реализуется.
Не компилил, не проверял, просто идея:

typedef struct ARRAY< int num_; int size_ int top_; char arr_[1]; >ARRAY; #define SIZEARRAYMEM(n, s) ((n)*(s)+sizeof(ARRAY)) char *CreateArray(int numElem, int sizeElem) < ARRAY *pa=(ARRAY*)malloc(SIZEARRAYMEM(numElem, sizeElem)); pa->num_=numElem; pa->size_=sizeElem; pa->top_=0; return pa->arr_; > void DestroyArray(void *pa) < pa=((char*)pa)-offsetof(ARRAY, arr_); free(pa); > void AddElem(void **parr, void *pe) < ARRAY *pa=(ARRAY*)(((*(char**)parr))-offsetof(ARRAY, arr_)); if(pa->top_ == pa->num_) < int num=pa->num_*2; pa=(ARRAY*)realloc(pa, SIZEARRAYMEM(num, pa->size_)); pa->num_=num; > memcpy(pa->arr_+pa->top_*pa->size_, pe, pa->size_); pa->top_++; *parr=pa; > int GetCount(void *parr) < ARRAY *pa=(ARRAY*)(((char*)parr)-offsetof(ARRAY, arr_)); return pa->top_; >

Re[3]: Добавление/удаление элементов массива в Си

От: Алексей Владимирович Миронов
Дата: 05.02.03 15:08
Оценка: 3 (1)

Здравствуйте, _wqwa, Вы писали:

W>Вот как раз все остальное, кроме массивов в Glib есть. А их-то и нету.

Как же так? На странице документации Glib 2.0 перечислены следующие типы данных, поддерживаемые Glib:

Memory Chunks — efficient way to allocate groups of equal-sized chunks of memory.
Doubly-Linked Lists — linked lists containing integer values or pointers to data, with the ability to iterate over the list in both directions.
Singly-Linked Lists — linked lists containing integer values or pointers to data, limited to iterating over the list in one direction.
Double-ended Queues — double-ended queue data structure.
Trash Stacks — maintain a stack of unused allocated memory chunks.
Hash Tables — associations between keys and values so that given a key the value can be found quickly.
Strings — text buffers which grow automatically as text is added.
String Chunks — efficient storage of groups of strings.
Arrays — arrays of arbitrary elements which grow automatically as elements are added.
Pointer Arrays — arrays of pointers to any type of data, which grow automatically as new elements are added.
Byte Arrays — arrays of bytes, which grow automatically as elements are added.
Balanced Binary Trees — a sorted collection of key/value pairs optimized for searching and traversing in order.
N-ary Trees — trees of data with any number of branches.
Quarks — a 2-way association between a string and a unique integer identifier.
Keyed Data Lists — lists of data elements which are accessible by a string or GQuark identifier.
Datasets — associate groups of data elements with particular memory locations.
Relations and Tuples — tables of data which can be indexed on any number of fields.
Caches — caches allow sharing of complex data structures to save resources.
Memory Allocators — allocates chunks of memory for GList, GSList and GNode.

Я не говорю, что эти массивы подойдут на все случаи жизни. Но автор оригинального сообщения и не говорил, какие именно массивы ему нужны. А зря.

Re[4]: Добавление/удаление элементов массива в Си

От: _wqwa
Дата: 05.02.03 16:02
Оценка:

Как удалить элемент из динамического массива c

Пусть надо удлить элемент с индексом K
в цикле сдвигаете все элементы K+1 на место предыдущего.
после чего изменяете размер массива.

for i:=K+1 to Length(Valies)-1 do Valies[i-1] := Valies[i]; SetLength(Valies, Length(Valies) - 1);

Внимание. Вообще операции изменения размера динамического массива ресурсоёмкие. А тут ещё и цикл (представьте, Вы удаляете 2-й элемент в массиве из миллиона элементов. Надо 999998 элементов переместить в памяти. Это весьма не быстро.

Поэтому рекомендую посмотреть в сторону связных динамиских списков. Там опреция удаления сводится к изменению ссылки(или пары ссылок) и очистке памяти одного элемента. Это практически мгновенно происходит (т.е. не затрагивает остальные элементы этой динамической структуры)

Последний раз редактировалось Serge_Bliznykov; 14.05.2011 в 12:34 .

Serge_Bliznykov
Посмотреть профиль
Найти ещё сообщения от Serge_Bliznykov

Регистрация: 03.01.2011
Сообщений: 2,508

если порядок не важен, вместо сдвига можно менять местами с последним элементом

Length(Valies)

возвращает количество элементов в массиве, а нумеруются они с 0. Так что или — 1 добавить, или лучше использовать high().

«Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего.»
Последний раз редактировалось veniside; 14.05.2011 в 11:47 .
Регистрация: 09.01.2008
Сообщений: 26,238

Length(Valies)
возвращает количество элементов в массиве, а нумеруются они с 0. Так что или — 1 добавить, или лучше использовать high().

согласен. важное замечание. Это я ошибся.
исправил в исходном сообщении

если порядок не важен, вместо сдвига можно менять местами с последним элементом

и с этим согласен. Хотя мне связные списки всё равно как-то больше нравятся

Serge_Bliznykov
Посмотреть профиль
Найти ещё сообщения от Serge_Bliznykov

Форумчанин
Регистрация: 26.07.2009
Сообщений: 489
Сообщение от mrCloud
Есть тип например

TValues = record Price,term:integer; end;

и по нему создан динамический массив

var Valies:array of TValues

Вопрос: как удалить элемент с заданным индексом?

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

TValues = record Price,term:integer; Exist: Boolean; end; . for I := 0 to High(Valies) do begin if Valies[I].Exist then begin // Обработка end; end;

И для «удаления» (исключения из обработки) присваиваем Valies[I].Exist := False;

Но если все-таки хочешь удаление, то

 TValues = record Price, Term:integer; end; TValuesArr = array of TValues; var Form1: TForm1; V: TValuesArr; function DeleteEl(V: TValuesArr; Index: Integer): TValuesArr; implementation function DeleteEl(V: TValuesArr; Index: Integer): TValuesArr; var NewSize: Integer; I, Ind: Integer; begin NewSize := Length(V) - 1; if Index > NewSize then raise Exception.Create('Указанный элемент не существует'); SetLength(Result, NewSize); Ind := 0; for I := 0 to High(V) do begin if I <> Index then begin Result[Ind] := V[I]; Inc(Ind); end; end; end; procedure TForm1.Button1Click(Sender: TObject); begin SetLength(V, 5); V := DeleteEl(V, 4); end;

Если в глубине души вы программист, то, следуя своим наклонностям, вы захотите написать кусок кода.
Последний раз редактировалось chertovich; 14.05.2011 в 15:04 .

chertovich
Посмотреть профиль
Найти ещё сообщения от chertovich

Как удалить элемент массива?

Доброго времени суток! Задача следующая:
1) Сформировать одномерный массив целых чисел, используя датчик случайных чисел.
2) Распечатать полученный массив.
3) Удалить элемент с номером К.
4) Добавить после каждого четного элемента массива элемент со значением 0.
5) Распечатать полученный массив.
Первые два пункта получилось сделать,но я не могу понять,как сделать 3 и 4 пункты. Векторы еще не изучал,так что,если не составит труда,объясните пожалуйста человеческим языком,какой алгоритм нужен для решения задач подобного рода.Спасибо)

  • Вопрос задан более трёх лет назад
  • 52117 просмотров

Комментировать
Решения вопроса 1

gbg

Армянское Радио @gbg Куратор тега C++
Любые ответы на любые вопросы

Третий пункт решается просто — вам нужно передвинуть элементы в массиве: присвоить a[i]=a[i+1] в цикле.
Я думаю, вам запрещено использовать STL, так что пишите циклы.

Формат данного сайта запрещает совмещать кучу вопросов в один, так что постарайтесь разделить темы.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *