Прикладное программирование
кафедра
прикладной и компьютерной оптики
Составные типы данных
2
Составные типы данных
Гомогенные Гетерогенные
Назначение
для хранения однотипных
переменных
для хранения неоднородных
разнотипных переменных
Пример
массив, строка,
список, стек, очередь,
набор, карта, дерево
структура, класс
3
Массивы
Массив - это группа последовательных ячеек памяти,
имеющих один и тот же тип
int data[4];
Нумерация элементов – от 0 до <размер-1>
data[0]=1;
data[1]=2;
data[2]=3;
data[3]=4;
Объявление и инициализация
double v[3]={0.3, 2.2, 2.};
char symbols[]={'a', 'b', 'c', 'd', 'e'};
4
Динамическое размещение
массива
double *data; // указатель на массив
data=new double[1000]; // указатель на 0-й элемент массива
// инициализация
for(int i=0; i<1000; i++)
{
data[i]=0.;
}
delete [] data; // обязательно освободить память
data+1; // указатель на 1-й элемент
data+100; // указатель на 100-й элемент,
*(data+4); // эквивалентно data[4]
См. пример программы
5
Передача массива в функцию
Передача массива в функцию может осуществляться только
по указателю на нулевой элемент, с дополнительной
информацией о количестве элементов в массиве
// указатель на массив + количество элементов в массиве
double sum(double* m, int n) // или double m[]
{
double s=0.;
for(int i=0; i<n; ++i)
{
s+=m[i];
}
return s;
}
См. пример программы
6
Двумерный массив
Для создания двумерного массива необходимо указать в квадратных
скобках два значения – количество строк и столбцов в массиве
double matrix[3][2]; // двумерный массив 2х3
double sum=0.;
for(int i=0; i<3; i++) // номер строки
{
for(int j=0; j<2; j++) // номер столбца
{
sum+=matrix[i][j];
}
}
matrix[0][0];
matrix[2][1];
[0][0] [0][1]
[1][0] [1][1]
[2][0] [2][1]
[0][0] [0][1] [1][0] [1][1] [2][0] [2][1]
7
Динамическое размещение
двумерного массива
Двумерный массив можно разместить динамически, только если
представить его как одномерный
 вместо доступа по индексам [i][j], придется вычислять индекс одномерного
массива, которому будет соответствовать необходимый элемент двумерного
массива
• Например, элементу [1][0] двумерного массива будет соответствовать индекс [2] одномерного
массива
// указатель на двумерный массив matrix[3][2]
double *matrix=new double[3*2];
// matrix[i][j]
matrix[i*2+j]=0.;
// например matrix[1][0]
matrix[1*2+0]=0.;
delete [] matrix; //освободить память
0 1 2 3 4 5
[0][0] [0][1] [1][0] [1][1] [2][0] [2][1]
См. пример программы
8
Контейнеры
Контейнер – тип данных, предназначенный для хранения
однотипных данных
 вектор, стек, очередь, список, ассоциативный массив, дерево
Хранение элементов контейнера
 последовательно (непрерывным блоком)
 разбросаны по всей памяти
Доступ к элементам контейнера
 по индексу
 только последовательным перебором
9
STL (Standard Template Library) –
стандартная библиотека шаблонов
Контейнеры
 объекты для хранения однотипных данных:
• последовательные (vector, deque, list);
• ассоциативные (set, multiset, map, multimap);
Адапторы
 объекты, созданные на основе базовых контейнеров, с измененным
интерфейсом (например, queue, stack)
Итераторы
 объекты, которые используются для универсального доступа к элементам
хранящимся в контейнере любого типа
Алгоритмы
 обобщенные процедуры для обработки элементов любых контейнеров
Функции-объекты
 объекты, у которых перегружен оператор вызова функций
10
Контейнеры:
вектор, стек, очередь
Вектор
 хранение элементов единым блоком
 доступ к любому элементу по индексу
Стек
 хранение элементов единым блоком
 доступ только к последнему элементу,
внесенному в стек
Очередь
 хранение элементов единым блоком
 доступ только к первому элементу,
внесенному в очередь
11
Контейнеры: список, дерево,
ассоциативный массив
Список
 элементы разбросаны по памяти
• каждый элемент содержит указатель на
последующий и предыдущий
 только перебор
Дерево
 элементы разбросаны по памяти
 обхода дерева от корня
• родитель содержит ссылки на дочерние
элементы
Ассоциативный массив
 элементы разбросаны по памяти
 обход дерева по ключу
12
Вектор
Вектор - одномерный массив проиндексированных элементов
• Доступ к функциям вектора производится через оператор "."
• Подробнее о классах и шаблонах см. главу 4 и раздел 5.4.
#include <vector>
using namespace std;
vector<double> x; // создание вектора
x.resize(10); // изменение размера вектора
x.resize(x.size()+100); // изменение размера вектора
double sum=0.0;
for(int i=0; i<x.size(); i++)
{
sum+=x[i]; //доступ по индексу
}
13
Функции работы с вектором
Размер (количество элементов) контейнера
int n=x.size();
Изменение размера контейнера
x.resize(100);
Доступ к элементам контейнера
x[i]=5;
Добавить элемент в конец контейнера
• Добавляет копию элемента
x.push_back(7);
Определяет пустой ли контейнер
bool res=x.empty(); // эквивалентно x.size() == 0
Очистить контейнер
• разрушает все элементы и освобождает контейнер
x.clear();
Выделение дополнительной памяти для размещения новых эл-в
x.reserve(200);
Определяет кол-во элементов, для которых зарезервирована.память
int n=x.capacity();
Остальные функции – см.Приложение 5 См. пример программы
14
Список
Список – структура данных для организации хранения
элементов с эффективной вставкой и удаления в любом
месте этой структуры, не требует доступа по индексу
 УЗЕЛ (Node) – объект, который содержит ссылки на последующий и
предыдущий элементы, а также значение данного элемента списка
Простой односвязный список
Простой двухсвязный список
Кольцевой двухсвязный список
15
Функции списка
STL – простой двухсвязный список
list<int> example;
example.push_back(0); // вставка в конец
example.push_front(1); // вставка в начало
x.insert(x.begin(), 3); // вставка в любое место списка
 (переразмещения данных в памяти не происходит)
16
Итераторы
Итератор – это обобщённый "указатель" на элемент,
хранящийся в контейнере
list<double> ls;
list<double>::iterator it;
 оператор * – разыменование и получение доступа к значению элемента
(*it)=5;
 операторы «++» и «– –» получение указателя на следующий и
предыдущий элемент
it++, it--
 итератор на первый элемент контейнера
it=ls.begin()
 итератор на следующий после последнего элемент контейнера
it=ls.end()
17
Использование итераторов
list<double> x;
list<double>::iterator it;
for(it=x.begin(); it!=x.end(); it++)
{
sum+=(*it); //доступ к элементам по итератору
}
it=x.begin();
while(it!=x.end())
{
sum+=*it;
it++;
}
См. пример программы
18
Двусторонняя очередь (deque)
Двусторонняя очередь – последовательность, которая:
 поддерживает произвольный доступ к элементам (аналогично vector)
 поддерживает вставку и удаление в начало последовательности
 Кроме того:
• не имеет функций-членов capacity() и reserve()
• не предоставляет никаких гарантий на допустимость итератора
См. пример программы
19
Стек (stack)
Стек – адаптер очереди, который организует ее работу по
правилу "last in, first out" (LIFO)
 не предоставляет функций для получения итераторов и их перебора
 позволяет проверить, какой элемент находится на вершине стека (top)
stack<int> s;
s.push(8); // s = 8
s.push(7); // s = 7 8
s.push(4); // s = 4 7 8
cout<<s.top()<<endl; // 4
s.pop();
cout<<s.top()<<endl; // 7
s.pop();
cout<<s.top()<<endl; // 8
См. пример программы
20
Очередь (queue)
Очередь – это адаптер очереди, который организует ее
работу по правилу "first in, first out" (FIFO)
 не предоставляет функций для получения итераторов и их перебора
 позволяет проверить, какой элемент находится на вершине стека (front)
queue<int> q;
q.push(8); // q = 8
q.push(7); // q = 7 8
q.push(4); // q = 4 7 8
cout<<q.front()<<endl; // 8
q.pop();
cout<<q.front()<<endl; // 7
q.pop();
cout<<q.front()<<endl; // 4
21
Ассоциативный массив
Ассоциативный массив - используется для хранения
связанных пар "ключ-значение" ("key-value")
 массив, в котором индекс может быть не целочисленного типа
 организуются как сбалансированное дерево узлов
pair<const key, mapped_type>
Ассоциативные контейнеры STL
 map – ассоциативный массив, по ключу в контейнере хранится одно
значение
 multimap – ассоциативный массив с повторяющимися ключами
 set – массив уникальных ключей без значений
 multiset – массив с повторяющимися ключами без значений
22
Ассоциативный массив map
Доступ к элементам по ключу
map<string, double> glass;
double n=glass["K8"];
• поиск по ключу
• если ключ не найден, то вставляется элемент со значением по умолчанию (0)
glass["K8"]=1.5;
• поиск по ключу
• если ключ не найден, то вставляется элемент с заданным значением
Доступ к элементам по итератору (объект pair)
• первый элемент (pair::first) – ключ
• второй элемент (pair::second) – значение
• элементы хранятся в отсортированном виде: от меньшего ключа к большему ключу
map<string, double>::iterator it;
for(it=glass.begin(); it!=glass.end(); it++)
{
cout<<it->first<<" "<<it->second<<endl;
}
См. пример программы
23
Ассоциативный массив set
Доступ к элементам по итератору
 все значения уникальны и отсортированы
• от меньшего ключа к большему ключу
set<string> glass;
map<string>::iterator it;
glass.insert("K8");
glass.insert("ТK14");
glass.insert("K8");
for(it=glass.begin(); it!=glass.end(); it++)
{
cout<<*it<<" "<<endl;
}
См. пример программы
24
Алгоритмы
Алгоритмы – обобщенные процедуры для обработки
элементов любых контейнеров
#include <algorithm>
using namespace std;
list<double> x;
// вычисление суммы через итераторы
list<double>::iterator it;
for(it=x.begin(); it!=x.end(); it++)
{
sum+=(*it);
}
// вычисление суммы через алгоритмы
sum=accumulate(x.begin(), x.end(), 0.0);
25
Алгоритмы не модифицирующие
контейнер
Алгоритмы не модифицирующие контейнер – процедуры
поиска и сравнения
list<string> ls;
list<string>::const_iterator it;
// поиск значения "К8" в диапазоне от ls.begin() до ls.end()
it=find(ls.begin(), ls.end(), "К8");
26
Алгоритмы модифицирующие
значение элементов контейнера
Алгоритмы модифицирующие значение элементов
контейнера, но не изменяющие порядок их следования –
выполнение действий над каждым элементом контейнера,
поиск и замена
vector<int> v(100);
// заполнение всех элементов от ls.begin() до ls.end()
// значением 0
fill(v.begin(), v.end(), 0);
// замена всех элементов от ls.begin() до ls.end(),
// равных -1 на 1
replace(v.begin(), v.end(), -1, 1);
27
Алгоритмы модифицирующие
контейнер
Алгоритмы модифицирующие контейнер –
функции копирования, перестановок, удаления, тасования
и сортировки, разбиения и слияния последовательностей
vector<int> v(100);
// сортировка массива
sort(v.begin(), v.end());
// перестановка элементов массива в обратном порядке
reverse(v.begin(), v.end());
28
Функции-помощники
Функции-помощники (перестановки и сравнения)
vector<int> v(100);
vector<int>::iterator it=v.begin();
it++;
swap(*v.begin(), *it);
29
Численные алгоритмы
#include <numeric>
accumulate - накапливает результаты выполнения
операций над последовательностью
• (сложение элементов)
inner_product - накапливает результаты выполнения
операций над двумя последовательностями
• (перемножение элементов)
partial_sum - позволяет получить последовательность
инкрементных изменений
• (a, a+b, a+b+c, a+b+c+d, ...)
adjacent_difference - позволяет получить
последовательность декрементных изменений
• (a, b-a, c-b-a, d-c-b-a, ...)
См. пример программы

Lecture 2

  • 1.
    Прикладное программирование кафедра прикладной икомпьютерной оптики Составные типы данных
  • 2.
    2 Составные типы данных ГомогенныеГетерогенные Назначение для хранения однотипных переменных для хранения неоднородных разнотипных переменных Пример массив, строка, список, стек, очередь, набор, карта, дерево структура, класс
  • 3.
    3 Массивы Массив - этогруппа последовательных ячеек памяти, имеющих один и тот же тип int data[4]; Нумерация элементов – от 0 до <размер-1> data[0]=1; data[1]=2; data[2]=3; data[3]=4; Объявление и инициализация double v[3]={0.3, 2.2, 2.}; char symbols[]={'a', 'b', 'c', 'd', 'e'};
  • 4.
    4 Динамическое размещение массива double *data;// указатель на массив data=new double[1000]; // указатель на 0-й элемент массива // инициализация for(int i=0; i<1000; i++) { data[i]=0.; } delete [] data; // обязательно освободить память data+1; // указатель на 1-й элемент data+100; // указатель на 100-й элемент, *(data+4); // эквивалентно data[4] См. пример программы
  • 5.
    5 Передача массива вфункцию Передача массива в функцию может осуществляться только по указателю на нулевой элемент, с дополнительной информацией о количестве элементов в массиве // указатель на массив + количество элементов в массиве double sum(double* m, int n) // или double m[] { double s=0.; for(int i=0; i<n; ++i) { s+=m[i]; } return s; } См. пример программы
  • 6.
    6 Двумерный массив Для созданиядвумерного массива необходимо указать в квадратных скобках два значения – количество строк и столбцов в массиве double matrix[3][2]; // двумерный массив 2х3 double sum=0.; for(int i=0; i<3; i++) // номер строки { for(int j=0; j<2; j++) // номер столбца { sum+=matrix[i][j]; } } matrix[0][0]; matrix[2][1]; [0][0] [0][1] [1][0] [1][1] [2][0] [2][1] [0][0] [0][1] [1][0] [1][1] [2][0] [2][1]
  • 7.
    7 Динамическое размещение двумерного массива Двумерныймассив можно разместить динамически, только если представить его как одномерный  вместо доступа по индексам [i][j], придется вычислять индекс одномерного массива, которому будет соответствовать необходимый элемент двумерного массива • Например, элементу [1][0] двумерного массива будет соответствовать индекс [2] одномерного массива // указатель на двумерный массив matrix[3][2] double *matrix=new double[3*2]; // matrix[i][j] matrix[i*2+j]=0.; // например matrix[1][0] matrix[1*2+0]=0.; delete [] matrix; //освободить память 0 1 2 3 4 5 [0][0] [0][1] [1][0] [1][1] [2][0] [2][1] См. пример программы
  • 8.
    8 Контейнеры Контейнер – типданных, предназначенный для хранения однотипных данных  вектор, стек, очередь, список, ассоциативный массив, дерево Хранение элементов контейнера  последовательно (непрерывным блоком)  разбросаны по всей памяти Доступ к элементам контейнера  по индексу  только последовательным перебором
  • 9.
    9 STL (Standard TemplateLibrary) – стандартная библиотека шаблонов Контейнеры  объекты для хранения однотипных данных: • последовательные (vector, deque, list); • ассоциативные (set, multiset, map, multimap); Адапторы  объекты, созданные на основе базовых контейнеров, с измененным интерфейсом (например, queue, stack) Итераторы  объекты, которые используются для универсального доступа к элементам хранящимся в контейнере любого типа Алгоритмы  обобщенные процедуры для обработки элементов любых контейнеров Функции-объекты  объекты, у которых перегружен оператор вызова функций
  • 10.
    10 Контейнеры: вектор, стек, очередь Вектор хранение элементов единым блоком  доступ к любому элементу по индексу Стек  хранение элементов единым блоком  доступ только к последнему элементу, внесенному в стек Очередь  хранение элементов единым блоком  доступ только к первому элементу, внесенному в очередь
  • 11.
    11 Контейнеры: список, дерево, ассоциативныймассив Список  элементы разбросаны по памяти • каждый элемент содержит указатель на последующий и предыдущий  только перебор Дерево  элементы разбросаны по памяти  обхода дерева от корня • родитель содержит ссылки на дочерние элементы Ассоциативный массив  элементы разбросаны по памяти  обход дерева по ключу
  • 12.
    12 Вектор Вектор - одномерныймассив проиндексированных элементов • Доступ к функциям вектора производится через оператор "." • Подробнее о классах и шаблонах см. главу 4 и раздел 5.4. #include <vector> using namespace std; vector<double> x; // создание вектора x.resize(10); // изменение размера вектора x.resize(x.size()+100); // изменение размера вектора double sum=0.0; for(int i=0; i<x.size(); i++) { sum+=x[i]; //доступ по индексу }
  • 13.
    13 Функции работы свектором Размер (количество элементов) контейнера int n=x.size(); Изменение размера контейнера x.resize(100); Доступ к элементам контейнера x[i]=5; Добавить элемент в конец контейнера • Добавляет копию элемента x.push_back(7); Определяет пустой ли контейнер bool res=x.empty(); // эквивалентно x.size() == 0 Очистить контейнер • разрушает все элементы и освобождает контейнер x.clear(); Выделение дополнительной памяти для размещения новых эл-в x.reserve(200); Определяет кол-во элементов, для которых зарезервирована.память int n=x.capacity(); Остальные функции – см.Приложение 5 См. пример программы
  • 14.
    14 Список Список – структураданных для организации хранения элементов с эффективной вставкой и удаления в любом месте этой структуры, не требует доступа по индексу  УЗЕЛ (Node) – объект, который содержит ссылки на последующий и предыдущий элементы, а также значение данного элемента списка Простой односвязный список Простой двухсвязный список Кольцевой двухсвязный список
  • 15.
    15 Функции списка STL –простой двухсвязный список list<int> example; example.push_back(0); // вставка в конец example.push_front(1); // вставка в начало x.insert(x.begin(), 3); // вставка в любое место списка  (переразмещения данных в памяти не происходит)
  • 16.
    16 Итераторы Итератор – этообобщённый "указатель" на элемент, хранящийся в контейнере list<double> ls; list<double>::iterator it;  оператор * – разыменование и получение доступа к значению элемента (*it)=5;  операторы «++» и «– –» получение указателя на следующий и предыдущий элемент it++, it--  итератор на первый элемент контейнера it=ls.begin()  итератор на следующий после последнего элемент контейнера it=ls.end()
  • 17.
    17 Использование итераторов list<double> x; list<double>::iteratorit; for(it=x.begin(); it!=x.end(); it++) { sum+=(*it); //доступ к элементам по итератору } it=x.begin(); while(it!=x.end()) { sum+=*it; it++; } См. пример программы
  • 18.
    18 Двусторонняя очередь (deque) Двусторонняяочередь – последовательность, которая:  поддерживает произвольный доступ к элементам (аналогично vector)  поддерживает вставку и удаление в начало последовательности  Кроме того: • не имеет функций-членов capacity() и reserve() • не предоставляет никаких гарантий на допустимость итератора См. пример программы
  • 19.
    19 Стек (stack) Стек –адаптер очереди, который организует ее работу по правилу "last in, first out" (LIFO)  не предоставляет функций для получения итераторов и их перебора  позволяет проверить, какой элемент находится на вершине стека (top) stack<int> s; s.push(8); // s = 8 s.push(7); // s = 7 8 s.push(4); // s = 4 7 8 cout<<s.top()<<endl; // 4 s.pop(); cout<<s.top()<<endl; // 7 s.pop(); cout<<s.top()<<endl; // 8 См. пример программы
  • 20.
    20 Очередь (queue) Очередь –это адаптер очереди, который организует ее работу по правилу "first in, first out" (FIFO)  не предоставляет функций для получения итераторов и их перебора  позволяет проверить, какой элемент находится на вершине стека (front) queue<int> q; q.push(8); // q = 8 q.push(7); // q = 7 8 q.push(4); // q = 4 7 8 cout<<q.front()<<endl; // 8 q.pop(); cout<<q.front()<<endl; // 7 q.pop(); cout<<q.front()<<endl; // 4
  • 21.
    21 Ассоциативный массив Ассоциативный массив- используется для хранения связанных пар "ключ-значение" ("key-value")  массив, в котором индекс может быть не целочисленного типа  организуются как сбалансированное дерево узлов pair<const key, mapped_type> Ассоциативные контейнеры STL  map – ассоциативный массив, по ключу в контейнере хранится одно значение  multimap – ассоциативный массив с повторяющимися ключами  set – массив уникальных ключей без значений  multiset – массив с повторяющимися ключами без значений
  • 22.
    22 Ассоциативный массив map Доступк элементам по ключу map<string, double> glass; double n=glass["K8"]; • поиск по ключу • если ключ не найден, то вставляется элемент со значением по умолчанию (0) glass["K8"]=1.5; • поиск по ключу • если ключ не найден, то вставляется элемент с заданным значением Доступ к элементам по итератору (объект pair) • первый элемент (pair::first) – ключ • второй элемент (pair::second) – значение • элементы хранятся в отсортированном виде: от меньшего ключа к большему ключу map<string, double>::iterator it; for(it=glass.begin(); it!=glass.end(); it++) { cout<<it->first<<" "<<it->second<<endl; } См. пример программы
  • 23.
    23 Ассоциативный массив set Доступк элементам по итератору  все значения уникальны и отсортированы • от меньшего ключа к большему ключу set<string> glass; map<string>::iterator it; glass.insert("K8"); glass.insert("ТK14"); glass.insert("K8"); for(it=glass.begin(); it!=glass.end(); it++) { cout<<*it<<" "<<endl; } См. пример программы
  • 24.
    24 Алгоритмы Алгоритмы – обобщенныепроцедуры для обработки элементов любых контейнеров #include <algorithm> using namespace std; list<double> x; // вычисление суммы через итераторы list<double>::iterator it; for(it=x.begin(); it!=x.end(); it++) { sum+=(*it); } // вычисление суммы через алгоритмы sum=accumulate(x.begin(), x.end(), 0.0);
  • 25.
    25 Алгоритмы не модифицирующие контейнер Алгоритмыне модифицирующие контейнер – процедуры поиска и сравнения list<string> ls; list<string>::const_iterator it; // поиск значения "К8" в диапазоне от ls.begin() до ls.end() it=find(ls.begin(), ls.end(), "К8");
  • 26.
    26 Алгоритмы модифицирующие значение элементовконтейнера Алгоритмы модифицирующие значение элементов контейнера, но не изменяющие порядок их следования – выполнение действий над каждым элементом контейнера, поиск и замена vector<int> v(100); // заполнение всех элементов от ls.begin() до ls.end() // значением 0 fill(v.begin(), v.end(), 0); // замена всех элементов от ls.begin() до ls.end(), // равных -1 на 1 replace(v.begin(), v.end(), -1, 1);
  • 27.
    27 Алгоритмы модифицирующие контейнер Алгоритмы модифицирующиеконтейнер – функции копирования, перестановок, удаления, тасования и сортировки, разбиения и слияния последовательностей vector<int> v(100); // сортировка массива sort(v.begin(), v.end()); // перестановка элементов массива в обратном порядке reverse(v.begin(), v.end());
  • 28.
    28 Функции-помощники Функции-помощники (перестановки исравнения) vector<int> v(100); vector<int>::iterator it=v.begin(); it++; swap(*v.begin(), *it);
  • 29.
    29 Численные алгоритмы #include <numeric> accumulate- накапливает результаты выполнения операций над последовательностью • (сложение элементов) inner_product - накапливает результаты выполнения операций над двумя последовательностями • (перемножение элементов) partial_sum - позволяет получить последовательность инкрементных изменений • (a, a+b, a+b+c, a+b+c+d, ...) adjacent_difference - позволяет получить последовательность декрементных изменений • (a, b-a, c-b-a, d-c-b-a, ...) См. пример программы