- •Содержание Введение
- •Задача 1: Обнаружить учетку памяти
- •Задача 2. Составить тесты к программе
- •Задача 3: Напечатать все содержимое файла на экран.
- •Задача 3: Напечатать все содержимое файла на экран (оптимизация).
- •Задача 4. Удалить все нечетные элементы из массива
- •Задача4.Удалить все нечетные элементы из массива (оптимизация)
- •Задача 4. Удалить все нечетные элементы из массива (последующая оптимизация)
- •Задача 4. Удалить все нечетные элементы из массива (основа тестов)
- •Задача 5. В файле удалить все слова, которые начинаются и заканчиваются одной буквой
- •Задача 5. В файле удалить все слова, которые начинаются и заканчиваются одной буквой (без использования потоков и std::string)
- •Задача 6. Удалить строки, в которых есть два одинаковых элемента (без использования std::vector)
- •Задача 6. Удалить строки, в которых есть два одинаковых элемента (c использованием std::vector)
- •Задача 7. Отсортировать содержимое словаря
- •Задача 8. Реализовать сохранение и загрузку пользовательских структур данных с использованием fstream
- •Заключение Глоссарий
- •Список рекомендуемой литературы
Задача4.Удалить все нечетные элементы из массива (оптимизация)
Следует отметить, что в С++ существует Standart Type Library (STL). В ней существует множество готовых классов и функций, которые можно использовать.
Название |
Реализуемыя структура |
bitset |
Битовый массив |
deque |
Очередь с двухсторонним доступом |
list |
Двухсвязанный список |
map |
Ассоциативный массив |
multimap |
Мультиотображение |
queue |
Односторонная очередь(контейнер-адаптор) |
set |
Множество |
stack |
Стек (контейнер-адаптор) |
vector |
Динамический массив |
В этой таблице некоторые строки отмечены как контейнеры-адапторы. Это означает, что это «обертка» над другим классом, но этот тип структур реализован на чем-то ином (для примера, queue реализован на list).
Одним из готовых классов является класс vector, для работы с которым надо подключить #include <vector>. Следует отметить, что он является шаблонным. Для его использования (для работы с целыми числами) надо написать std::vector<int>. Он обладает множеством полезных методов. Поэтому предыдущий вариант решения можно оптимизировать.
При вводе вектора, с учетом того, что известено количество вводимых данных, желательно зарезервировать нужные количество элементов, что бы избежать лишних перевыделейний памяти. Каждый новый элемент данных необходимо добавлять в конец вектора (это можно сделать с помощью операции push_back). Таким образом, функция ввода будет выглядить следующим образом:
void fillVector(vector<int> &data, int size) {
data.reserve(size);
for (int i = 0; i < size; i++) {
data.push_back(getRandValue(-5, 10));
}
}
При выводе вектора можно воспользоваться функцией size() для получения использованного количества элементов. Функция вывода будет иметь следующий вид:
void printVector(char *caption, vector<int> &data) {
cout << caption << ": ";
for (int i = 0; i < data.size(); i++) {
cout << data[i] << " ";
}
cout << "\n";
}
Отдельно следует отметить наличие ссылки (&) при передаче vector<int> в аргументах функции. С точки зрения логики она не нужна. Однако, если её не будет, то при вызове функции будет передаваться копия вектора. А операция создания копии вектора может быть весьма затратной, поэтому для увеличения скорости работы добавление ссылки обосновано.
Для следующей оптимизации необходимо учесть, что vector имеет функцию erase для удаления цепочки элементов. Цепочка характеризуется позицией начала и позицией конца. При этом удаляются все элементы в диапазоне [начало, конец). Так же следует отметить, что начало цепочки указывается от начала вектора, которое можно получить с помощью функции вектора begin(). C учетом этого главная функция обработки будет выглядить следующим образом:
void mainAction(vector<int> &data) {
for (int i = data.size() - 1; i >= 0; i--) {
if (data[i] % 2 == 1) {
data.erase(data.begin() + i, data.begin() + i + 1);
}
}
}
Приведем таблицу наиболее часто встречающихся функций класса vector
Название метода |
Выполняемые действия |
|
|
|
|
Приведем полный код решения:
#include <vector>
#include <time.h>
#include <conio.h>
#include <iostream>
using namespace std;
void mainAction(vector<int> &data) {
for (int i = data.size() - 1; i >= 0; i--) {
if (data[i] % 2 == 1) {
data.erase(data.begin() + i, data.begin() + i + 1);
}
}
}
int getCorrectValue() {
while (true) {
int size;
if (!(cin >> size)) {
cin.clear();
while(std::cin.get()!= '\n');
continue;
}
return size;
}
}
void printVector(char *caption, vector<int> &data) {
cout << caption << ": ";
for (int i = 0; i < data.size(); i++) {
cout << data[i] << " ";
}
cout << "\n";
}
int getRandValue(int max, int min) {
return (((double)rand())/RAND_MAX)*(max - min) + min;
}
void fillVector(vector<int> &data, int size) {
data.reserve(size);
for (int i = 0; i < size; i++) {
data.push_back(getRandValue(-5, 10));
}
}
int main(int argc, char* argv[]) {
srand(time(NULL));
cout << "enter array size: ";
int size = getCorrectValue();
if (size < 0) {
cout << "array size can not be negative number";
_getch();
return 1;
}
vector<int> data;
fillVector(data, size);
printVector("before process", data);
mainAction(data);
printVector("after process", data);
_getch();
return 0;
}