Программирование

175
Программирование Часть 4 Структуры данных

Upload: sinjin

Post on 07-Jan-2016

37 views

Category:

Documents


2 download

DESCRIPTION

Программирование. Часть 4 Структуры данных. 4. Структурное программирование 4. 5 . Базовые структуры данных: структуры. Программа = Структуры данных + Алгоритмы. СТРУКТУРА ДАННЫХ – способ представления данных в программе для компьютера - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Программирование

Программирование

Часть 4Структуры данных

Page 2: Программирование

4. Структурное программирование 4.5. Базовые структуры данных: структуры

Программа = Структуры данных + Алгоритмы

СТРУКТУРА ДАННЫХ – способ представления данных в программе для компьютера

ПРОГРАММА - описание структур данных и алгоритма решения задачи на языке программирования, автоматически переводимое на язык машинных команд конкретной ЭВМ помощи транслятора (интерпретатора).

Задача:Спроектировать структуру данных для представления в памяти компьютера информации о членах университетского коллектива.

Page 3: Программирование

4. Структурное программирование 4.5. Базовые структуры данных: структуры

НАЧНЕМ С ДАННЫХ О ЧЛЕНЕ УНИВЕРСИТЕТСКОГО КОЛЛЕКТИВА. ПОСТАВЛЕНА ЗАДАЧА ХРАНИТЬ И ОБРАБАТЫВАТЬ СЛЕДУЮЩУЮ ИНФОРМАЦИЮ О НЕМ:

Идентификационный номер (студенческого билета или удостоверения) Фамилия Имя Отчество Дата рождения Домашний адрес Дата зачисления (на работу или учебу) Должность Является ли членом профсоюза

Page 4: Программирование

4. Структурное программирование 4.5. Базовые структуры данных: структуры

ВЫБЕРЕМ ТИПЫ ДАННЫХ И ИМЕНА ПЕРЕМЕННЫХ ДЛЯ ХРАНЕНИЯ ИНФОРМАЦИИ О КАЖДОМ ЧЕЛОВЕКЕ:

Идентификационный номер – int id Фамилия – char surname [80] Имя – char firstname [40] Отчество – char patronymic [60] Дата рождения – unsigned short birthyear, birthmonth, birthday Адрес – char address [80] Дата зачисления – unsigned short enteryear, entermonth, enterday Должность – char position [30] Является ли членом профсоюза – bool tradeunion

Page 5: Программирование

Структура – упорядоченное множество данных различного типа, которые называются полями или членами структуры.

Доступ к полю структуры осуществляется по имени структуры и имени поля.

Поля структуры могут иметь любой тип (кроме void). Структура может содержать только такие поля, длина которых

известна компилятору в момент определения структуры. Структурным типом данных или просто структурой называется тип,

описывающий структуру.Синтаксис объявления структурного типа:

struct Имя_структуры{

Тип_ поля_1 Имя_поля1;Тип_ поля_2 Имя_поля2;

… };

4. Структурное программирование 4.5. Базовые структуры данных: структуры

Page 6: Программирование

Примеры объявления структурных типов :

struct Date struct Name{ { unsigned short year; char surname [80]; unsigned short month; char firstname [40]; unsigned short day; char patronymic [60]; }; };

struct Cmplx{ double re; double im;};

4. Структурное программирование 4.5. Базовые структуры данных: структуры

Обратите внимание: описание структуры заканчивается точкой с

запятой

Page 7: Программирование

Размещение в памяти структурных типов :

struct Date{ unsigned short year; unsigned short month; unsigned short day;};

struct Cmplx{ double re; double im;};

4. Структурное программирование 4.5. Базовые структуры данных: структуры

Внимание!Компилятор не гарантирует размещение элементов структуры в смежных ячейках памяти!

Page 8: Программирование

Объявление переменных структурного типа

Имя_типа Имя_переменной;Имя_типа Имя_переменной = {список значений};

Примеры объявления переменных структурных типов,

Cmplx c1, c2, c3;Date birth, enter, expel, graduate, death ;

struct // Совмещение объявлений типа и переменных { // в анонимной структуре double re; double im;} c1, c2, c3;

4. Структурное программирование 4.5. Базовые структуры данных: структуры

Page 9: Программирование

Примеры объявления переменных структурных типов с инициализацией

Cmplx c1 = {0, 0};Date birth = {1991, 10, 7}, enter = {2009, 9 , 1}, graduate = {2014, 6, 30};

struct // Совмещение объявлений типа и переменных { double re; double im;} c1={0, 0}, c2={1, 0}, c3={1, 0};

4. Структурное программирование 4.5. Базовые структуры данных: структуры

Page 10: Программирование

Доступ к элементам структуры: оператор . (точка)

Имя_переменной.Имя_поля

birth.year = 2002; birth.month=12;

c1.re = 12.5; c1.im = -24;c2.re = c1.re*c1.re + c1.im*c1.im;

Присваивание переменных – структур одного типа :

c1=c2; expel.year=enter.year;

4. Структурное программирование 4.5. Базовые структуры данных: структуры

Page 11: Программирование

Структуры могут:объединять данные (поля) различных типов;быть вложенными друг в друга

4. Структурное программирование 4.5. Базовые структуры данных: структуры

struct Date{ unsigned short year; unsigned short month; unsigned short day;};

struct Member{ int id; Name ownname; Date birth; char address [80]; Date enter; char position [30]; //"student", "teacher", "scientist" …

bool tradeunion;};

struct Name{ char surname [80]; char firstname [40]; char patronymic [60]; };

Page 12: Программирование

Рассмотрим работу с вложенными структурами

4. Структурное программирование 4.5. Базовые структуры данных: структуры

struct Member{ int id; Name ownname; Date birth; char address [80]; Date enter; char position [30]; bool tradeunion;};

Member stud1 = {298678, “Сидорова”, “Анна”, “Ивановна”, 1991, 10, 7, “Минск, ул. Серова 23, кв. 1”, 2009, 9, 1, “student”, false};

Member prep4 = {129639, {“Попкец”, “Павел”, “Петрович”}, {1980, 6, 1}, “Минск, ул. Казинца 75, кв. 12”, {2003, 3, 18}, “teacher”, true}; Member temp = stud1;

stud1.cardno = 123456789; stud1.ownname.surname = “Попкец”;stud1.ownname.surname = prep4.ownname.surname;prep4=temp;

Page 13: Программирование

А как представить в памяти информацию обо всех членах коллектива, например, факультета?

4. Структурное программирование 4.5. Базовые структуры данных: структуры

Student stud1, stud2, stud3, stud4, stud5, … stud788, stud789, stud790;

Page 14: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Массив – нумерованная последовательность данных одного типа, которые хранятся в непрерывной области памяти друг за другом. Члены последовательности данных называются элементами массива.

Доступ к элементу массива производится путем указания имени массива и номера элемента.

Нумерация элементов может выполняться одной или несколькими последовательностями целых чисел – индексными последовательностями.

Если нумерация выполняется одной последовательностью говорят, что массив является одномерным, в противном случае – многомерным.

Нумерация элементов массива всегда начинается с 0, а номер каждого следующего члена больше номера предыдущего на 1.

Page 15: Программирование

Размещение в памяти массивов:

int b [10]

short x [2][4]

4. Структурное программирование 4.5. Базовые структуры данных: структуры

0b

1 2 3 4 5 6 7 8 9

0,0x

0,1 0,2 0,3 1,0 1,1 1,2 1,3

Внимание!Компилятор гарантирует размещение элементов массива в смежных ячейках памяти!

Page 16: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Массив определяется: именем (идентификатором); количеством размерностей - числом номеров, необходимых

для указания местонахождения элемента массива; размером (диапазоном изменения индексов) по каждой

размерности.

Конфигурация массива фиксирована. Все элементы массива принадлежат к одному и тому же

типу данных. Элементами массива могут быть как простые переменные

любых типов, так и переменные составных типов (массивов, структур, строк и т.д.).

В качестве индексов в С++ могут использоваться константы и переменные любых целых типов.

Page 17: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Синтаксис описания одномерного массива

Имя_типа_элемента Имя_массива [Размер]; Имя_типа_элемента Имя_массива [Размер] = {список значений};

Примеры описаний массивов

float b[20] ;

const int n=4;int a[n] = {5, 6,7,8};

5 6 7 8

a

… a[0] a[1] a[2] a[3] …

4 байта

Page 18: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Примеры описаний массивов

float x[20] = {0} ; Если список инициализации содержит меньше элементов, чем массив, оставшиеся

элементы инициализируются значением 0. Если список содержит больше элементов, чем массив, компилятор генерирует сообщение об ошибке.

double y [ ] = {5.5, 6.8, 8.8, 9.5, 10.3}Если значения элементов перечисляются явно, размер массива можно не

указывать (компилятор определит его по количеству элементов)

5.5 6.8 8.8 9.5 10.3

y

… y[0] y[1] y[2] y[3] y[4] …

8 байтов

Page 19: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Операция индексирования

Имя_массива [Индекс];

Индекс – целочисленное выражение, значение которого изменяется между 0 и (Размер-1). Для переменной – индекса лучше выбирать тип целый со знаком, так как контроль выхода значений индекса за допустимый диапазон не ведется.

const int n=4;int a[n] = {5, 6,7,8};

int i = 3;a[1] = a[2]+a[i]-6;

5 9 7 8

a

… a[0] a[1] a[2] a[3] …

Page 20: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Задача.Написать программу, осуществляющую ввод, сложение, вычитание, скалярное умножение двух n-мерных векторов и вывод результатов.

Структура данных для представления n-мерного вектора: одномерный массив размера n типа double.

Расчетные формулы:

....

);,...,,(

);,...,,(

).,...,,( );,...,,(

2211

2211

2211

2121

nn

nn

nn

nn

babababa

babababa

babababa

bbbbaaaa

Page 21: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Решение задачи:

int main() { const int n=4; double a[n]={0}, b[n]={0}, res[n]={0};

cout << "Enter..." << endl; for (int i=1; i<=n; i++)

{ cout << endl << "a" << i << ": ";

cin >> a[i-1]; cout << "b" << i << ": "; cin >> b[i-1];}

Если список инициализации содержит меньше значений, чем число элементов массива, оставшиеся элементы будут инициализированы 0

Page 22: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Решение задачи: for (int i=1; i<=n; i++) res[i-1]=a[i-1]+b[i-1]; //Sum cout << endl << "a + b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")";

for (int i=1; i<=n; i++) res[i-1]=a[i-1]-b[i-1]; //Difference cout << endl << "a - b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")"; double r=0; for (int i=1; i<=n; i++) r+=a[i-1]*b[i-1]; //Product cout << endl << "a * b = " << r;

_getch(); return 0;};

Page 23: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Задача (Решето Эратосфена).Найти простые числа, меньшие наперед заданного n.

Идея алгоритма Эратосфена: из списка всех чисел от 2 до n последовательно вычеркивать числа, кратные уже известным простым числам.

Основная структура данных программы: одномерный массив размера 2..n типа boolean. Индексы массива соответствуют анализируемым числам. Элемент массива имеет значение true, если индекс этого элемента - простое число.

Page 24: Программирование

Алгоритм на псевдокоде Данные.Максимальное анализируемое число n Массив, хранящий информацию, простым ли является значение индекса каждого элемента: bool erato [n]Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до n

3.1. Если erato [ i ] == true , 3.1.1. Заменить на false значения элементов массива erato с индексами от i до n, кратными i 4. Вывести значения индексов элементов массива erato , принимающих значение true

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 25: Программирование

Оптимизируем и уточняем алгоритм на псевдокоде Данные.Максимальное анализируемое число n Массив, хранящий информацию, простым ли является значение индекса каждого элемента: bool erato [n]Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true , 3.1.1. Заменить на false значения элементов массива erato с индексами от i до n, равными i * j, где j изменяется от i до n 4. Вывести значения индексов элементов массива erato , принимающих значение true

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 26: Программирование

Уточняем алгоритм на псевдокоде Данные.Максимальное анализируемое число n Массив, хранящий информацию, простым ли является значение индекса каждого элемента: bool erato [n+1]Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 27: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

i = 2j =

erato[i] = true

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 28: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

1 1 1 0 1 1 1 1 1 1 1 1 1 1

1 2 3 4 5 6 7 8 9 10 11 12 13 14

i = 2j = 2

erato[i] = trueerato[4] = false

1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 29: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 2j = 3

erato[i] = trueerato[6] = false

1 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 30: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 2j = 4

erato[i] = trueerato[8] = false

1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 31: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 2j = 5

erato[i] == trueerato[10] = false

1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 32: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 2j = 6

erato[i] == trueerato[12] = false

1 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 33: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 2j = 7

erato[i] == trueerato[14] = false

1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 34: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 2j = 8

erato[i] == trueerato[16] = false

1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 35: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 2j = 9

erato[i] == truei * j > n

1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 36: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 3j = 3

erato[i] == trueerato[9] = false

1 1 0 1 0 1 0 0 0 1 0 1 0 1 0 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 37: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 3j = 4

erato[i] == trueerato[12] = false Повторное присваивание выгоднее проверки!

1 1 0 1 0 1 0 0 0 1 0 1 0 1 0 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 38: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 3j = 5

erato[i] == trueerato[15] = false

1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 39: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 3j = 6

erato[i] == truei * j > n

1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 40: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = 4j =

erato[i] == false

1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 41: Программирование

Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)

3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true

i = j =

1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 42: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Программа на С++ int main() // sieve of Eratosthenes{ const unsigned int n = 1000; const unsigned int size = n+1; bool erato [size]={0};

for (int i = 2; i <= n; i++) erato [i] = 1; for (int i = 2; i <= static_cast <int> (sqrt(static_cast <float> (n))); i++) { if (erato[i]) for (int j = i; j <= n; j++) {

if (i*j > n)break;erato [i*j]=false;

} } for(int i=2; i <= n; i++) if (erato[i]) cout << i << endl; _getch(); return 0;}

Page 43: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Строки символов в С++ В С++ есть несколько способов представления строк

символов: в виде одномерного массива символов (строки,

завершающиеся нулевым байтом); в виде объекта класса string; другие способы в зависимости от реализации.

Строки, завершающиеся нулевым байтом Описываются как одномерный массив, каждый элемент

которого имеет тип char. Символы строки последовательно располагаются в

элементах массива, начиная с нулевого. В элемент массива, следующий за последним символом

автоматически записывается элемент с ASCII кодом 0: ‘\0’

Page 44: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Описание строк, завершающихся нулевым байтом Строка описывается как обычный массив символов char Размер массива должен быть на 1 больше длины самой

длинной строки, которую предполагается в этом массиве хранить

char s[10] = “Hello”;

Основные отличия строк от массивов: В процессе выполнения программы отслеживается текущая длина строки Строка в целом может быть проинициализирована значением строкового

литерала (а не только поэлементно символьными значениями) При помещении идентификатора символьного массива в поток cout

выводится не адрес массива, а его содержимое от 0-го элемента до последнего перед завершающим символом \0

H e l l 0 \0

0s

1 2 3 4 5 6 7 8 9

Page 45: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Самые распространенные функции из <string.h>

Имя Предназначение

strcpy (s1,s2) Копирует строку s2 в строку s1

strcat (s1,s2) Приписывает строку s2 в конец строки s1

strlen (s1) Вычисляет текущую длину строки s1

strcmp (s1,s2) Возвращает 0, если строки совпадают, отрицательное значение, если s1 < s2 и положительное, если s1 > s2

strchr (s1, ch) Возвращает указатель на позицию первого вхождения символа ch в строку s1

strstr (s1, s2) Возвращает указатель на позицию первого вхождения строки s2 в строку s1

Page 46: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Примерыchar st [20] = “ Good Morning”;

cout << st; // Good Morningstrcpy(st, “Hello”);

cout << st; // Hellostrcpy(st,“”);

G o o d M o r n i n g \0

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Мусор

H e l l o \0 o r n i n g \0

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

\0 e l l o \0 o r n i n g \0

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Page 47: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Основные ограничения на действия со строками, завершающимися нулевым байтомСтроки, как и обычные массивы, нельзя присваивать друг другу, используя оператор присваивания (включая присвоение строке строкового литерала где-либо, кроме начальной инициализации).К строкам, как к обычным массивам, нельзя применять операции сравненияДля строк нет перегруженных операций (например, + для операции конкатенации)Для выполнения операций копирования, конкатенации, сравнения строк и ряда других операций приходится использовать встроенные функции, описанные в заголовке <string.h>

Page 48: Программирование

int main() // Basic operations with strings{ char st [20] = "*******************"; // 19 '*‘ char st1 [20];

for (int i=0; i <=19; i++) cout << st[i]; // ******************* cout << endl<< st << " " << strlen (st) << endl; // ******************** 19 strcpy(st,"Good Morning"); for (int i=0; i <=19; i++) cout << st[i]; // Good Morning ****** cout << endl<< st << " " << strlen (st) << endl; // Good Morning 12 strcpy(st,"Hello"); for (int i=0; i <=19; i++) cout << st[i]; // Hello orning ****** cout << endl<< st << " " << strlen (st) << endl; // Hello 5 cout << endl; strcpy(st1, strchr(st, 'e')); cout << st1 << endl; // ello bool i = strchr(st, 'e'); cout << i << endl; // 1 if (strchr(st, 'e')) cout << "char e found"; // char e found _getch(); return 0;}

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 49: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Ввод строк При вводе строки с клавиатуры (помещение в поток cin) следует контролировать длину вводимой строки (чтобы она не превышала длину массива, где будет храниться строка

char str [MAX];cin >> setw (MAX) >> str; // Ввод до MAX-1 символов При помещении строки в поток cin пробелы и символы новой строки конвертируются в завершающий нулевой байт

cin >> setw (MAX) >> str; // Введем строку “Good Morning”cout << str; // Получим GoodЧтобы ввести строку, содержащую пробелы, необходимо вызвать встроенную функцию getline для потока cin:

cin.getline(st, MAX); или char SEP=‘$’; cin.getline (st, MAX, SEP); // Задаем свой разделитель строк

Page 50: Программирование

int main() // Counting number of characters into string{ const int MAX = 80; // Maximum array dimension char buffer[MAX]=""; // Input buffer int count = 0; // Character counter

while (true) { cout << "Enter a string of less than 80 characters:\n"; cin.getline(buffer, MAX); if (! strcmp(buffer,"")) break; for(count=0; buffer[count] != '\0'; count++); // The same: count=strlen(buffer) cout << endl << "The string \"" << buffer

<< "\" has " << count << " characters." << endl; } return 0;}

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 51: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Двумерные массивы

Одномерный массивint a[6];

a[0] a[1] a[2] a[3] a[4] a[5]

Page 52: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Двумерные массивы

Построим массив, состоящий из четырех таких массивовint a[6];

a[0] a[1] a[2] a[3] a[4] a[5]

a[0] a[1] a[2] a[3] a[4] a[5]

a[0] a[1] a[2] a[3] a[4] a[5]

a[0] a[1] a[2] a[3] a[4] a[5]

0

1

2

3

Page 53: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Двумерные массивы

Построим массив, состоящий из четырех таких массивовint a[6];Перенумеруем элементы, используя два индекса и соответственно опишем этот массив:int a[4][6]

a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] a[0][5]

a[1][0] a[1][1] a[1][2] a[1][3] a[1][4] a[1][5]

a[2][0] a[2][1] a[2][2] a[2][3] a[2][4] a[2][5]

a[3][0] a[3][1] a[3][2] a[3][3] a[3][4] a[3][5]

0

1

2

3

Page 54: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Двумерные массивы

Построим массив, состоящий из четырех таких массивовint a[6];Перенумеруем элементы, используя два индекса и соответственно опишем этот массив:int a[4][6]

В памяти двумерный массив вытянут по строкам

a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] a[0][5]

a[1][0] a[1][1] a[1][2] a[1][3] a[1][4] a[1][5]

a[2][0] a[2][1] a[2][2] a[2][3] a[2][4] a[2][5]

a[3][0] a[3][1] a[3][2] a[3][3] a[3][4] a[3][5]

0

1

2

3

Page 55: Программирование

int main() // How to initialize two-dimensional arrays{ const int m=4, n =6; // maximum array dimensions int a[m][n] = {{0,1,2,3,4,5}, {10,11,12,13,14,15}, {20,21,22,23,24,25}, {30,31,32,33,34,35}};

int b[m][n] = {0,1,2,3,4,5,10,11,12,13,14,15}; // third & fourth rows are set to zero

int d[m][n] = {0}; // the whole array is set to zero

int c[][n]={{0,1,2,3,4,5}, // first dimension’s size will be calculated by compiler {10,11,12,13,14,15}, {20,21,22,23,24,25}, {30,31,32,33,34,35}};}

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 56: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

ЗадачаПредставить целочисленную квадратную матрицу 4х4 в виде массива. Присвоить элементам на главной диагонали значение 1, выше главной диагонали - 2, ниже – 0.

44434241

34333231

24232221

14131211

a[0][0] a[0][1] a[0][2] a[0][3]

a[1][0] a[1][1] a[1][2] a[1][3]

a[2][0] a[2][1] a[2][2] a[2][3]

a[3][0] a[3][1] a[3][2] a[3][3]

a[0][0] a[0][1] a[0][2] a[0][3] a[0][4]

a[1][0] a[1][1] a[1][2] a[1][3] a[1][4]

a[2][0] a[2][1] a[2][2] a[2][3] a[2][4]

a[3][0] a[3][1] a[3][2] a[3][3] a[3][4]

a[4][0] a[4][1] a[4][2] a[4][3] a[4][4]

]1][1[ jiaij

]][[ jiaij

Page 57: Программирование

int main() // working with two-dimensional arrays{ const int n=4; int a[n][n] = {0};

for (int i=0; i<=n-1; i++) for (int j=0; j<=n-1; j++) { if (i == j) a[i][j]=1; else if (i < j) a[i][j]=2; }

for (int i=0; i<=n-1; i++) { cout << endl; for (int j=0; j<=n-1; j++) cout << a[i][j]; } _getch(); return 0;}

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

1a[0][0]

2a[0][1]

2a[0][2]

2a[0][3]

0a[1][0]

1a[1][1]

2a[1][2]

2a[1][3]

0a[2][0]

0a[2][1]

1a[2][2]

1a[2][3]

0a[3][0]

0a[3][1]

0a[3][2]

1a[3][3]

1 2 2 2

0 1 2 2

0 0 1 2

0 0 0 1

Page 58: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Многомерные массивыТрехмерный массивfloat x[2][3][4];

x[0][0][0] x[0][0][1] x[0][0][[2] x[0][0][3] x[0][1][0] x[0][1][1]

x[0][1][2] x[0][1][3] x[0][2][[0] x[0][2][1] x[0][2][2] x[0][2][3]

x[1][0][0] x[1][0][1] x[1][0][[2] x[1][0][3] x[1][1][0] x[1][1][1]

x[1][1][2] x[1][1][3] x[1][2][[0] x[1][2][1] x[1][2][2] x[1][2][3]

Page 59: Программирование

int main() // sets elements of 3-D array to sin (i+j*k){ const int l=1, m=2, n=3; float x[l+1][m+1][n+1] = {0};

for (int i=0; i<=l; i++) for (int j=0; j<=m; j++) for (int k=0; k<=n; k++) { x[i][j][k] = sin(static_cast <double> (i+j*k)); cout << setw (10) << x [i][j][k]; if (k==n) cout << endl; if (k==n & j==m) cout << endl; }_getch(); return 0;}

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Page 60: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Массив структур

rfe[0] rfe[1] rfe[2] rfe[3] … rfe[799]

struct Member{ int id; Name ownname; Date birth; char address [80]; Date enter; char position [30]; bool tradeunion;};

const int nmembers = 800Member rfe [nmembers];

Page 61: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

int main() //working with the array of members { struct Date {unsigned short year, month, day;}; struct Name { char surname [80]; char firstname [40]; char patronymic [60]; }; struct Member { int id; Name ownname; Date birth; char address [80]; Date enter; char position [30]; //"student", "teacher", "scientist" or smth.else bool tradeunion; };

Page 62: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

const int nmembers = 800; Member rfe [nmembers];

//init array rfe Date initdate = {1900,1,1};

for (int i = 0; i < nmembers; i++) { rfe[i].id=0; strcpy(rfe[i].ownname.surname,""); strcpy(rfe[i].ownname.firstname,""); strcpy(rfe[i].ownname.patronymic,""); rfe[i].birth=initdate; rfe[i].enter=initdate; strcpy (rfe[i].position,"student"); rfe[i].tradeunion=false; }

Page 63: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

// ...

rfe[120].id = 123456; strcpy(rfe[120].ownname.surname,"Poupkin");

// let's admit all students to the trade union for (int i = 0; i < nmembers; i++) if (rfe[i].position == "student") rfe[i].tradeunion = true; //let's print surname for the student with card no 123456 for (int i = 0; i < nmembers; i++) if (rfe[i].id == 123456) cout << i << " " << rfe[i].id << " " << rfe[i].ownname.surname; _getch(); return 0;}

Page 64: Программирование

4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки

Инструкция typedef

Позволяет назначить синоним некоторому типу данных.

Синтаксис инструкции

typedef Декларация_Типа Синоним;

Например ,

typedef double MyFloat;

const int nmembers = 800;typedef Member Array_members [nstudents];

Array_members rfe;… Array_memebers humanoids;

Page 65: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Сортировка - процесс перестановки заданного множества нумерованных объектов в определенном порядке. Цель сортировки - облегчить последующий поиск элементов в отсортированном множестве.Две категории методов сортировки:

- сортировка массивов- сортировка файлов

a1, a2, … an ak1, ak2, … akn f(ak1) f(ak2) f(ak3) … f(akn)

struct item // typical element of array to be sorted { int key; … // specification of other members of the structure }const n=10;typedef item t_array [n];

Page 66: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Принципы построения алгоритмов сортировки массивов:• сортировка на месте• произвольный доступ к элементам

Базовые алгоритмы сортировки массивов: сортировка вставкой (включениями) сортировка выбором (выделением) сортировка обменом (метод «пузырька»)

Базовые операции:- пересылки (присваивания)- сравнения

Page 67: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Пусть все рассматриваемые программы начинаются так: int main() // The beginning of all arrays’ sorting programs {

struct item { unsigned int key; // add members you want}; const int n=9; // right boundary of the array to be sortedtypedef item t_array [n+1];t_array s;

srand( static_cast <unsigned int> (time(NULL)));for (int i=0; i<=n; i++) s[i].key = rand()%33;

for (int i=0; i<=n; i++) cout << setw (4) << s[i].key; … }

Page 68: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Алгоритм сортировки вставкой массива [0…n]:

1. Для всех i от 1 до n выполнить:

1. 1. Взять очередной i-й неотсортированный элемент и сохранить его в рабочей переменной 1. 2. Найти позицию j в отсортированной (0…i-1) части массива, в которой присутствие взятого элемента не нарушит упорядоченности элементов 1.3. Сдвиг элементов массива от i-1 до j-1 вправо, чтобы освободить найденную позицию вставки 1.4. Вставка взятого элемента в найденную j-ю позицию.

Page 69: Программирование

4. Структурное программирование 4.7. Сортировка массивов

12 3 7 1 8 0

0 1 2 3 4 5

i = 1

3 work

j = 0

Сортировка вставкой : 1-й проход

Page 70: Программирование

4. Структурное программирование 4.7. Сортировка массивов

12 12 7 1 8 0

0 1 2 3 4 5

i = 1

3 work

j = 0

Сортировка вставкой : 1-й проход

Page 71: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 12 7 1 8 0

0 1 2 3 4 5

i = 1

3 work

j = 0

Сортировка вставкой : 1-й проход

Page 72: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 12 7 1 8 0

0 1 2 3 4 5

i = 2

7 work

j = 1

Сортировка вставкой : 2-й проход

Page 73: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 12 12 1 8 0

0 1 2 3 4 5

i = 2

7 work

j = 1

Сортировка вставкой : 2-й проход

Page 74: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 7 12 1 8 0

0 1 2 3 4 5

i = 2

7 work

j = 1

Сортировка вставкой : 2-й проход

Page 75: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 7 12 1 8 0

0 1 2 3 4 5

i = 3

1 work

j = 0

Сортировка вставкой : 3-й проход

Page 76: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 3 7 12 8 0

0 1 2 3 4 5

1 work

i = 3j = 0

Сортировка вставкой : 3-й проход

Page 77: Программирование

4. Структурное программирование 4.7. Сортировка массивов

1 3 7 12 8 0

0 1 2 3 4 5

1 work

i = 3j = 0

Сортировка вставкой : 3-й проход

Page 78: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Простейшая программа сортировки вставкой: int main() {

item work; int i=0, j=0, k=0;for(i=1; i<=n; i++){

work=s[i]; // taking first non-sorted element for (j=i-1; work.key < s [j].key; j++); // search insert position for (k=i-1; k>=j; k--) s[k+1]=s[k]; //shift s[j]=work; // insert

}cout << endl;for (int i=0; i<=n; i++) cout << setw (4) << s[i].key;_getch(); return 0;

}

Page 79: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Оптимизированная программа сортировки вставкой: int main() { …

item work; int i=0, j=0;

for(i=1; i<=n; i++) {

work=s[i]; // taking first non-sorted elementfor (j = i-1; (work.key < s[j].key) && (j >= 0) ; j--) s[j+1] = s[j]; //search & shifts[j+1]=work; // insert

}

cout << endl; for (int i=0; i<=n; i++) cout << setw (4) << s[i].key; _getch(); }

Page 80: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Алгоритм сортировки выбором массива [0…n]

1. Для всех i от 0 до n выполнять:

1.1. Найти в части массива от i-го до n-го элемента элемент с минимальным значением ключа и поменять его местами с i-м элементом.

Page 81: Программирование

4. Структурное программирование 4.7. Сортировка массивов

12 3 7 1 8 0

0 1 2 3 4 5

i = 0

0 min

j = 5

Сортировка выбором : 1-й проход

Page 82: Программирование

4. Структурное программирование 4.7. Сортировка массивов

0 3 7 1 8 12

0 1 2 3 4 5

i = 0

0 min

j = 5

Сортировка выбором : 1-й проход

Page 83: Программирование

4. Структурное программирование 4.7. Сортировка массивов

0 3 7 1 8 12

0 1 2 3 4 5

i = 1

1 min

j = 3

Сортировка выбором : 2-й проход

Page 84: Программирование

4. Структурное программирование 4.7. Сортировка массивов

0 1 7 3 8 12

0 1 2 3 4 5

i = 1

1 min

j = 3

Сортировка выбором : 2-й проход

Page 85: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Программа сортировки выбором int main() { …

item min; int imin=0, i=0, j=0; for (i=0; i<=n-1; i++) {

for (j = i+1, min = s[i], imin = i; j <= n; j++) // search min element if (s[j].key < min.key) {

min = s[j]; imin = j; }

s[imin]=s[i]; s[i]=min; //change elements } … return 0; }

Page 86: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Алгоритм сортировки обменом (метод «пузырька»)

1. Для всех k от n до 1 выполнять :

1.1. Слева направо поочередно сравнивать два соседних элемента и если их взаиморасположение не соответствует заданному условию упорядоченности, то менять их местами.

Page 87: Программирование

4. Структурное программирование 4.7. Сортировка массивов

12 3 7 1 8 4

0 1 2 3 4 5

i = 0 k = 5

Сортировка обменом: 1-й проход

i +1= 1

Page 88: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 12 7 1 8 4

0 1 2 3 4 5

i = 1 k = 5

Сортировка обменом: 1-й проход

i +1= 2

Page 89: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 7 12 1 8 4

0 1 2 3 4 5

i = 2 k = 5

Сортировка обменом: 1-й проход

i +1= 3

Page 90: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 7 1 12 8 4

0 1 2 3 4 5

i = 3 k = 5

Сортировка обменом: 1-й проход

i +1= 4

Page 91: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 7 1 8 12 4

0 1 2 3 4 5

i = 4 k = 5

Сортировка обменом: 1-й проход

i +1= 5

Page 92: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 7 1 8 4 12

0 1 2 3 4 5

Сортировка обменом: 2-й проход

i = 0 k = 4i +1= 1

Page 93: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 7 1 8 4 12

0 1 2 3 4 5

Сортировка обменом: 2-й проход

i = 1 k = 4i +1= 2

Page 94: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 1 7 8 4 12

0 1 2 3 4 5

Сортировка обменом: 2-й проход

i = 2 k = 4i +1= 3

Page 95: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 1 7 8 4 12

0 1 2 3 4 5

Сортировка обменом: 2-й проход

i = 3 k = 4

i +1= 4

Page 96: Программирование

4. Структурное программирование 4.7. Сортировка массивов

3 1 7 4 8 12

0 1 2 3 4 5

Сортировка обменом: 3-й проход

i = 0 k = 3i +1= 1

Page 97: Программирование

4. Структурное программирование 4.7. Сортировка массивов

1 3 7 4 8 12

0 1 2 3 4 5

Сортировка обменом: 3-й проход

i = 1 k = 3i +1= 2

Page 98: Программирование

4. Структурное программирование 4.7. Сортировка массивов

1 3 7 4 8 12

0 1 2 3 4 5

Сортировка обменом: 3-й проход

i = 2 k = 3

i +1= 3

Page 99: Программирование

4. Структурное программирование 4.7. Сортировка массивов

1 3 4 7 8 12

0 1 2 3 4 5

Сортировка обменом: 4-й проход ?

i = 0 k = 3i +1= 1

Page 100: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Программа сортировки методом пузырька int main() { …

item work; for (int k=n; k>=1; k--) for (int i=0; i<=k-1; i++) if (s[i].key > s[i+1].key)

{ work=s[i]; s[i]=s[i+1]; s[i+1]=work;

} … return 0; }

Page 101: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Усовершенствованный метод пузырька int main() { …

item work; bool flag = true;

for (int k=n; (k>=1) && flag; k--) { flag=false; for (int i=0; i<=k-1; i++) if ( s[i].key > s[i+1].key ) {

work=s[i]; s[i]=s[i+1]; s[i+1]=work; flag=true; } }return 0}

Page 102: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Вычислительная сложность алгоритмов сортировки массивов

1.Сортировка вставкой for(i=1; i<=n; i++) { work=s[i]; // taking first non-sorted element for (j = i-1; (work.key < s[j].key) && (j >= 0) ; j--) s[j+1] = s[j]; //search & shift s[j+1]=work; // insert } Число сравнений при i-м просеивании Ci = 1 i-1,

в среднем Ci= i/2

Число присваиваний (пересылок) M i = (C i -1)+2 = = C i +1

Cmin= n = N-1 (где N – размер массива)

M min= 2*n = 2*(N-1)

Page 103: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Cmin= N-1

M min= 2*(N-1)

N-1

Cср= i/2 = (1/2+1/2(N-1))*(N-1)/2= ¼(N2-N)

i=1N-1

Mср= (i/2+2) = (5/2 + ½(N-1)+2)*(N-1) / 2 = ¼(N2+7N-16)

i=1N-1

Cmax= (i-1) = (0 + N-1)*(N - 1) / 2 = ½ (N2-N)

i=1N-1

Mmax= (i+1) = (2 + N-1)*(N - 1) / 2 = ½(N2-1)

i=1

Число сравнений при i-м просеивании Ci = 1 i-1,

в среднем Ci= i/2

Число присваиваний (пересылок) M i = (C i -1)+2 = = C i +1

Cmin= n = N-1 (где N – размер массива)

M min= 2*n = 2*(N-1)

Page 104: Программирование

4. Структурное программирование 4.7. Сортировка массивов

2. Сортировка выборомЧисло сравнений не зависит от начального порядка ключейC = ½ (n2-n)M ср= n(ln n + ), =0,577216…

3. Сортировка обменом (метод «пузырька»)Число сравнений не зависит от начального порядка ключейC = ½ (n2-n)M ср= ¾ (n2-n)

Page 105: Программирование

4. Структурное программирование 4.7. Сортировка массивов

Алгоритм бинарного поиска в массиве размера n+1

1.Положить left=0, right=n;2.Пока left < right выполнять

3.1. Найти индекс среднего элемента в массиве mid = (left+right)/2

3.2. Если для элемента массива с индексом mid значение ключа > искомого, положить right =mid-1, иначе если значение ключа < искомого, положить left = mid+1, иначе выйти из цикла (элемент с индексом mid найден);

3.Если значение ключа элемента с индексом mid совпадает с заданным, поиск успешен, иначе – искомого элемента в массиве нет.

Page 106: Программирование

4. Структурное программирование 4.7. Сортировка массивов

int main() // Binary search in array {

struct item {unsigned int key;

// add members you want}; const int n=9; // right boundary of the array typedef item t_array [n+1];t_array s; unsigned int key_to_find=0;

for (int i=0; i<=n; i++) s[i].key = i+10;for (int i=0; i<=n; i++) cout << setw (4) << s[i].key;

Page 107: Программирование

4. Структурное программирование 4.7. Сортировка массивов

cout << "\nEnter your value of key: "; cin >> key_to_find;

int left = 0, right = n, mid = 0; while (left <= right){

mid = (left+right)/2;if (s[mid].key > key_to_find) right = mid-1;else if (s[mid].key < key_to_find)left = mid+1;else break;

}if (s[mid].key == key_to_find) cout << "\nOK, element no " << mid;else cout << "\nThere is no element with required value of key";cout << endl;

_getch(); return 0;}

Page 108: Программирование

4. Структурное программирование 4.8. Указатели

Что такое указателиКаждый байт в памяти ЭВМ имеет адрес по которому можно обратиться к определенному элементу данныхУказатель – это переменная, которая сохраняет адрес другой переменной определенного типа.

Содержимое указателя содержит адрес, начиная с которого размещается переменная, на которую ссылается указатель.

По описанию указателя компилятор получает информацию о том, какова длина области памяти, на которую ссылается указатель (которую занимает переменная, на которую он ссылается) и о том, как интерпретировать данные в этой области памяти.

Таким образом, переменная-указатель обладает именем и имеет тип, определяющий на какого рода данные она может ссылаться.

Page 109: Программирование

4. Структурное программирование 4.8. Указатели

Объявление указателя: Базовый_тип *Имя_Указателя;

int k = 0;short j=0;int *p_i = NULL;

NULL 0 0

0013FF50 0013FF52 0013FF54 0013FF56 0013FF58 0013FF5A

2 байта

p_i k j

Page 110: Программирование

4. Структурное программирование 4.8. Указатели

Операция взятия адреса: &Имя_Переменной

p_i = &k

0013FF56 0 0

0013FF50 0013FF52 0013FF54 0013FF56 0013FF58 0013FF5A

p_i k j

Page 111: Программирование

4. Структурное программирование 4.8. Указатели

Операция взятия адреса

нельзя p_i = &j; (p_i – указатель на int, a j объявлена как short)

0013FF56 0 0

0013FF50 0013FF52 0013FF54 0013FF56 0013FF58 0013FF5A

p_i k j

Page 112: Программирование

4. Структурное программирование 4.8. Указатели

Операция разыменования: *Имя_Указателя

*p_i = 123; // k = 123

0013FF56 123 0

0013FF50 0013FF52 0013FF54 0013FF56 0013FF58 0013FF5A

p_i k j

123

Page 113: Программирование

4. Структурное программирование 4.8. Указатели

Операция разыменования

j = *p_i; // j = k

0013FF56 123 123

0013FF50 0013FF52 0013FF54 0013FF56 0013FF58 0013FF5A

p_i k j

Page 114: Программирование

4. Структурное программирование 4.8. Указатели

Операция взятия адреса: как размещаются в памяти переменные и элементы массивов

int main() {

short c1 = '1', c2 = '2', c3 = '3';short c4[3] = {1,2,3};

cout << &c1 << endl; // 0013FF5С cout << &c2 << endl; // 0013FF50

cout << &c3 << endl; // 0013FF44 cout << endl;

cout << &c4[1] << endl; // 0013FF36cout << &c4[2] << endl; // 0013FF38

cout << &c4[3] << endl; // 0013FF40

return 0; }

Debug Mode

12 байт между адресами переменных

2 байта между адресами элементов массива, строго упорядочены

Page 115: Программирование

4. Структурное программирование 4.8. Указатели

Операция взятия адреса: как размещаются в памяти переменные и элементы массивов

int main() {

short c1 = '1', c2 = '2', c3 = '3';short c4[3] = {1,2,3};

cout << &c1 << endl; // 0013FF70 cout << &c2 << endl; // 0013FF68

cout << &c3 << endl; // 0013FF6C cout << endl;

cout << &c4[1] << endl; // 0013FF76cout << &c4[2] << endl; // 0013FF78

cout << &c4[3] << endl; // 0013FF7A

return 0; }

Release Mode

2 байта между адресами переменных, неупорядочены

2 байта между адресами элементов массива, строго упорядочены

Page 116: Программирование

4. Структурное программирование 4.8. Указатели

Особенности синтаксиса объявления указателейПервый способ записи:

Базовый_тип *Имя_Указателя;Нет проблем с объявлением нескольких указателей:

int *pa, *pb, *pc;Второй способ записи:

Базовый_тип* Имя_Указателя;Позволяет идентифицировать тип «указатель на базовый тип» как Базовый_тип* . Однако , эта форма записи вызывает проблемы при множественном объявлении перемненых:

int* pa, ib, ic;Во избежание путаницы, если Вы придерживаетесь второго способа, никогда не декларируйте в одном инструкции более одной (указательной) переменной. В качестве базового типа можно указать void: void *p; Указатель на void не может быть разыменован

Page 117: Программирование

4. Структурное программирование 4.8. Указатели

Инициализация указателейУказатель можно инициализировать адресом переменной, которая уже определена:double dvar = 0.0;double *pvar = &dvar;

Инициализация значением NULL гарантирует, что указатель не содержит адреса, который воспринимается как корректный, а значение можно проверить в инструкции if :int *pinteger = NULL;if (pinteger == NULL) cout << “pinteger is null”;

равнозначная альтернатива инициализировать указатель 0:int *pinteger = 0;if (!pinteger) cout << “pinteger is null”;

Page 118: Программирование

4. Структурное программирование 4.8. Указатели

Присваивание указателей. Неявное приведение типов.int main(){ int x=0; int *pi_1=NULL, *pi_2=NULL; double *pd_1=NULL; void *pv_1=NULL;

pi_1 = &x; pi_2 = pi_1;// pd_1=pi_1; prohibited !!! pv_1=pi_1; // pi_2=pv_1; prohibited !!!

return 0}

Page 119: Программирование

4. Структурное программирование 4.8. Указатели

Присваивание указателей. Явное приведение типов

int main() { int x=123; int *pi_1=NULL; float *pf_1=NULL; double *pd_1=NULL;

pi_1 = &x; cout << pi_1 << " " << *pi_1 << endl; // 0013FF60 123 pf_1=reinterpret_cast <float*> (pi_1); cout << pf_1 << " " << *pf_1 << endl; // 0013FF60 1.7236e-043 pd_1=reinterpret_cast <double*> (pi_1); cout << pd_1 << " " << *pd_1 << endl; // 0013FF60 -9.25596e+061 return 0}

Используйте reinterpret_cast только по большой нужде!!!

Page 120: Программирование

4. Структурное программирование 4.8. Указатели

Явное приведение типов. Почти катастрофа.

short c1=1, c2=2, c3=3; double *pf = reinterpret_cast <double*> (&c1); *pf = 12345e99;

0013FF34 1 3 2

0013FF30 0013FF32 0013FF34 0013FF36 0013FF38 0013FF3A 0013FF3C 0013FF3E

c1 c2c3pf

Page 121: Программирование

4. Структурное программирование 4.8. Указатели

Явное приведение типов. Почти катастрофа.

short c1=1, c2=2, c3=3; double *pf = reinterpret_cast <double*> (&c1); *pf = 12345e99;

0013FF34 1.2345e103 2

0013FF30 0013FF32 0013FF34 0013FF36 0013FF38 0013FF3A 0013FF3C 0013FF3E

c1 c2c3pf

Page 122: Программирование

4. Структурное программирование 4.8. Указатели

Явное приведение типов. Почти катастрофа.

int main() { short c1=1, c2=2, c3=3; double *pf = reinterpret_cast <double*> (&c1);

cout << &c1 << endl; // 0013FF34 cout << &c2 << endl; // 0013FF3C cout << &c3 << endl; // 0013FF38

cout << c1 << c2 << c3 << endl; // 1 2 3 *pf = 12345e99; cout << *pf << endl; // 1.2345e103 cout << c1 << c2 << c3 << endl; // 30764 2 3090 _getch(); return 0;}

Page 123: Программирование

4. Структурное программирование 4.8. Указатели

Адресная арифметикаК указателям можно применять только две арифметические операции: сложения и вычитания. При добавлении к указателю целого числа N значение указателя увеличивается на N*L, где L – длина базового типа на котороый ссылается указатель. При вычитании N значение указателя уменьшается на N*L. (Говоря другими словами, мы смещаемся в памяти на N длин элементов базового типа.Указатели можно вычитать. Результатом вычитания является количество объектов базового типа, которые можно расположить между указателями.Нельзя производить вычитание разнотипных указателей.Нельзя складывать указатели

Использовать арифметику указателей, как правило, имеет смысл только применительно к элементам массивов

Page 124: Программирование

4. Структурное программирование 4.8. Указатели

0013FF60 0 1 4 9 16 25

K[0] K[1] k[2] k[3] K[4] K[5]

F5С F5D F5E F5F F60 F61 F62 F63 F64 F65 F66 F67 F68 F69 F6A F6B

36 49 64

k[6] K[7] K[8]

F6C F6D F6E F6F F70 F71 F72 F73 F74

p k

short k [10] = {0};short *p = k; // pointer to the first element, the same like *p=&k[0]for (int i=0; i<=8; i++) k[i]= i*i; cout << &p << endl; // 0013FF5C where the pointer p is placedcout << k << " " << &k << " " << p << endl; //0013FF60 0013FF60 0013FF60 cout << *k << " " <<*p << endl; // 0 0

Адресная арифметика: пример с одномерным массивом

Исходное состояние:

Page 125: Программирование

4. Структурное программирование 4.8. Указатели

0013FF64 0 1 4 9 16 25

k[0] k[1] k[2] k[3] k[4] k[5]

F5С F5D F5E F5F F60 F61 F62 F63 F64 F65 F66 F67 F68 F69 F6A F6B

p k

p+=3; // k++; prohibited: can’t change address of arraycout << k+3 <<" "<< p << endl; // 0013FF66 //0013FF66 cout << *(k+3) << " " << *p; // 9 9

Адресная арифметика: пример с одномерным массивом

Исходное состояние: 36 49 64

K[6] K[7] K[8]

F6C F6D F6E F6F F70 F71 F72 F73 F74

k+3

Page 126: Программирование

4. Структурное программирование 4.8. Указатели

0013FF64 0 1 4 9 16 25

k[1] k[2] k[3] k[4] k[5] k[6]

F5С F5D F5E F5F F60 F61 F62 F63 F64 F65 F66 F67 F68 F69 F6A F6B

p k

cout << &k[6] - &k[2]; // 4 // cout << &p - & k[1]; prohibited: different basic types of pointers

Адресная арифметика: пример с одномерным массивом

Исходное состояние: 36 49 64

k[7] k[8] k[9]

F6C F6D F6E F6F F70 F71 F72 F73 F74

Page 127: Программирование

4. Структурное программирование 4.8. Указатели

Сравнение указателейУказатели можно сравнивать между собой. Как правило, указатели сравнивают, когда они ссылаются на один и тот же объект, например, массив. Сравнивать указатели, если их базовый тип различается, нельзя. Если это необходимо, следует воспользоваться операцией приведения типа reinterpret_cast. (Либо присвоить их значения указателям на void, что выглядит достаточно гнусно).

Page 128: Программирование

4. Структурное программирование 4.8. Указатели

Указатели и одномерные массивыПо сути, объявляя массив, мы объявляем имя массива как указатель на его первый элемент. Так, пусть объявлен массив m и указатель ps:short m [8];short *ps;Идентификатор m будет восприниматься как указатель на первый элемент, значение которого нельзя изменить (константный указатель).C именем массива можно работать как с указателем на первый элемент:ps = m;cout << m << ps; // 0013FEDC 0013FEDC

Page 129: Программирование

4. Структурное программирование 4.8. Указатели

Указатели и массивы : информация к размышлению int main() { typedef int t_array_int [4]; t_array_int a={1,2,3,4}, b={10,20,30,40}; int *pint, *pint1=NULL; t_array_int *parint=NULL;

cout << "a= " << a << endl; // 0013FF54 pint=a; cout << "pint=a " << pint << endl; // 0013FF54 pointer to the first element // parint=a; prohibited!!!// pint=&a; prohibited!!! parint=&a; cout<< "parint=&a " << parint << endl; // 0013FF54 pointer to the whole array// parint=&pint; prohibited!!! cout << "*pint " << *pint << endl; // 1 cout << "*parint " << *parint << endl; // 0013FF54 cout << "**parint " << **parint << endl; // 1// a=b; prohibited !!! pint1=b; pint=pint1; cout << "pint " << pint << endl; // 0013FF3C cout << "*pint+2 " << *(pint+2); // 30

Page 130: Программирование

4. Структурное программирование 4.8. Указатели

Указатели и одномерные массивыПрименяя к идентификатору одномерного массива операцию [n], мы смещаемся на n элементов относительно начала и разыменовываем полученный указатель на n-й элемент массива. То же можно сделать явно, используя адресную арифметику

short a [8] = {10,11,12,13,14,15,16,17};cout << a [3]; // 13cout << *(a+3); // 13

10 11 12 13 14 15 16 17

0 1 2 3 4 5 6 7

a[0]

a

a[3]

a+3

Page 131: Программирование

4. Структурное программирование 4.8. Указатели

Указатели и многомерные массивыВ случае многомерного массива смещение можно рассчитать вручную, учитывая, что в С++ многомерные массивы вытягиваются в памяти «по строкам» (вначале изменяется крайний правый индекс, потом второй справа и т.д.). const int m=3, n=4; int ai [m][n] = { {0, 1, 2, 3}, {10, 11, 12, 13} , {20, 21, 22, 23} };int *pi=&ai[0][0];int i=2, j=2;cout << ai [i][j] << endl; // 22cout << *(pi+(j+i*n)) << endl; // 22

0 1 2 3 10 11 12 13 20 21 22 23

[0][0] [0][1] [0][2] [0][3] [1][0] [1][1] [1][2] [1][3] [2][0] [2][1] [2][2] [2][3]

ai[0][0]

pi

ai[2][2]

pi+(j+i*n)

Page 132: Программирование

4. Структурное программирование 4.8. Указатели

Указатели и многомерные массивыИдентификатор многомерного массива трактуется как указатель на массив (для двумерного массива - указатель на первую строку). Исходя из этого, можно поступить и иначе:

const int m=3, n=4; int ai [m][n] = { {0, 1, 2, 3}, {10, 11, 12, 13} , {20, 21, 22, 23} };

int i=2, j=2;cout << ai [i][j] << endl; // 22cout << * (*(ai+i)+j) // 22

0 1 2 3 10 11 12 13

[0][0] [0][1] [0][2] [0][3] [1][0] [1][1] [1][2] [1][3] [2][0] [2][1] [2][2] [2][3]

aik+i

* (ai+i)

*(ai+i)+j

Page 133: Программирование

4. Структурное программирование 4.8. Указатели

Массивы указателейНикто не мешает нам описать не просто указатель на int, но и массив указателей на int:

int * pparint [10];

int a=0;int b=1;pparint [1]=&a;pparint [2]=&b;*pparint[1]= *pparint[2];cout << pparint[1] << pparint[2];cout << *pparint[1] << *pparint[2];

Page 134: Программирование

4. Структурное программирование 4.8. Указатели

Указатели и строки Имя массива элементов типа char трактуется, как и для любых других массивов как указатель на его первый (номер 0) элемент. Особенность: в контексте программы имя массива типа char автоматически разыменовывается, в результате чего мы получаем строку, начинающуюся с первого (номер 0) элемента и заканчивающуюся нулевым символом. Интересно, что указатель на char тоже автоматически разыменовывается по тем же правилам. То есть, в результате выполненияchar c=‘a’;char *pc=&c;cout << pc; // aивесьмусорвпамятидоближайшегонулевогоэлементаcout << *pc; // acout << &pc ; // 0013FF0C

Page 135: Программирование

4. Структурное программирование 4.8. Указатели

Указатели и строки : информация к размышлению

typedef char t_array_char [4];t_array_char c="abc";char *pchar=NULL;t_array_char *parchar=NULL;

cout << "c= " << c << endl; // abcpchar=c; cout << "pchar=c " << pchar << endl; // abc

// parchar=c; prohibited!!!// pchar=&c; prohibited!!!

parchar=&c; cout<< "parchar=&c " << parchar << endl; // 0013FF0C// parint=&pint; prohibited!!!

cout << "*pchar " << *pchar << endl; // acout << "*parchar " << *parchar << endl; // abc

cout << "**parchar " << **parchar << endl; // a// a=b; prohibited !!!

cout << "*pchar+2 " << *(pchar+2); // c

Page 136: Программирование

4. Структурное программирование 4.8. Указатели

Инициализация указателей на char Раньше мы инициализировали строкой массивы типа char.Указатель на символ !!! char* также можно инициализировать строковым литералом. В этом случае указатель будет содержать адрес, по которому в оперативной памяти, в т.н. «таблице строк», размещен строковый литерал – неименованная константа

char *pverb=“Hello”;

Изменение в программе значения такого указателя – весьма дурной тон. C формальной точки зрения в С++ строковый литерал имеет тип не char* , а const char*. Просто в языке С++ предусмотрено автоматическое преобразование типа const char* в тип char*. Хорошим стилем считается, если Вы пишете программу на С++ , строковый литерал считать константным и объявлять:

const char *pverb = “Hello”;

Page 137: Программирование

4. Структурное программирование 4.8. Указатели

Инициализация указателей на char . Пример

int main() // prints the string forward and backwards {

const char *p="Hello";cout << "*p= " <<*p << endl; // Hcout << "p = " << p << endl << endl; // Hello

for (int t = strlen(p)-1 ; t >= 0; t--) cout << p[t]; // olleH

cout << endl;_getch(); return 0;

}

Page 138: Программирование

4. Структурное программирование 4.8. Указатели

Указатели на структурыОбъявление указателя на структуру ничем не отличается от обычного:

struct cmplx{ double re; double im;};

cmplx c1, c2;cmplx *pc;pc = &c1;

Page 139: Программирование

4. Структурное программирование 4.8. Указатели

Указатели на структурыДля доступа к членам структуры по указателю на нее можно воспользоваться операцией разыменования:(*pc).re = 1; cout << c1.re; // 1

Однако, лучше использовать специальную операцию ссылки на член структуры (оператор «стрелка»):pc->re = 2; cout << c1.re; // 2pc->im = pc->re;pc=&c2;pc->re=c1.re;pc->im=c1.im;

Итак, оператор «.» используется для непосредственного обращения к членам структуры, а оператор «->» для доступа к членам структуры через указатель на нее.

Page 140: Программирование

4. Структурное программирование 4.8. Указатели

Указатель на указательshort **ppshort=NULL;short *pshort=NULL;short a=3;pshort=&a;ppshort = &pshort;cout << ppshort << *ppshort << **ppshort // 0013FF4C 0013FF52 3

NULL NULL 3

F48 F49 F4A F4B F4C F4D F4E F4F F50 F51 F52 F53 F54 F55

ppshort pshort a

Page 141: Программирование

4. Структурное программирование 4.8. Указатели

Указатель на указательshort **ppshort=NULL;short *pshort=NULL;short a=3;pshort=&a;ppshort = &pshort;cout << ppshort << *ppshort << **ppshort // 0013FF4C 0013FF52 3

NULL 0013FF52 3

F48 F49 F4A F4B F4C F4D F4E F4F F50 F51 F52 F53 F54 F55

ppshort pshort a

Page 142: Программирование

4. Структурное программирование 4.8. Указатели

Указатель на указательshort **ppshort=NULL;short *pshort=NULL;short a=3;pshort=&a;ppshort = &pshort;cout << ppshort << *ppshort << **ppshort // 0013FF4C 0013FF52 3

0013FF4C 0013FF52 3

F48 F49 F4A F4B F4C F4D F4E F4F F50 F51 F52 F53 F54 F55

ppshort pshort a

Page 143: Программирование

4. Структурное программирование 4.8. Указатели

Операция sizeof Операция sizeof будучи применена к какому-либо объекту возвращает целое число – количество байт, занимаемых ее операндом.

int m=0; double k=0;char *pchar;short l [6][5];

cout << sizeof m; // 4cout << sizeof k ; // 8cout << sizeof pchar; // 4cout << sizeof *pchar; // 1cout << sizeof l ; // 60 bytes cout << (sizeof l) / (sizeof l[0][0]) ; // 30 number of elementscout << (sizeof l) / (sizeof l[0]) ; // 6 number of rows

Page 144: Программирование

4. Структурное программирование 4.9. Ссылки

Ссылки Ссылка (reference) – псевдоним для другой переменной. Ссылка имеет имя, которое может использоваться вместо имени переменной. Так как ссылка – это псевдоним, а не указатель, переменная, для которой она определяется, должна быть объявлена ранее. В отличие от указателя ссылка не может быть изменена, чтобы представлять другую переменную Объявление и инициализация: Базовый_тип &Имя_Ссылки = Имя_Переменной;

int number = 0;int &rnumber = number; // ссылка int *pnumber = &number // указательСсылку, можно использовать вместо имени исходной переменной:

rnumber +=10;*pnumber +=10; // требуется разыменование Ссылка подобна указателю, который уже разыменован и значение которого нельзя изменить.

Page 145: Программирование

4. Структурное программирование 4.9. Ссылки

Ссылки чаще всего используют для передачи аргументов в функции, однако иногда их можно использовать в качестве синонимов для упрощения текста программы.

Например, вместо //init array rfe Date initdate = {1900,1,1}; for (int i = 0; i < nmembers; i++) { rfe[i].id=0; strcpy(rfe[i].ownname.surname,""); strcpy(rfe[i].ownname.firstname,""); strcpy(rfe[i].ownname.patronymic,""); rfe[i].birth=initdate; rfe[i].enter=initdate; strcpy (rfe[i].position,"student"); rfe[i].tradeunion=false; }

Page 146: Программирование

4. Структурное программирование 4.9. Ссылки

Можно записать

//init array rfe Date initdate = {1900,1,1}; for (int i = 0; i < nmembers; i++) { Member &t = rfe[i]; t.id=0; strcpy(t.ownname.surname,""); strcpy(t.ownname.firstname,""); strcpy(t.ownname.patronymic,""); t.birth=initdate; t.enter=initdate; strcpy (t.position,"student"); t.tradeunion=false; }

Page 147: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

Память для глобальных переменных распределяется на этапе компиляции и выделяется при загрузке программы в память.

Память для локальных переменных выделяется в области стека в момент начала выполнения функции.

Мы не можем в процессе выполнения программы объявить новые локальные или глобальные переменные, хотя необходимость этого может выясниться только в процессе выполнения.

Мы не можем работать со структурами данных, размер которых может изменяться в процессе выполнения программы (списки, стеки, очереди, деревья)

Механизм динамического распределения памяти позволяет программе получать необходимую для хранения данных память в процессе своего выполнения.

Для получения доступа к динамически выделяемым областям памяти и их типизации служат указатели.

Page 148: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

В языке С++ имеются два оператора динамического распределения памяти: new и delete. (В С используются функции malloc() и free()).

Выделение памяти:

Имя_Указателя = new Тип;

Имя_Указателя = new Тип (инициализирующее_значение);

Освобождение памяти:

delete Имя_Указателя;

Разумеется, перед использованием оператора new следует описать используемый указатель.

Page 149: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

NULL NULL …

F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2

float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;

Динамическое выделение памяти для переменных

ps pf

Page 150: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

NULL 003B619D …

F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2

float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;

Динамическое выделение памяти для переменных

ps pf

Page 151: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

NULL 003B619D … 4.5

F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2

float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;

Динамическое выделение памяти для переменных

ps pf

Page 152: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

003B61A1 003B619D … 4.5 3

F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2

float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;

Динамическое выделение памяти для переменных

ps pf

Page 153: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

003B61A1 003B619D … 3.0 3

F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2

float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;

Динамическое выделение памяти для переменных

ps pf

Page 154: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

003B61A1 003B619D … 3.0

F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2

float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;

Динамическое выделение памяти для переменных

ps pf

Page 155: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

003B61A1 003B619D …

F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2

float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;

Динамическое выделение памяти для переменных

ps pf

Page 156: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

003B6188 …

F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F

struct cmplx{ double re; double im;};cmplx *pc = new cmplx;cout << &pc << endl; // 0013FF5Сcout << pc; // 003B6188pc->re=1.0;pc->im=0;cout <<pc->re; // 1delete pc;

Динамическое выделение памяти для структур

pc

Page 157: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

003B6188 … 1.0 0.0

F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F

struct cmplx{ double re; double im;};cmplx *pc = new cmplx;cout << &pc << endl; // 0013FF5Сcout << pc; // 003B6188pc->re=1.0;pc->im=0;cout <<pc->re; // 1delete pc;

Динамическое выделение памяти для структур

pc

Page 158: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

003B6188 …

F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F

struct cmplx{ double re; double im;};cmplx *pc = new cmplx;cout << &pc << endl; // 0013FF5Сcout << pc; // 003B6188pc->re=1.0;pc->im=0;cout <<pc->re; // 1delete pc;

Динамическое выделение памяти для структур

pc

Page 159: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

003B6188 …

pa[0] pa[1] pa[2] pa[3]

F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F

int k=0; cin >> k; // 4short *pa = new short [k];cout << &pa << endl; // 0013FF5Сcout << pa; // 003B6188for (int i=0; i<=3; i++) pa[i]=i*i;cout << *pa; // 0cout << pa[2]; // 4delete [ ] pa;

Динамическое выделение памяти для одномерных массивов

pa

Обратите внимание на особенности выделения памяти для массива:

-указатель объявляется на базовый тип массива;- размер массива указывается в квадратных скобках после идентификатора типа в new -допустим неконстантный размер массива

Page 160: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

003B6188 … 0 1 4 9

pa[0] pa[1] pa[2] pa[3]

F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F

int k=0; cin >> k; // 4short *pa = new short [k];cout << &pa << endl; // 0013FF5Сcout << pa; // 003B6188for (int i=0; i<=3; i++) pa[i]=i*i;cout << *pa; // 0cout << pa[2]; // 4delete [ ] pa;

Динамическое выделение памяти для одномерных массивов

pa

Обратите внимание: -для получения доступа к элементу массива разыменовывать указатель не надо! Операция [ ] вычисляет адрес элемента массива и разыменовывает соответствующий указатель

Page 161: Программирование

4. Структурное программирование 4.10. Динамическое распределение памяти

003B6188 …

F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F

int k=0; cin >> k; // 4short *pa = new short [k];cout << &pa << endl; // 0013FF5Сcout << pa; // 003B6188for (int i=0; i<=3; i++) pa[i]=i*i;cout << *pa; // 0cout << pa[2]; // 4delete [ ] pa;

Динамическое выделение памяти для одномерных массивов

pa

Обратите внимание на особенности освобождения

памяти от массива: - квадратные скобки после delete,- размер массива не указывается!

Page 162: Программирование

Ранее разработанная программа работы с n-мерными векторами

4. Структурное программирование 4.10. Динамическое распределение памяти

int main() { const int n=4; double a[n]={0}, b[n]={0}, res[n]={0};

cout << "Enter..." << endl; for (int i=1; i<=n; i++)

{ cout << endl << "a" << i << ": ";

cin >> a[i-1]; cout << "b" << i << ": "; cin >> b[i-1];}

Page 163: Программирование

Ранее разработанная программа работы с n-мерными векторами

4. Структурное программирование 4.10. Динамическое распределение памяти

for (int i=1; i<=n; i++) res[i-1]=a[i-1]+b[i-1]; //Sum cout << endl << "a + b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")";

for (int i=1; i<=n; i++) res[i-1]=a[i-1]-b[i-1]; //Difference cout << endl << "a - b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")"; double r=0; for (int i=1; i<=n; i++) r+=a[i-1]*b[i-1]; //Product cout << endl << "a * b = " << r;

_getch(); return 0;};

Page 164: Программирование

Новая версия программы работы с n-мерными векторами

4. Структурное программирование 4.10. Динамическое распределение памяти

int main() {int n=0; cout << "Enter dimension n: "; cin >> n; double* a = new double[n]; double* b = new double[n]; double* res = new double[n];

cout << "Enter..." << endl; for (int i=1; i<=n; i++)

{ cout << endl << "a" << i << ": ";

cin >> a[i-1]; cout << "b" << i << ": "; cin >> b[i-1];}

Page 165: Программирование

Новая версия программы работы с n-мерными векторами

4. Структурное программирование 4.10. Динамическое распределение памяти

for (int i=1; i<=n; i++) res[i-1]=a[i-1]+b[i-1]; //Sum cout << endl << "a + b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")";

for (int i=1; i<=n; i++) res[i-1]=a[i-1]-b[i-1]; //Difference cout << endl << "a - b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")"; double r=0; for (int i=1; i<=n; i++) r+=a[i-1]*b[i-1]; //Product cout << endl << "a * b = " << r;

_getch(); return 0;};

Page 166: Программирование

Ранее разработанная программа нахождения простых чисел

int main() // sieve of Eratosthenes{ const unsigned int n = 1000; const unsigned int size = n+1; bool erato [size]={0};

for (int i = 2; i <= n; i++) erato [i] = 1; for (int i = 2; i <= static_cast <int> (sqrt(static_cast <float> (n))); i++) { if (erato[i]) for (int j = i; j <= n; j++) {

if (i*j > n)break;erato [i*j]=false;

} } for(int i=2; i <= n; i++) if (erato[i]) cout << i << endl;return 0;}

4. Структурное программирование 4.10. Динамическое распределение памяти

Page 167: Программирование

Новая программа нахождения простых чисел int main() // sieve of Eratosthenes: dynamic store allocation{ int n = 0; cout << "Enter max number:"; cin >> n; if (n <= 0)return -1; bool *perato = new bool [n+1];

for (int i = 2; i <= n; i++) perato [i] = 1; for (int i = 2; i <= static_cast <int> (sqrt(static_cast <float> (n))); i++) { if (perato[i]) for (int j = i; j <= n; j++) {

if (i*j > n)break;perato [i*j]=false;

} } for(int i=2; i <= n; i++) if (perato[i]) cout << i << endl; delete [ ] perato; return 0;}

4. Структурное программирование 4.10. Динамическое распределение памяти

Page 168: Программирование

Эмуляция двумерного массива размером [n] [m]

4. Структурное программирование 4.10. Динамическое распределение памяти

int **pr int * int

int **pr;

Page 169: Программирование

Эмуляция двумерного массива размером [n] [m]

4. Структурное программирование 4.10. Динамическое распределение памяти

int **pr

int **pr;pr = new int* [n]

int *

int *

int *

int *

0

1

2

n-1

int

int

int

int

Page 170: Программирование

Эмуляция двумерного массива размером [n] [m]

4. Структурное программирование 4.10. Динамическое распределение памяти

int **pr

int **pr;pr = new int* [n]for (int i=0; i<=n-1; i++) pr[i] = new int [m];

int *

int *

int *

int *

0

1

2

n-1

int int … int

int int … int

int int … int

int int … int

0 1 m-1

Page 171: Программирование

Эмуляция двумерного массива размером [n] [m]

4. Структурное программирование 4.10. Динамическое распределение памяти

int **pr

int **pr;pr = new int* [n]for (int i=0; i<=n-1; i++) pr[i] = new int [m];

int *

int *

int *

int *

0

1

2

n-1

int int … int

int int … int

int int … int

int int … int

0 1 m-1

pr

Page 172: Программирование

Эмуляция двумерного массива размером [n] [m]

4. Структурное программирование 4.10. Динамическое распределение памяти

int **pr

int **pr;pr = new int* [n]for (int i=0; i<=n-1; i++) pr[i] = new int [m];

int *

int *

int *

int *

0

1

2

n-1

int int … int

int int … int

int int … int

int int … int

0 1 m-1

pr *

Page 173: Программирование

Эмуляция двумерного массива размером [n] [m]

4. Структурное программирование 4.10. Динамическое распределение памяти

int **pr

int **pr;pr = new int* [n]for (int i=0; i<=n-1; i++) pr[i] = new int [m];

int *

int *

int *

int *

0

1

2

n-1

int int … int

int int … int

int int … int

int int … int

0 1 m-1

pr [2]

Page 174: Программирование

Эмуляция двумерного массива размером [n] [m]

4. Структурное программирование 4.10. Динамическое распределение памяти

int **pr

int **pr;pr = new int* [n]for (int i=0; i<=n-1; i++) pr[i] = new int [m];

int *

int *

int *

int *

0

1

2

n-1

int int … int

int int … int

int int … int

int int … int

0 1 m-1

pr [2][1]

Page 175: Программирование

Эмуляция двумерного массива

4. Структурное программирование 4.10. Динамическое распределение памяти

int main() // Dynamic store allocation for 2D array [n][m]{ int m = 0, n=0; cout << "Enter matrix size (n,m):"; cin >> n,m; if ((n <= 1)||(m<=1))return -1; cout << "m= " << m << " n= " << n << endl;

int* *pr = new int*[n]; // pointer to allocating array of pointers to rows for (int i=0; i<=n-1; i++) pr[i] = new int [m]; // allocating rows for (int i=0; i<=n-1; i++) for (int j=0; j<=m-1; j++) pr [i][j]=i*100+j; // init array

for (int i=0; i<=n-1; i++) delete [] pr[i]; // free memory of rows delete [ ]pr; // free memory of array of pointers to rows

_getch();return 0;}