C++. STL. Алгоритмы. Алгоритмы обмена значениями элементов последовательности

Модифицирующие алгоритмы. Часть 2
Алгоритмы обмена значениями элементов последовательности

1. Алгоритм swap. Обмен значениями двух переменных (объектов)

Для обмена значениями двух объектов или массивов используется алгоритм swap. Алгоритм имеет несколько реализаций, наиболее распространенные из которых следующие

template <class Type>
void swap(
  Type& left,
  Type& right);
  template <class Type, size_t N>
  void swap(
  Type (& left)[N],
  Type (& right)[N]);

здесь

  • left, right – объекты, значение которых нужно обменять местами;
  • N – размер массивов объектов.

Пример.

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

int main()
{
  // Алгоритм swap - обмен значениями
  // 1. Обмен типов int
  int a = 8, b = 9;
  swap(a, b);
  cout << "a = " << a << ", b = " << b << endl; // a = 9, b = 8

  // 2. Обмен массивов фиксированного размера
  int A1[] = { 1, 5, 3 };
  int A2[] = { 2, 8, 4 };

  swap(A1, A2);

  cout << "A1 => ";
  for (int i : A1)
    cout << i << " ";
  cout << endl;

  cout << "A2 => ";
  for (int i : A2)
    cout << i << " ";
  cout << endl;

  // 3. Обмен значениями указателей unique_ptr<T>
  unique_ptr<int> p1(new int(38));
  unique_ptr<int> p2(new int(29));
  swap(p1, p2);
  cout << "p1->" << *p1 << endl;
  cout << "p2->" << *p2 << endl;

  // 4. Обмен значениями указателей shared_ptr<T>
  shared_ptr<int> ps1(new int(100));
  shared_ptr<int> ps2(new int(50));
  swap(ps1, ps2);
  cout << "ps1->" << *ps1 << endl;
  cout << "ps2->" << *ps2 << endl;

  // 5. Обмен значениями векторов
  vector<int> v1 = { 1, 3, 8, 4 };
  vector<int> v2 = { 7, 9, 0 };
  swap(v1, v2);
  cout << "v1 => ";
  for (int i : v1)
    cout << i << " ";
  cout << endl;
  cout << "v2 => ";
  for (int i : v2)
    cout << i << " ";
  cout << endl;
}

Результат

a = 9, b = 8
A1 => 2 8 4
A2 => 1 5 3
p1->29
p2->38
ps1->50
ps2->100
v1 => 7 9 0
v2 => 1 3 8 4
2. Алгоритм swap_ranges. Обменять местами диапазоны элементов двух последовательностей

Алгоритм swap_ranges меняет местами элементы двух диапазонов. Наиболее распространенная реализация алгоритма имеет следующий вид

template <class ForwardIterator1, class ForwardIterator2>
ForwardIterator2 swap_ranges(
  ForwardIterator1 first1,
  ForwardIterator1 last1,
  ForwardIterator2 first2 );

здесь

  • first1, last1 – прямые итераторы, задающие первый диапазон элементов;
  • first2 – прямой итератор, задающий начало второго диапазона элементов.

Пример.

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

int main()
{
  // Алгоритм swap_ranges - меняет местами элементы заданного диапазона

  // 1. Объявить 2 вектора и вывести их на экран
  vector<char> V1 = { 'a', 'b', 'c', 'd', 'e', 'f' };
  vector<char> V2 = { '0', '1', '2', '3', '4' };

  cout << "V1 => ";
  for (char c : V1)
    cout << c << " ";
  cout << endl;

  cout << "V2 => ";
  for (char c : V2)
    cout << c << " ";
  cout << endl;
  cout << "-------------------" << endl;

  // 2. Создать итераторы на начало и конец диапазона вектора V1
  vector<char>::iterator itBegin = V1.begin();
  vector<char>::iterator itEnd = V1.begin();
  itEnd++;
  itEnd++; // itEnd -> 'c'

  // 3. Создать итераторы на начало и конец диапазона вектора V2
  vector<char>::iterator itBegin2 = V2.begin();
  itBegin2 += 3; // itBegin2 -> '3'

  // 4. Вызов алгоритма
  swap_ranges(itBegin, itEnd, itBegin2);

  // 5. Вывести вектор V1
  cout << "V1 => ";
  for (char c : V1)
    cout << c << " ";
  cout << endl;

  // 6. Вывести вектор V2
  cout << "V2 => ";
  for (char c : V2)
    cout << c << " ";
  cout << endl;
}

Результат

V1 => a b c d e f
V2 => 0 1 2 3 4
-------------------
V1 => 3 4 c d e f
V2 => 0 1 2 a b

 

3. Алгоритм iter_swap. Обмен местами двух значений, на которые указывают итераторы

Алгоритм iter_swap производит обмен местами двух значений, на которые указывают итераторы. Согласно документации, шаблон алгоритма следующий

template <class ForwardIterator1, class ForwardIterator2>
void iter_swap( ForwardIterator1 left, ForwardIterator2 right );

здесь

  • left – итератор на первое значение (значение, размещаемое слева);
  • right – итератор на второе значение (значение, размещаемое справа).

Пример.

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

int main()
{
  // Алгоритм iter_swap - меняет местами два значения, на которые указывают итераторы

  // 1. Объявить вектор
  vector<double> V1 = { 1.1, 2.2, 2.7, 2.8, 3.2 };

  // 2. Вывести вектор
  cout << "V1 => ";
  for (double x : V1)
    cout << x << " ";
  cout << endl;

  // 3. Установить итераторы на первый и последний элемент вектора
  vector<double>::iterator it1 = V1.begin();
  vector<double>::iterator it2 = V1.begin();
  while (it2 != V1.end()) it2++;
  it2--;

  // 4. Обменять местами - алгоритм iter_swap
  iter_swap(it1, it2);

  // 5. Повторно вывести вектор V1
  cout << "V1 => ";
  for (double x : V1)
    cout << x << " ";
  cout << endl;
}

Результат

V1 => 1.1 2.2 2.7 2.8 3.2
V1 => 3.2 2.2 2.7 2.8 1.1