6.0 KiB
6.0 KiB
Третий семинар
Шаблоны
// template <typename>
template <class T>
void swap(T& a, T& b) {
T tmp;
tmp = a;
a = b;
b = tmp;
}
Можно применять и от нескольких неизвестных параметров
template <typename T, typename K>
void transfer(T fromAccount, T toAccount, K code, int sum)
{
std::cout << "From: " << fromAccount << "\nTo: " << toAccount
<< "\nSum: " << sum << "\nCode: " << code << std::endl;
}
Пример кода для абсолютного значения:
template <class T> T abs(const T& x) {
// template <class T> T abs(T x) {
return x >= 0 ? x : -x;
}
Суммирование элементов массива
template <class T> T sum(T* mas, int N) {
T res = 0;
for (int i = 0; i < N; ++i) {
res += mas[i];
}
return res;
}
int main() {
double mas[5] = {...};
std::cout << sum(mas, 5);
return 0;
}
template <class T> T sum(T* mas, int N) {
T res = 0;
for (int i = 0; i < N; ++i) {
res += mas[i];
}
return res;
}
int main() {
double mas[5] = {...};
std::cout << sum<double, 5>(mas);
return 0;
}
Что-то про стэк
Вторая задача: Суть была реализовывать динамически расширяемый массив
template<class T, int SIZE>
class st {
T st[SIZE];
int top = 0;
public:
void push(T a) {
if (top == SIZE) {
// error
} else {
st[top++] = a;
}
}
T pop();
}
template<class T, int SIZE>
T st<T, SIZE>::pop() {
return st[--top];
}
Если указать стандартное значение для каких-то параметров, вызов обычный
Библиотеки
Контейнеры
Последовательности
- list - двунаправленный список
- vector
- deque - очередь
На их основе создаются:
- stack
- queue
Ассоциативные массивы
- map - отображения
- multimap - ключ может несколько раз встречаться
- set - уникальные упорядоченные ключи
- multiset - совпадающие ключи
Итераторы
#include <algorithm> - подключение библиотеки
- value_type - тип значений в контейнере
- size_type - аналог size_t
- reference/ const reference - ссылки на элемент
- pointer/const pointer - указатели
Исполняют роль указателей
Для каждого контейнера определён:
- iterator - идёт от начала
- reverse_iterator - идёт с конца
- const_iterator - не меняет значений
- const_reverse_iterator - не меняет значений, ревёрс
begin(), end();
rbegin(), rend();
cbegin(), cend(); // для константных
Виды итераторов:
- input
- output
- forward
- bidirectional - list, map, set
- random_access - для vector deque, можно индексировать, += n
#include <vector>
int main() {
vector<int> v1; // длина 0
vector<int> v2(5); // длина 5, занулены
vector<int> v3(10, '*');
int m[] = {1, 2, 3, 4};
vector<int> v4(m, m + 4);
// vector<int> v4(m.begin(), m.end());
}
for (int i = 0; i < v.size(); ++i)
cout << v[i] << " "; // только для random_access контейнера
v[i] == v.at(i) // выдаёт out_of_range, если нет элемента
Печать элементов в прямом и обратном при помощи итераторов
#include <vector>
#include <iostream>
// прямой с помощью прямого
void f1(std::vector<int> mas) {
std::vector<int>::std::iterator iter = mas.begin();
while (iter != mas.end()) {
std::cout << *iter << " ";
iter++;
}
}
// обратный с помощью реверсивного
void f2(std::vector<int> mas) {
std::vector<int>::std::reverse_iterator iter = mas.rbegin();
while (iter != mas.rend()) {
std::cout << *iter << " ";
iter++;
}
}
// обратный с помощью прямого
void f3(std::vector<int> mas) {
std::vector<int>::std::iterator iter = mas.end();
while (iter != mas.begin()) {
--iter;
std::cout << *iter << " ";
}
}
Или же код нормального человека:
for (auto x : v) cout << x << " ";
Алгоритмы
Некоторые методы контейнеров:
size_type size()- количество элементов в контейнереbool empty()- пустой ли контейнерvoid clear()- очищает контейнерvoid push_back()- добавляет в конец value_type<>void pop_back()- удаляет последний элементreference back()- возвращает ссылку на последний элементreference front()- возвращает ссылку на первый элементiterator insert(iterator p, value_type<>)- вставка перед позицией p, возвращает на новый элементiterator erase(iterator p)- удаляет, куда указывает, возвращает итератор на некст элементiterator erase(iterator p1, iterator p2)- c первого до последнего (не включительно)
для list, deque
void push_front(value_type<>)void pop_front(value_type<>)
Для bidirectional итераторов можно использовать
advance(p1, 3)для плюсаn = distance(p1, p2)для вычитания
void f(vactor<char>& mas) {
auto iter = mas.begin();
while (iter < mas.end()) {
++iter;
if (iter != mas.end())
iter = mas.erase(iter);
}
}