Решение задач с контейнером vector

Передача вектора в функцию по ссылке

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

//============================================================================
// Name        : lesson-17a-1.cpp
//============================================================================
#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <iomanip>
using namespace std;
void iomass(vector<int>&, int, int);
void iomass(vector<int>&);

int main() {
    vector<int> mass(20);
    srand(time(0));
    int a, b;
    cout << "a = "; cin >> a;
    cout << "b = "; cin >> b;
    iomass(mass, a, b);
    iomass(mass);
    return 0;
}
void iomass(vector<int>& A, int x, int y) {
	for (auto &ar: A) {
	        ar = x + rand() % (y - x);
	        cout << ar << setw(4);
	    }
}
void iomass(vector<int>& A) {
	for (auto &ar: A)
	    	cout << ar << setw(4);
}

В следующих задачах определения этих функций будут опущены.

Удаление и итераторы

Дан целочисленный массив размера N (> 2). Удалить из массива все элементы с нечетными номерами (1, 3, ...). Условный оператор не использовать.
В постановке задачи имеется ввиду, что нельзя использовать условный оператор для перебора индексов. Мы же используем его для других целей: проверка положения итератора first для четного числа элементов массива.
Программа 17a.2

//============================================================================
// Name        : lesson-17a-2.cpp
//============================================================================
#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <iterator>
#include <iomanip>
using namespace std;
void iomass(vector<int>&, int, int);
void iomass(vector<int>&);

int main()
{
    int N;
    cout << "N = "; cin >> N;
    vector<int> mass(N);
    //==================================================//
    //  Заполнение и вывод элементов исходного массива  //
    //==================================================//
    srand(time(0));
    int a, b;
    cout << "a = "; cin >> a;
    cout << "b = "; cin >> b;
    iomass(mass, a, b);
    //=====================//
    //  Реализация задачи  //
    //=====================//
    auto first = mass.begin() + 1;
    while (first != mass.end()) {
        first = mass.erase(first);
        if (first == mass.end()) break;
        else first++;
    }
    //=======================================//
    //  Вывод элементов измененного массива  //
    //=======================================//
    cout << "\n";
    iomass(mass);
    return 0;
}

Если, как мы уже говорили, количество элементов в векторе четное, то на последнем шаге удаление элемента с нечетным индексом приведет к тому, что итератор first станет равным итератору last (последующая инкрементация приведет их недействительности), поэтому осуществляется проверка равенства first и last. Эту задачу можно решить способом создания временного массива, как показано в следующем примере. Однако, следует учитывать, что будет увеличиваться объем затраченной памяти.
Дан целочисленный массив размера N. Удалить из массива все элементы, встречающиеся ровно два раза, и вывести размер полученного массива и его содержимое.
Программа 17a.3

//============================================================================
// Name        : lesson-17a-3.cpp
//============================================================================
#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <iterator>
#include <algorithm>
#include <iomanip>
using namespace std;
void iomass(vector<int>&, int, int);
void iomass(vector<int>&);

int main() {
    vector<int> mass(20);
    vector<int> temp;
    temp.reserve(20);
    //==================================================//
    //  Заполнение и вывод элементов исходного массива  //
    //==================================================//
    srand(time(0));
    int a, b;
    cout << "a = "; cin >> a;
    cout << "b = "; cin >> b;
    iomass(mass, a, b);
    //=====================//
    //  Реализация задачи  //
    //=====================//
    auto first = mass.begin();
    auto last = mass.end();
    for (size_t i = 0; i < mass.size(); i++) {
    	if (count(first, last, mass.at(i)) != 2)
    		temp.push_back(mass.at(i));
    }
    mass = temp;
    temp.~vector();
    //=======================================//
    //  Вывод элементов измененного массива  //
    //=======================================//
    cout << "\nРазмер модифицированного массива: "
    	 << mass.size()
		 << "\nЭлементы массива:\n";
    iomass(mass);
    return 0;
}

В данной программе (стр. 33) используется функция count(first, last, value) из библиотеки обобщенных алгоритмов, для включения которой мы использовали соответствующий заголовок. Эта функция возвращает количество элементов равных value из промежутка [first, last).
Примечание. Класс vector имеет специальную функцию – деструктор: ~vector(), которая освобождает выделенную (другой специальной функцией – конструктором) память. Деструктор вызывается неявно, когда vector выходит из области видимости (но не в нашем случае, поэтому он вызван явно), вся занятая им память будет освобождена для дальнейшего использования. Поэтому прибегать к использованию операций new и delete с использованием указателя нет необходимости!
Перепишем программу 17a.3 в которой мы будем создавать экземпляр класса vector как указатель (стр. 3). Собственно разницы создания указателя для динамической переменной и для объекта vector нет. Но в коде мы увидим некоторую особенность, а именно: использование операции "->" (стрелка) для обращения к методам класса (подробнее с этой операцией мы познакомимся позднее).

int main() {
    vector<int> mass(20);
    vector<int> *temp = new vector<int>;
    temp -> reserve(20);
    srand(time(0));
    int a, b;
    cout << "a = "; cin >> a;
    cout << "b = "; cin >> b;
    iomass(mass, a, b);
    auto first = mass.begin();
    auto last = mass.end();
    for (size_t i = 0; i < mass.size(); i++) {
        if (count(first, last, mass.at(i)) != 2)
            temp -> push_back(mass.at(i));
    }
    mass = *temp;
    delete temp;
    cout << "\nРазмер модифицированного массива: "
         << mass.size()
         << "\nЭлементы массива:\n";
    iomass(mass);
    return 0;
}
Print Friendly, PDF & Email

Comments are closed.