C++. STL. Модифицирующие методы. Часть 4. Алгоритмы, извлекающие из последовательности отдельные элементы или группы элементов

Модифицирующие методы. Часть 4.
Алгоритмы, извлекающие из последовательности отдельные элементы или группы элементов


Содержание


Поиск на других ресурсах:

1. Алгоритм remove. Удалить элемент из последовательности на основе его значения

 

#include <iostream>
#include <list>
#include <algorithm>
#include <vector>
#include <functional>
#include <time.h>
using namespace std;

void main()
{
  // Алгоритм remove - удалить элемент из последовательности на основе его значения.
  // 1. Создать список случайных чисел в пределах [1; 20]
  list<int> l;
  srand(time(NULL));
  for (int i = 0; i < 15; i++)
    l.push_back(rand() % (20 - 1 + 1) + 1);

  // 2. Вывести сформированный список
  cout << "List of integers:\n";

  // 2.1. Объявить итератор
  list<int>::iterator it;

  // 2.2. Установить итератор на первый элемент списка
  it = l.begin();

  // 2.3. Цикл вывода списка-оригинала
  while (it != l.end())
  {
    cout << *it << " ";
    it++;
  }
  cout << endl << endl;

  // 3. Использование алгоритма remove.
  // Удалить все элементы, равные 5.
  // 3.1. Вычислить кол-во элементов, которые равны 5 - использовать алгоритм count
  int value_5 = count(l.begin(), l.end(), 5);

  // 3.2. Удалить элементы, равные 5 - вызвать алгоритм remove
  remove(l.begin(), l.end(), 5);

  // 3.3. Изменить размер последовательности l
  l.resize(l.size() - value_5);

  // 4. Вывести новую результирующую последовательность
  cout << "A new sequence: " << endl;
  it = l.begin();
  while (it != l.end())
  {
    cout << *it << " ";
    it++;
  }
}

Результат

List of integers:
10 20 5 12 3 7 12 13 4 20 2 6 18 10 3

A new sequence:
10 20 12 3 7 12 13 4 20 2 6 18 10 3

 

2. Алгоритм remove_if. Удалить элементы из последовательности, удовлетворяющие заданному условию

 

#include <iostream>
#include <list>
#include <algorithm>
#include <vector>
#include <functional>
#include <time.h>
using namespace std;

// Предикат, определяющий, больше ли число 10
bool More_Than_10(int value)
{
  return value > 10;
}

void main()
{
  // Алгоритм remove_if – удалить все элементы из последовательности
  // соответствующие заданному значению.
  // 1. Создать список случайных чисел в пределах [1; 20]
  list<int> l;
  srand(time(NULL));
  for (int i = 0; i < 15; i++)
    l.push_back(rand() % (20 - 1 + 1) + 1);

  // 2. Вывести сформированный список
  cout << "List of integers:\n";

  // 2.1. Объявить итератор
  list<int>::iterator it;

  // 2.2. Установите итератор на первый элемент списка
  it = l.begin();

  // 2.3. Цикл вывода списка-оригинала
  while (it != l.end())
  {
    cout << *it << " ";
    it++;
  }
  cout << endl << endl;

  // 3. Использование алгоритма remove_if.
  // Удалить все элементы, которые более 10.
  // Задается предикат More_Than_10
  // 3.1. Вычислить количество элементов, которые больше 10 - алгоритм count_if
  int count = count_if(l.begin(), l.end(), More_Than_10);

  // 3.2. Сформировать новый список – размер списка остается 15
  remove_if(l.begin(), l.end(), More_Than_10);

  // 3.3. Изменить размер списка
  l.resize(l.size() - count);

  // 4. Вывести новую результирующую последовательность
  cout << "A new sequence: " << endl;
  it = l.begin();
  while (it != l.end())
  {
    cout << *it << " ";
    it++;
  }

  // 5. Вывести новый размер списка
  cout << endl << l.size() << endl;
}

Результат

List of integers:
4 3 12 14 16 12 7 13 2 18 2 18 9 12 13

A new sequence:
4 3 7 2 2 9
6

 

3. Алгоритм remove_copy. Удаление элементов из последовательности и создание новой последовательности.

 

#include <iostream>
#include <list>
#include <algorithm>
#include <vector>
#include <functional>
#include <time.h>
using namespace std;

void main()
{
  // Алгоритм remove_copy.
  // Алгоритм удаляет элементы из заданного диапазона и создает новую копию последовательности.

  // 1. Создать список случайных символов
  list<char> l;
  srand(time(NULL));
  for (int i = 0; i < 15; i++)
    l.push_back((int)'a' + rand() % 26);

  // 2. Вывести сформированный список
  cout << "List of characters:\n";

  // 2.1. Объявить итератор
  list<char>::iterator it;

  // 2.2. Установить итератор на первый элемент списка
  it = l.begin();

  // 2.3. Цикл вывода списка-оригинала
  while (it != l.end())
  {
    cout << *it << " ";
    it++;
  }
  cout << endl << endl;

  // 3. Использование алгоритма remove_copy().
  // Удалить все символы 'f'
  // 3.1. Объявить новый список такого же размера как список l
  list<char> l2(l.size());

  // 3.2. Вызвать алгоритм remove_copy
  remove_copy(l.begin(), l.end(), l2.begin(), 'f');

  // 3.3. Вывести новую результирующую последовательность
  cout << "A new sequence: " << endl;
  it = l2.begin();
  for (int i = 0; i < l2.size(); i++)
  {
    cout << *it << " ";
    it++;
  }
  cout << endl;
}

Результат

List of characters:
l o s f q q h f q t u m j y j

A new sequence:
l o s q q h q t u m j y j

 

4. Алгоритм remove_copy_if. Удалить элементы из последовательности на основе заданного условия с созданием последовательности-копии

 

#include <iostream>
#include <list>
#include <algorithm>
#include <vector>
#include <functional>
#include <time.h>
using namespace std;

// Предикат, который определяет, меньше ли значение 5
bool LessThan_5(int value)
{
  return value < 5;
}

void main()
{
  // Алгоритм remove_copy_if.
  // Алгоритм удаляет элементы из заданного диапазона, соответствующие заданному условию.
  // Алгоритм создает новую последовательность-копию.

  // 1. Создать список случайных чисел в пределах [1; 20]
  list<int> l;
  srand(time(NULL));
  for (int i = 0; i < 15; i++)
    l.push_back(rand() % (20 - 1 + 1) + 1);

  // 2. Вывести сформированный список
  cout << "List of integers:\n";

  // 2.1. Объявить итератор
  list<int>::iterator it;

  // 2.2. Установить итератор на первый элемент списка
  it = l.begin();

  // 2.3. Цикл вывода списка-оригинала
  while (it != l.end())
  {
    cout << *it << " ";
    it++;
  }
  cout << endl << endl;

  // 3. Использование алгоритма remove_copy_if().
  // Удалить все элементы, которые меньше 5
  // 3.1. Огласить новый список такого же размера как список l
  list<int> l2(l.size());

  // 3.2. Вызвать алгоритм remove_copy_if – сформировать список элементов,
  // имеющих значение больше 5. Для этого используется предикат MoreThan_5
  remove_copy_if(l.begin(), l.end(), l2.begin(), LessThan_5);

  // 3.3. Вывести новую результирующую последовательность
  cout << "A new sequence: " << endl;
  it = l2.begin();
  for (int i = 0; i < l2.size(); i++)
  {
    cout << *it << " ";
    it++;
  }
  cout << endl;

  // 4. Использование алгоритма remove_copy_if() в сочетании с лямбда-выражением.
  // 4.1. Объявить новый список такого же размера как список l.
  list<int> l3(l.size());

  // 4.2. Вызвать алгоритм с лямбда-выражением
  remove_copy_if(l.begin(), l.end(), l3.begin(), [](int value) { return value < 5; });

  // 4.3. Вывести результат
  cout << "A new sequence: " << endl;
  it = l3.begin();
  while (it != l3.end())
  {
    cout << *it << " ";
    it++;
  }
  cout << endl;
}

Результат

List of integers:
5 11 1 6 19 3 20 8 18 11 3 2 14 19 2

A new sequence:
5 11 6 19 20 8 18 11 14 19 0 0 0 0 0
A new sequence:
5 11 6 19 20 8 18 11 14 19 0 0 0 0 0

Как видно из результата, данный алгоритм не изменяет размера результирующей последовательности. Размер можно задать через использование алгоритма count_if и метода resize() контейнера list<T> (смотрите как это сделано в алгоритмах remove и remove_if).

 

5. Алгоритм unique. Извлечь дубликаты из последовательности

 

#include <iostream>
#include <vector>
#include <list>
#include <functional>
#include <algorithm>
using namespace std;

// Предикат, определяющий равенство элементов
bool Equal_Items(int a, int b)
{
  // следующий элемент больше предыдущего на 1
  return a + 1 == b;
}

int main()
{
  // Алгоритм unique - извлечь дубликаты из последовательности
  // { ... 3, 3, 3, ... } => { ... 3 ... }

  // 1. Использование unique без предиката
  // 1.1 Создать последовательность чисел и вывести ее на консоль
  list<int> L1 = { 2, 8, 2, 2, 3, 4, 5, 8, 1 };
  cout << "L1 => ";
  for (int i : L1)
    cout << i << " ";
  cout << endl;

  // 1.2. Объявить итератор, указывающий на конец новой последовательности
  list<int>::iterator endL1;

  // 1.3. Создать другую последовательность, не содержащую дубликатов
  endL1 = unique(L1.begin(), L1.end());

  // 1.4. Вывести результирующую последовательность L1 до итератора endL1
  cout << "L1+ => ";
  list<int>::iterator it = L1.begin();
  while (it != endL1)
  {
    cout << *it << " ";
    it++;
  }
  cout << endl;

  // 2. Использование алгоритма с предикатом
  // 2.1. Создать последовательность чисел и вывести ее на консоль
  list<int> L2 = { 2, 8, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 8, 5 };
  cout << "L2 => ";
  for (int i : L2)
    cout << i << " ";
  cout << endl;

  // 2.2. Огласить итератор, который будет указывать на конец новой последовательности
  list<int>::iterator endL2;

  // 2.3. Вызвать алгоритм unique
  endL2 = unique(L2.begin(), L2.end(), Equal_Items);

  // 2.4. Вывести последовательность L2 до итератора endL2
  cout << "L2+ => ";
  list<int>::iterator it2 = L2.begin();
  while (it2 != endL2)
  {
    cout << *it2 << " ";
    it2++;
  }
  cout << endl;
}

Результат

L1 => 2 8 2 2 3 4 5 8 1
L1+ => 2 8 2 3 4 5 8 1
L2 => 2 8 2 2 2 3 3 4 4 4 5 5 5 5 8 5
L2+ => 2 8 2 2 2 4 4 4 8 5

 

6. Алгоритм unique_copy. Вытащить дубликаты из последовательности с получением новой последовательности

 

#include <iostream>
#include <vector>
#include <list>
#include <functional>
#include <algorithm>
using namespace std;

// Предикат, определяющий равенство элементов
bool Equal_Items(int a, int b)
{
  // следующий элемент больше предыдущего на 1
  return a + 1 == b;
}

int main()
{
  // Алгоритм unique_copy – извлечь дубликаты из последовательности
  // с получением новой последовательности-копии
  // { ... 3, 3, 3, ... } => { ... 3 ... }

  // 1. Использование unique_copy без предиката
  // 1.1 Создать последовательность чисел и вывести ее на консоль
  list<int> L1 = { 2, 8, 2, 2, 2, 3, 3, 4, 5, 8, 1 };
  cout << "L1 => ";
  for (int i : L1)
    cout << i << " ";
  cout << endl;

  // 1.2. Создать последовательность, в которую будет записываться результат
  list<int> L2(L1.size());

  // 1.3. Объявить итератор, указывающий на конец новой последовательности
  list<int>::iterator endL2;

  // 1.4. Создать другую последовательность, не содержащую дубликатов
  endL2 = unique_copy(L1.begin(), L1.end(), L2.begin());

  // 1.5. Вывести результирующую последовательность L2 до итератора endL2
  cout << "L2 => ";
  list<int>::iterator it = L2.begin();
  while (it != endL2)
  {
    cout << *it << " ";
    it++;
  }
  cout << endl;

  // 2. Использование алгоритма с лямбда-выражением
  // 2.1. Создать последовательность чисел и вывести ее на консоль
  list<int> L3 = { 2, 8, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 8, 5 };
  cout << "L3 => ";
  for (int i : L3)
    cout << i << " ";
  cout << endl;

  // 2.2. Создать последовательность, в которую будет записываться результат
  list<int> L4(L3.size());

  // 2.3. Объявить итератор, указывающий на конец новой последовательности
  list<int>::iterator endL4;

  // 2.4. Вызвать алгоритм unique_copy на основе лямбда-выражения
  // Лямбда-выражение задает правило:
  // если предыдущий элемент больше следующего, то объединить эти 2 элемента,
  // остается прежний элемент.
  endL4 = unique_copy(
    L3.begin(), // начало исходной последовательности
    L3.end(), // конец исходной последовательности
    L4.begin(), // начало результирующей последовательности
    [](int a, int b) { return a > b; } // здесь может быть также соответствующий предикат
  );

  // 2.5. Вывести последовательность L2 до итератора endL2
  cout << "L2+ => ";
  list<int>::iterator it2 = L4.begin();
  while (it2 != endL4)
  {
    cout << *it2 << " ";
    it2++;
  }
  cout << endl;
}

Результат

L1 => 2 8 2 2 2 3 3 4 5 8 1
L2 => 2 8 2 3 4 5 8 1
L3 => 2 8 2 2 2 3 3 4 4 4 5 5 5 5 8 5
L2+ => 2 8 8

 


Связанные темы