Операции с векторами в STL
Размер вектора можно узнать при помощи универсального метода size() , возвращающего для всех контейнеров в STL их размер. Также есть метод empty() , возвращающий логическое значение ( true , если вектор пустой).
Размер вектора можно изменить в любой момент, при помощи метода resize . У этого метода может быть один или два параметра. Вызов метода resize(n) изменяет размер вектора до n элементов (длина вектора может как уменьшится, так и увеличиться). Вызов метода resize(n, val) изменяет размер вектора до n элементов, и если при этом размер вектора увеличивается, то новые элементы получают значение, равное val.
Очень часто бывает полезно добавлять элементы в конец вектора по одному и удалять элементы из конца вектора по одному. Для добавления нового элемента, равного val в конец вектора используется метод push_back(val) . Для удаления последнего элемента вектора используется метод pop_back() — он не возвращает значения.
Добавление элемента в конец вектора осуществляется в среднем за O(1). Это реализовано за счет того, что память для хранения элементов вектора выделяется “с запасом”, то есть можно будет добавлять элементы по одному, пока не кончится запас памяти. Если запас памяти исчерпан, выделяется новая память, при этом «запас» размера вектора удваивается.
Очистить вектор можно при помощи метода clear() .
Вставка и удаление элементов в середину вектора
Для удаления и вставки элементов в середину вектора используются методы erase и insert . В качестве параметра им нужно передавать итератор, поэтому просто покажем на примере, как их использовать.
Итератор — специальный объект, указывающий на элемент вектора (или другой структуры данных). Итератор на элемент с индексом i можно получить при помощи выражения a.begin() + i . Кроме того, можно при помощи итератора a.end() “отсчитывать” элементы, начиная с конца. При этом a.end() будет итератором на элемент, следующий за последним, a.end() будет итератором на последний элемент, то есть то же самое, что a.begin() + a.size() — 1 , a.end() — 2 — второй элемент с конца и т.д.
Удаление элементов: метод erase
Метод erase позволяет удалять из середины вектора один или несколько элементов. Если вызвать метод erase с одним параметром–итератором, то будет удален соответствующий элемент из вектора, то есть для удаления элемента с индексом i из вектора a нужно вызвать метод следующим образом:
a.erase(a.begin() + i);
Методу erase передать два итератора на начало и конец удаляемого фрагмента, например:
a.erase(a.begin() + i, a.begin() + j);
В этом случае будут удалены элементы с индексами от i (включительно) до j не включительно, то есть элементы a[i] , a[i + 1] , . a[j — 1] . Всего будет удалено j — i элементов.
Методу erase можно передавать и итераторы, полученные относительно итератора end . Например, удалить из вектора три последних элемента можно так:
a.erase(a.end() - 3, a.end());
Подробней про его использование можно прочитать в документации.
Вставка элементов: метод insert
Метод insert позволяет вставлять в середину вектора новый элемент, или несколько равных элементов, или другой вектор, или фрагмент другого вектора. Этот метод также работает с итераторами и про его использование можно прочитать в документации.
Примеры использования метода insert :
Вставка одного элемента со значением val в позицию с индексом i :
a.insert(a.begin() + i, val);
Вставка нескольких равных (количеством count ) элементов со значением val в позицию с индексом i :
a.insert(a.begin() + i, count, val);
Вставка в вектор a в позицию с индексом i фрагмент вектора b с индексами от start включительно до finish не включительно:
a.insert(a.begin() + i, b.begin() + start, b.begin() + finish);
В качестве параметром могут использоваться произвольные итераторы. Рассмотрим несколько примеров:
Весь вектор b добавить в конец вектора a :
a.insert(a.end(), b.begin(), b.end());
Последние 5 элементов вектора b вставить в начало вектора a :
a.insert(a.begin(), b.end() - 5, b.end());
Поскольку вставка и удаление элементов требуют сдвига других элементов вектора, эти операции имеют линейную сложность, то есть выполняются за время, пропорциональное длине вектора.
Присваивание и сравнение векторов
Содержимое одного вектора можно целиком скопировать в другой вектор при помощи операции присваивания. При этом размер вектора A автоматически изменится и будет равен размеру вектора B . A = B .
Также векторы можно сравнивать на равенство и неравенство ( A == B , A != B ), и сравнивать их содержимое в лексикографическом порядке ( A < B , A B , A >= B ).
Как удалить элемент из вектора c
Для добавления элементов в вектор применяется функция push_back() , в которую передается добавляемый элемент:
#include #include int main() < std::vectornumbers; // пустой вектор numbers.push_back(5); numbers.push_back(3); numbers.push_back(10); for(int n : numbers) cout << n << "\t"; // 5 3 10 std::cout
Векторы являются динамическими структурами в отличие от массивов, где мы скованы его заданым размером. Поэтому мы можем динамически добавлять в вектор новые данные.
Функция emplace_back() выполняет аналогичную задачу — добавляет элемент в конец контейнера:
std::vector numbers< 1, 2, 3, 4, 5 >; numbers.emplace_back(8); // numbers = < 1, 2, 3, 4, 5, 8 >;
Добавление элементов на определенную позицию
Ряд функций позволяет добавлять элементы на определенную позицию.
- emplace(pos, value) : вставляет элемент value на позицию, на которую указывает итератор pos
- insert(pos, value) : вставляет элемент value на позицию, на которую указывает итератор pos, аналогично функции emplace
- insert(pos, n, value) : вставляет n элементов value начиная с позиции, на которую указывает итератор pos
- insert(pos, begin, end) : вставляет начиная с позиции, на которую указывает итератор pos, элементы из другого контейнера из диапазона между итераторами begin и end
- insert(pos, values) : вставляет список значений начиная с позиции, на которую указывает итератор pos
std::vector numbers< 1, 2, 3, 4, 5 >; auto iter = numbers.cbegin(); // константный итератор указывает на первый элемент numbers.emplace(iter + 2, 8); // добавляем после второго элемента numbers = < 1, 2, 8, 3, 4, 5>;
std::vector numbers1< 1, 2, 3, 4, 5 >; auto iter1 = numbers1.cbegin(); // константный итератор указывает на первый элемент numbers1.insert(iter1 + 2, 8); // добавляем после второго элемента //numbers1 = < 1, 2, 8, 3, 4, 5>; std::vector numbers2 < 1, 2, 3, 4, 5 >; auto iter2 = numbers2.cbegin(); // константный итератор указывает на первый элемент numbers2.insert(iter2 + 1, 3, 4); // добавляем после первого элемента три четверки //numbers2 = < 1, 4, 4, 4, 2, 3, 4, 5>; std::vector values < 10, 20, 30, 40, 50 >; std::vector numbers3 < 1, 2, 3, 4, 5 >; auto iter3 = numbers3.cbegin(); // константный итератор указывает на первый элемент // добавляем после первого элемента три первых элемента из вектора values numbers3.insert(iter3 + 1, values.begin(), values.begin() + 3); //numbers3 = < 1, 10, 20, 30, 2, 3, 4, 5>; std::vector numbers4 < 1, 2, 3, 4, 5 >; auto iter4 = numbers4.cend(); // константный итератор указывает на позицию за последним элементом // добавляем в конец вектора numbers4 элементы из списка < 21, 22, 23 >numbers4.insert(iter4, < 21, 22, 23 >); //numbers4 = < 1, 2, 3, 4, 5, 21, 22, 23>;
Удаление элементов
Если необходимо удалить все элементы вектора, то можно использовать функцию clear :
std::vector v < 1,2,3,4 >; v.clear();
Функция pop_back() удаляет последний элемент вектора:
std::vector v < 1,2,3,4 >; v.pop_back(); // v =
Если нужно удалить элемент из середины или начала контейнера, применяется функция std::erase() , которая имеет следующие формы:
- erase(p) : удаляет элемент, на который указывает итератор p. Возвращает итератор на элемент, следующий после удаленного, или на конец контейнера, если удален последний элемент
- erase(begin, end) : удаляет элементы из диапазона, на начало и конец которого указывают итераторы begin и end. Возвращает итератор на элемент, следующий после последнего удаленного, или на конец контейнера, если удален последний элемент
std::vector numbers1 < 1, 2, 3, 4, 5, 6 >; auto iter = numbers1.cbegin(); // указатель на первый элемент numbers1.erase(iter + 2); // удаляем третий элемент // numbers1 = < 1, 2, 4, 5, 6 >std::vector numbers2 = < 1, 2, 3, 4, 5, 6 >; auto begin = numbers2.cbegin(); // указатель на первый элемент auto end = numbers2.cend(); // указатель на последний элемент numbers2.erase(begin + 2, end — 1); // удаляем с третьего элемента до последнего // numbers2 =
Также начиная со стандарта С++20 в язык была добавлена функция std::erase() . Она не является частью типа vector. В качестве первого параметра она принимает вектор, а в качестве второго — элемент, который надо удалить:
std::vector numbers3 < 1, 2, 3, 1, 5, 6 >; std::erase(numbers3, 1); // numbers3 =
В данном случае удаляем из вектора numbers3 все вхождения числа 1.
Размер вектора
С помощью функции size() можно узнать размер вектора, а с помощью функции empty() проверить, путой ли вектор:
#include #include int main() < std::vectornumbers; if(numbers.empty()) std::cout
С помощью функции resize() можно изменить размер вектора. Эта функция имеет две формы:
- resize(n) : оставляет в векторе n первых элементов. Если вектор содержит больше элементов, то его размер усекается до n элементов. Если размер вектора меньше n, то добавляются недостающие элементы и инициализируются значением по умолчанию
- resize(n, value) : также оставляет в векторе n первых элементов. Если размер вектора меньше n, то добавляются недостающие элементы со значением value
std::vector numbers1 < 1, 2, 3, 4, 5, 6 >; numbers1.resize(4); // оставляем первые четыре элемента — numbers1 = numbers1.resize(6, 8); // numbers1 =
Важно учитывать, что применение функции resize может сделать некорректными все итераторы, указатели и ссылки на элементы.
Изменение элементов вектора
Функция assign() позволяет заменить все элементы вектора определенным набором:
std::vector langs = < "Java", "JavaScript", "C">; langs.assign(4, «C++»); // langs =
В данном случае элементы вектора заменяются набором из четырех строк «C++».
Также можно передать непосредственно набор значений, который заменит значения вектора:
std::vector langs< "Java", "JavaScript", "C">; langs.assign(< "C++", "C#", "C">); // langs =
Еще одна функция — swap() обменивает значения двух контейнеров:
std::vector clangs < "C++", "C#", "Java" >; std::vector ilangs < "JavaScript", "Python", "PHP">; clangs.swap(ilangs); // clangs = < "JavaScript", "Python", "PHP">; for(std::string lang : clangs)
Сравнение векторов
Векторы можно сравнивать — они поддерживают все операции сравнения: , =, ==, !=. Сравнение контейнеров осуществляется на основании сравнения пар элементов на тех же позициях. Векторы равны, если они содержат одинаковые элементы на тех же позициях. Иначе они не равны:
std::vector v1 ; std::vector v2 ; std::vector v3 ; bool v1v2 = v1 == v2; // true bool v1v3 = v1 != v3; // true bool v2v3 = v2 == v3; // false
Как удалить элемент вектора по индексу?
Пытаюсь удалить элемент вектора если поле соответствует тому, что я ввел с клавиатуры, найденный мною способ на просторах интернета удаляет только два элемента, хотя должен по идее удалять все, код функции:
void Delete(vector &train) < string dest; cout > dest; for (int i = 0; i < train.size(); i++) if (train[i]->GetDest() == dest) train.erase(train.begin() + i); >
- Вопрос задан более двух лет назад
- 427 просмотров
Комментировать
Решения вопроса 1
Wataru @wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Не работает ваш код потому, что, допустим при i==3 вы удаляете элемент. Теперь элементом по индексу i будет следующий за удаленным элемент. Вы его не проверите и в конце итерации i увеличится на 1. Таким образом, следующие за удаляемым элементом вы просто пропустите.
Есть много способов исправить эту оплошность:
1) При удалении уменьшайте i на 1, чтобы следующее i++ от цикла for было отменено.
2) Вместо цикла for используйте while, где вы инкрементируете i только если элемент не удаляется.
3) Вместо if используйте цикл while, который удялял бы элемент в позиции i, пока его надо удалять (не забудьте проверить, что элемент, таки, существует — вы могли удалить последний элемент и i станет за границей массива).
4) (лучший вариант) Используйте remove. Мало того, что вам не надо изобретать велосипед, так этот метод еще и будет на порядок быстрее удаления по одному элементу. Потому что при каждом удалении у вас сдвигается часть массива и вы получаете квадратичное время работы на ровном месте.
Функция Vector Erase () в C++


Программирование и разработка
На чтение 6 мин Просмотров 25.5к. Опубликовано 06.08.2021
Массив используется для хранения нескольких данных, и количество элементов массива не может быть изменено во время выполнения. Эту проблему можно решить, используя вектор, который работает как динамический массив. В классе вектора существуют различные функции для добавления и удаления элемента из вектора. Функция erase () используется для удаления одного или нескольких элементов из вектора во время выполнения, что уменьшает размер вектора. Использование этой функции было объяснено в этом руководстве.
Синтаксис:
Ниже приведены два типа синтаксиса этой функции.
iterator erase ( iterator position ) ;
Вышеупомянутая функция erase () используется для удаления одного элемента из вектора, она возвращает итератор и указывает на элемент, за которым следует последний удаленный элемент.
iterator erase ( iterator starting_position, iterator ending_position ) ;
Вышеупомянутая функция erase () используется для удаления нескольких элементов из вектора на основе позиции, указанной в первом и втором аргументах этой функции.
Предварительные условия:
Прежде чем проверять примеры этого руководства, вы должны проверить, установлен ли компилятор g ++ в системе. Если вы используете Visual Studio Code, установите необходимые расширения для компиляции исходного кода C ++ и создания исполняемого кода. Здесь приложение Visual Studio Code было использовано для компиляции и выполнения кода C ++. Ниже показаны различные варианты использования функции erase () для вставки элемента (ов) в вектор.
Пример 1: удалить первый элемент element
Создайте файл C ++ со следующим кодом, чтобы удалить элемент из начала вектора. В коде использован вектор строковых значений. Значения вектора были напечатаны до и после удаления первого элемента из вектора с помощью функции erase () с одним параметром.
//Include necessary libraries
#include
#include
using namespace std ;
//Display the values of the vector
void display_vector ( vector < string >fruits )
//Initialize the counter
int counter = 1 ;
//Iterate and print the elements of the vector using loop
for ( auto ele = fruits. begin ( ) ; ele ! = fruits. end ( ) ; ele ++ )
//Check the elements is the last element or not
if ( counter ! = fruits. size ( ) )
cout
else
cout
//Increment the counter by 1
counter ++ ;
>
cout
>
int main ( void )
//Declare a vector of string data
vector < string >fruits = < «Orange» , «Banana» , «Mango» , «Jack Fruit» , «Lichi» >;
//Print the existing values of the vector
cout << «The values of the vector before remove: «
display_vector ( fruits ) ;
//Remove the first element from the vector
fruits. erase ( fruits. begin ( ) ) ;
//Print the existing values of the vector after remove
cout << « \n The values of the vector after remove: «
display_vector ( fruits ) ;
return 0 ;
>
Следующий вывод появится после выполнения вышеуказанного кода.

Пример 2: Удалить несколько элементов
Создайте файл C ++ со следующим кодом, чтобы удалить несколько элементов из вектора с помощью функции erase (). В коде использован вектор целочисленных значений. Здесь используются два итератора для установки диапазона элементов, удаленных из вектора. Функция erase () использовалась с двумя параметрами для удаления нескольких элементов из вектора.
//Include necessary libraries
#include
#include
using namespace std ;
//Display the vector
void display_vector ( vector < int >nums )
//Print the values of the vector using loop
for ( auto ele = nums. begin ( ) ; ele ! = nums. end ( ) ; ele ++ )
cout
//Add new line
cout
>
int main ( )
//Declare a vector of integer data
vector < int >intArray < 678 , 435 , 960 , 231 , 800 , 387 , 634 , 267 , 409 , 294 >;
//Print the existing values of the vector
cout
display_vector ( intArray ) ;
//Declare two iterators to remove the range of elements from the vector
vector < int >:: iterator startEle, endEle ;
//Set the iterator to the first position
startEle = intArray. begin ( ) ;
//Increment the starting iterator by 2
advance ( startEle, 2 ) ;
//Set the iterator to the last position
endEle = intArray. end ( ) ;
//Decrement the ending iterator by 3
advance ( endEle, — 3 ) ;
//Remove the range of elements
intArray. erase ( startEle, endEle ) ;
//Print the existing values of the vector after remove
cout
display_vector ( intArray ) ;
return 0 ;
>
Следующий вывод появится после выполнения вышеуказанного кода. В соответствии с диапазоном итераторов удалены элементы с 3-й по 7-ю позицию вектора.

Пример 3: Удалить определенные элементы
Создайте файл C ++ со следующим кодом, чтобы удалить определенные элементы вектора с помощью функции erase (). В коде объявлен вектор из 7 целочисленных элементов. Затем цикл for использовался для перебора элементов вектора и удаления из вектора тех элементов, которые не делятся на 5.
Следующий вывод появится после выполнения вышеуказанного кода. Выходные данные показывают, что вектор содержит только элементы, кратные 5, а другие элементы были удалены.

Заключение
В этом уроке были показаны различные варианты использования функции erase () для удаления векторных элементов. В C ++ есть много других функций для удаления элемента из вектора, и эти функции могут удалять по одному элементу за раз. Но как одиночные, так и множественные элементы из любой позиции вектора могут быть удалены с помощью функции vector erase ().