Скачать презентацию Одномерные массивы_1 Передача одномерного массива Скачать презентацию Одномерные массивы_1 Передача одномерного массива

Алгоритмизация и программированиеI__9_2.ppt

  • Количество слайдов: 105

 • Одномерные массивы_1 • Передача одномерного массива в функцию в качестве параметра • • Одномерные массивы_1 • Передача одномерного массива в функцию в качестве параметра • Одномерные массивы_2 • Сортировка_1

I. Описать синтаксис понятий языка С++: 1) определение функции 2) вызов функции 3) объявление I. Описать синтаксис понятий языка С++: 1) определение функции 2) вызов функции 3) объявление функции II. Что вычисляет данная функция? int Fun(int a, int b) { do { if (a>b) a= a%b; else b=b%a; } while (a!=0 && b!=0); return a+b; }

5 Одномерные массивы_1 Лекция 9 5 Одномерные массивы_1 Лекция 9

6 Что такое массив? ? Как ввести 10000 переменных? Массив – это группа переменных 6 Что такое массив? ? Как ввести 10000 переменных? Массив – это группа переменных одного типа, расположенных в памяти рядом (в соседних ячейках) и имеющих общее имя. Каждая ячейка в массиве имеет уникальный номер (индекс). Массив – набор однотипных данных, которые характеризуются общим именем, типом и отличаются друг от друга только числовым индексом. Надо: • выделять память • записывать данные в нужную ячейку • читать данные из ячейки

Определение массива ■ ■ ■ Размерность массива – количество индексов, необходимых для указания местонахождения Определение массива ■ ■ ■ Размерность массива – количество индексов, необходимых для указания местонахождения элемента массива (для одномерного массива – одним, для двухмерного – двумя и т. д. ). Размер задается целой положительной константой или константным выражением. Определение одномерного массива: ❑ тип имя [размер массива]; ❑ int A[20]; ❑ float z[30]; 7

Обращение к элементу массива ■ ■ ■ К отдельному элементу массива можно обратиться при Обращение к элементу массива ■ ■ ■ К отдельному элементу массива можно обратиться при помощи переменной с индексом: имени массива (единого для всех элементов) и одного индекса. Индекс может меняться от 0 до n-1, где n – количество элементов массива, его размер. Максимальный индекс элемента всегда на 1 меньше размера массива. 8

9 Выделение памяти (объявление) ! Массив = таблица! число элементов int A[5]; double V[8]; 9 Выделение памяти (объявление) ! Массив = таблица! число элементов int A[5]; double V[8]; bool L[10]; char S[80]; ! Элементы всегда нумеруются с нуля! A[0], A[1], A[2], A[3], A[4] размер через константу const int N = 10; int A[N]; ? Зачем?

Примеры ■ ■ Описание массива: ❑ char buffer[81]; //массив состоит из элементов buffer[0], … Примеры ■ ■ Описание массива: ❑ char buffer[81]; //массив состоит из элементов buffer[0], … buffer[80] типа char; ❑ int key[4]; //массив состоит из элементов key[0], … key[3] типа int; ❑ float a[10]; //массив состоит из элементов a[0], … a[9] типа float; Задание размера через константу ❑ const int N = 10; ❑ int M[N]; 10

Указатели и массивы • При определении массива ему выделяется память. После этого имя массива Указатели и массивы • При определении массива ему выделяется память. После этого имя массива воспринимается как константный указатель того типа, к которому относятся элементы массива. a int a[100]; sizeof(a)==400; sizeof(a)/sizeof(int) == 100; 0 1 2 . . . 99 Результатом операции & является адрес нулевого элемента массива: a==&a[0]

имя_массива[индекс] ==*(имя_массива+индекс) Примеры for(int i=0; i<n; i++) cout<<*(a+i)<< имя_массива[индекс] ==*(имя_массива+индекс) Примеры for(int i=0; i

13 Обращение к элементу массива A массив 0 НОМЕР элемента массива (ИНДЕКС) 1 5 13 Обращение к элементу массива A массив 0 НОМЕР элемента массива (ИНДЕКС) 1 5 10 A[0] A[1] 2 2 15 15 3 4 20 25 ЗНАЧЕНИЕ A[2] A[3] элемента массива A[4] НОМЕР (ИНДЕКС) элемента массива: 2 A[2] ЗНАЧЕНИЕ элемента массива: 15

 • Чтобы обратиться к элементу массива, надо указать имя массива и номер элемента • Чтобы обратиться к элементу массива, надо указать имя массива и номер элемента в массиве (индекс): a[0] – индекс задается как константа, a[i] – индекс задается как переменная, a[2*i] – индекс задается как выражение.

Операции над массивами ■ ■ Операции над массивами – это операции над их отдельными Операции над массивами ■ ■ Операции над массивами – это операции над их отдельными элементами: ❑ инициализация, ❑ ввод и вывод значений, ❑ перестановка значений, ❑ копирование. Для работы с массивами, как правило, используются циклы. 15

Типовые задачи обработки массивов ■ ■ ■ Анализ массива (всего или части) для нахождения Типовые задачи обработки массивов ■ ■ ■ Анализ массива (всего или части) для нахождения некоторой его характеристики. Поиск в массиве, т. е. определение элемента (первого, последнего, всех) с некоторым условием и нахождение его индекса. Построение массива по некоторому правилу, используя индексы, числа или массивы. Преобразование массива (изменение значения, перестановка элементов, добавление или удаление элементов и т. п. ). Сортировка массива по некоторому критерию. Вывод массива в специальном виде. 16

Инициализация элементов массива ■ ■ ■ Инициализация - присваивание каждому элемента массива значения, соответствующего Инициализация элементов массива ■ ■ ■ Инициализация - присваивание каждому элемента массива значения, соответствующего базовому типу. Возможна явная инициализация массива при его определении: Значения элементам присваиваются по порядку: ❑ int b[3]={3, 2, 1}; // b[0]=3, b[1]=2; b[2]=1; Если элементов в массиве больше, чем инициализаторов, элементы, для которых значения не указаны, обнуляются: ❑ int b[5]={3, 2, 1}; //массив целых значений, занимает 5*4=20 байтов //b[0]=3; b[1]=2; b[2]=1; b[3]=0; b[4]=0; Если элементов в массиве меньше, чем инициализаторов, то определение массива будет ошибочным: ❑ double B[3]={1, 2, 3, 4, 5}; //ошибка инициализации 17

 • Элементы массива можно задавать при его определении: int a[10]={1, 2, 3, 4, • Элементы массива можно задавать при его определении: int a[10]={1, 2, 3, 4, 55, 6, 7, 8, 9, 10}; int a[10]={1, 2, 3, 4, 5}; int a[]={1, 2, 3, 4, 5};

Инициализация элементов массива ■ При определении массива его размер может быть не указан (компилятор Инициализация элементов массива ■ При определении массива его размер может быть не указан (компилятор вычислит его по количеству инициализирующих значений). double x [ ] = {1. 5, 2. 8, 3. 4, 0. 5, 7. 3} ; //массив вещественных значений занимает 5*8=40 байтов ❑ char str [ ] = {‘a’, ‘b’, ‘+’}; //массив символов, занимает 3 байта ❑ 19

Размер массива ■ ■ Размер массива определяется из анализа условия задачи. Размерность и размер Размер массива ■ ■ Размер массива определяется из анализа условия задачи. Размерность и размер массива вместе с типом его элементов определяют общий объем памяти, необходимый для размещения массива, которое выполняется на этапе компиляции. С помощью операции sizeof (имя_массива) можно определить размер массива в байтах (т. е. размер участка памяти, выделенного для массива). Все элементы массива имеют одинаковый размер, поэтому количество элементов в массиве позволяет определить выражение: ❑ sizeof (имя_массива) / sizeof (имя_массива[0]). 20

Как обработать все элементы массива? ■ • • • Обработка в цикле: i = Как обработать все элементы массива? ■ • • • Обработка в цикле: i = 0; while ( i < N ) { // обработать A[i] i ++; } ИЛИ for( i = 0; i < N; i++ ) { // обработать A[i] } 21

Ввод элементов ■ ■ Если точное количество элементов в массиве неизвестно, то память можно Ввод элементов ■ ■ Если точное количество элементов в массиве неизвестно, то память можно выделить по максимуму (например, const int n = 100; ), а затем заполнять только часть ее. Несмотря на то, что значение константы n определяется с запасом, надежная программа должна обязательно содержать проверку на количество вводимых элементов. 22

Ввод массива. Стиль С ■ ■ Ввод массива реализуется вводом в цикле значений его Ввод массива. Стиль С ■ ■ Ввод массива реализуется вводом в цикле значений его элементов. Пример (размер массива задается константой). Ввод с клавиатуры: const int n=5; // Объявление int A[n]; for (int i=0; i

Ввод массива. Стиль С++ • • • int А[4]; for(int i=0; i<n; i++) { Ввод массива. Стиль С++ • • • int А[4]; for(int i=0; i> А[i]; //в стиле С++ } 24

Пример. Чему равен A[9]? • • void main() { const int N = 10; Пример. Чему равен A[9]? • • void main() { const int N = 10; int A[N]; int i; for ( i = 0; i < N; i++ ) A[i] = i*i; } 25

Вывод на экран в стиле С++ cout >> Вывод на экран в стиле С++ cout >> "Массив A: n"; ■ for ( i = 0; i < N; i++ ) ■ cout << A[i] << " "; ■ 26

Передача одномерного массива в функцию в качестве параметра ■ ■ Независимо от того, является Передача одномерного массива в функцию в качестве параметра ■ ■ Независимо от того, является ли массив для функции входным, выходным или одновременно входным и выходным (передается в функцию, преобразуется в ней и возвращается в вызывающую функцию), в функцию всегда передается адрес массива; поэтому изменение массива в вызываемой функции приводит к изменению массивааргумента в вызывающей функции; никакого ссылочного типа для возврата массива из функции не требуется; использование имени массива и указателя на массив в качестве аргумента функции эквивалентны (в функцию передается адрес); 28

Передача одномерного массива в функцию в качестве параметра ■ ■ В вызывающей функции массив Передача одномерного массива в функцию в качестве параметра ■ ■ В вызывающей функции массив определяется обычным образом, и при вызове функции в качестве аргумента задается имя массива (например, А – адрес начала массива) или &A[0] (адрес первого элемента); в заголовке функции указываются: ❑ тип элементов массива, его имя, ❑ размер массива (например, int x[5]; ) ❑ или пустые квадратные скобки (например, int x[]; ) ❑ или указатель на базовый тип (например, int *x); • в теле функции доступ к элементам массива осуществляется обычным способом: a[i] или *(a+i) или через указатель-переменную, проинициализированную именем массива. 29

Пример ввода с проверкой • • • • • void Vvod (int mas[], int Пример ввода с проверкой • • • • • void Vvod (int mas[], int kol_a); //прототипы функций ввода-вывода void Vyvod (int mas[], int kol_a); const int n = 1000; void main () { int a[n]; int kol_а; cout << "kol_a=? ? ? "; cin >> kol_а; if (kol_а > n) { //проверка cout << "size > n " << endl; } else { Vvod (a, kol_а); Vyvod (a, kol_а); 30 }

Пример ■ Написать программу нахождения суммы значений элементов массива. Для ввода, вывода значений элементов Пример ■ Написать программу нахождения суммы значений элементов массива. Для ввода, вывода значений элементов и для нахождения суммы использовать функции. 31

Программа. Сумма элементов массива • • • #include Программа. Сумма элементов массива • • • #include "iostream" using namespace std; const int nmax=10; //размер массива - глобальная константа void input(int [], int &); //прототип функции void print (int [], int); //прототип функции int sum(int [], int ); //прототип функции int main() { int a[nmax], n; input (a, n); //ввод массива print (a, n); //вывод массива cout << "S=" << sum(a, n)<< endl; } 32

Программа. Определение функций • • • • • void input (int a[], int &n) Программа. Определение функций • • • • • void input (int a[], int &n) { cout<<"n="; cin>>n; for(int i=0; i

Пример // Найти среднее арифметическое значений элементов // массива. double sr (int *a, int Пример // Найти среднее арифметическое значений элементов // массива. double sr (int *a, int n) { int s=0; for (int i=0; i

35 Поиск в массиве Найти в массиве элемент, равный X: i = 0; while 35 Поиск в массиве Найти в массиве элемент, равный X: i = 0; while ( A[i] != X ) i ++; cout << "A[" << i << "]=" << X; ? Что плохо? i = 0; while ( i < N && A[i] != X ) i ++; Что если такого нет? if ( i < N ) cout << "A[" << i << "]=" << X; else cout << "Не нашли!"; ?

36 Поиск в массиве Вариант с досрочным выходом: n. X = -1; for ( 36 Поиск в массиве Вариант с досрочным выходом: n. X = -1; for ( i = 0; i < N && n. X==-1; i++ ) if ( A[i] == X ) n. X = i; if ( n. X >= 0 ) cout << "A[" << n. X << "]=" << X; else cout << "Не нашли!";

Блок-схема Flag=0 i=0 Flag=0 И i<n – + Flag=a[i] сравнивается со свойством i++ Блок-схема Flag=0 i=0 Flag=0 И i

Пример ■ • • • Определить, имеется ли в массиве элемент, значение которого больше Пример ■ • • • Определить, имеется ли в массиве элемент, значение которого больше 1, но меньше 3? Программа: . . . Flag=0; i=0; while (Flag==0 && i1&&a[i]<3; i=i+1; } if (Flag) printf(“есть”); else printf(“нет”); . . . 38

39 Максимальный элемент M = A[0]; for ( i = 1; i < N; 39 Максимальный элемент M = A[0]; for ( i = 1; i < N; i++ ) if ( A[i]> M ) M = A[i]; cout << M; ? Как найти его номер? M = A[0]; n. Max = 0; n. Max for ( i = 1; i < N; i++ ) if ( A[i] > M ) { Что можно улучшить? M = A[i]; n. Max = i; } cout << "A[" << n. Max << "]=" << M; ?

40 Максимальный элемент и его номер ! По номеру элемента можно найти значение! n. 40 Максимальный элемент и его номер ! По номеру элемента можно найти значение! n. Max = 0; for ( i = 1; i < N; i++ ) if ( A[i] > A[n. Max] ) A[n. Max] n. Max = i; cout << "A[" << n. Max << "]=" << A[n. Max] ;

Поиск номера первого максимального/минимального элементов массива M = A[0]; n. M = 0; for Поиск номера первого максимального/минимального элементов массива M = A[0]; n. M = 0; for ( i = 1; i < N; i++ ) if ( A[i] M ) { M = A[i]; n. M = i; // номер первого максимального n. M = i; //Номер первого минимального } cout << "A[" << n. M << "]=" << M;

Поиск номера поcледнего максимального/минимального элементов массива M = A[0]; n. M = 0; for Поиск номера поcледнего максимального/минимального элементов массива M = A[0]; n. M = 0; for ( i = 1; i < N; i++ ) if ( A[i] M) { M = A[i]; n. M = i; // номер последнего максимального n. M = i; //Номер последнего минимального } cout << "A[" << n. M << "]=" << M;

43 Задачи «C» : Введите массив с клавиатуры и найдите (за один проход) количество 43 Задачи «C» : Введите массив с клавиатуры и найдите (за один проход) количество элементов, имеющих максимальное значение. Пример: Массив: 3 4 5 5 3 4 5 Максимальное значение 5 Количество элементов 3

#include <iostream> #include<cstdlib> using namespace std; void main() { int const N=10; int a[N]; #include #include using namespace std; void main() { int const N=10; int a[N]; int i, max, k=0; for(i=0; i>a[i]; } max=a[0]; k=1; for(i=1; imax) {max=a[i]; k=1; } cout<<"k="<

#include <iostream> #include<cstdlib> using namespace std; int kol_max(int *a, int n) { int max=a[0], #include #include using namespace std; int kol_max(int *a, int n) { int max=a[0], k=1, i; for(i=1; imax) {max=a[i]; k=1; } return k; } void main() { int const N=10; int a[N]; int i, max, k=0; for(i=0; i>a[i]; } cout<<"k="<

Пример ■ • • • ■ • Найти минимальный элемент массива #include <limits. h> Пример ■ • • • ■ • Найти минимальный элемент массива #include … int min(int *a, int n) { int min=a[0]; for(int i=1; i

Пример. Вариант 1 ■ • • Поиск номера минимального элемента в массиве int imin(int Пример. Вариант 1 ■ • • Поиск номера минимального элемента в массиве int imin(int *a, int n) { int min=a[0], i_min=0; for(int i=1; i

Пример. Вариант 2 ■ • • Поиск номера минимального элемента в массиве int imin_2(int Пример. Вариант 2 ■ • • Поиск номера минимального элемента в массиве int imin_2(int *a, int n) { int i_min=0; for(int i=1; i

Пример ■ • • • • Найти минимальный элемент в массиве и подсчитать их Пример ■ • • • • Найти минимальный элемент в массиве и подсчитать их количество. void kmin(int *a, int n, int &min, int &k) { min=a[0]; k=1; for(int i=1; i

Одномерные массивы_2 Лекция 10 Одномерные массивы_2 Лекция 10

Какую задачу решает эта функция? • • • • void km(int *a, int n, Какую задачу решает эта функция? • • • • void km(int *a, int n, int &m, int &k) { m=a[0]; k=1; for(int i=1; i

ОТВЕТ ■ Ищет минимальный элемент в массиве и подсчитывает количество элементов, значения которых совпадает ОТВЕТ ■ Ищет минимальный элемент в массиве и подсчитывает количество элементов, значения которых совпадает с минимальным.

Пример • • • • Найти второй минимальный элемент. int min_2(int *a, int n) Пример • • • • Найти второй минимальный элемент. int min_2(int *a, int n) { int min 1, min 2; min 1=min 2=a[0]; for(int i=1; i

57 Реверс массива 0 1 2 3 N-4 N-3 N-2 N-1 7 12 5 57 Реверс массива 0 1 2 3 N-4 N-3 N-2 N-1 7 12 5 8 18 34 40 23 0 1 2 3 N-4 N-3 N-2 N-1 23 40 34 18 8 5 12 5 «Простое» решение: остановиться на середине! for( i = 0; i < N/2 ; i++ ) N { // поменять местами A[i] и A[N-1 -i] } ? Что плохо?

58 Реверс массива for ( i = 0; i < (N/2); i++ ) { 58 Реверс массива for ( i = 0; i < (N/2); i++ ) { c = A[i]; A[i] = A[N-1 -i]; A[N-1 -i] = c; } ? *Как обойтись без переменной c?

59 Циклический сдвиг элементов 0 1 2 3 N-4 N-3 N-2 N-1 7 12 59 Циклический сдвиг элементов 0 1 2 3 N-4 N-3 N-2 N-1 7 12 5 8 18 34 40 23 0 1 2 3 N-4 N-3 N-2 N-1 12 5 8 15 34 40 23 7 «Простое» решение: ? Почему не до N-1? c = A[0]; for ( i = 0; i < N-1; i++ ) Что плохо? A[i] = A[i+1]; A[N-1] = c; ?

Пример ■ • • Напишите программу, чтобы решалась задача циклического сдвига элементов массива вправо. Пример ■ • • Напишите программу, чтобы решалась задача циклического сдвига элементов массива вправо. c = A[N-1]; for ( i = N-1; i >0; i-- ) A[i] = A[i-1]; A[0] = c; 60

Удаление элементов массива • Удалить элемент с номером К • Удалить все элементы с Удаление элементов массива • Удалить элемент с номером К • Удалить все элементы с заданными свойствами

Задачи удаления элементов одномерного массива • Удалить элемент с номером k из одномерного массива. Задачи удаления элементов одномерного массива • Удалить элемент с номером k из одномерного массива. Вариант 1: for (i=k+1; i

 • Удалить все элементы массива, обладающие заданным свойством. for (k=n-1; k>-1; k--) if • Удалить все элементы массива, обладающие заданным свойством. for (k=n-1; k>-1; k--) if (a[k] обладает свойством) {(1) или (2); } Внешний цикл от последнего элемента к нулевому. Сдвигаем только те элементы, которые проверили на свойство.

Задачи вставки элемента в одномерный массив • После элемента с номером k вставить заданную Задачи вставки элемента в одномерный массив • После элемента с номером k вставить заданную величину; например, 100: Вариант 1: for(i=n-1; i>k; i--) // все элементы, начиная с k+1 -го a[i+1]=a[i]; // сдвигаются на один вправо //i – номер элемента, который сдвигается вправо a[k+1]=B; // на k+1 -е место вставляется новый элемент n++; // размер массива увеличивается на единицу Вариант 2: В этой реализации параметр отвечает за место элемента, который сдвигается вправо: for(i=n; i>k+1; i--) a[i]=a[i-1]; // a[i] указывает, куда сдвигаем a[k+1]=B; n++;

 • Перед элементом с номером k вставить заданную величину. Вариант 1: for(i=n-1; i>=k; • Перед элементом с номером k вставить заданную величину. Вариант 1: for(i=n-1; i>=k; i--) // все элементы, начиная с k-го a[i+1]=a[i]; // сдвигаются на один вправо a[k]=B; // на k-е место вставляется новый элемент n++; // размер массива увеличивается на единицу Вариант 2: for(i=n; i>k; i--) a[i]=a[i-1]; a[k]=B; n++; // размер массива увеличивается на единицу Это можно сформулировать и так: вставить заданную величину после элемента с номером (k-1).

 • После элементов с заданными свойствами вставить указанную величину. Например, вставить число 100, • После элементов с заданными свойствами вставить указанную величину. Например, вставить число 100, после всех элементов, которые кратны 3. for (k=n-1; k>-1; k--) // просмотр начинается с // конца if (a[k]%3==0) {for (i=n-1; i>k; i--) // сдвиг на один элемент a[i+1]=a[i]; // вправо a[k+1]=100; n++; }

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

Создание динамических переменных указатель = new имя_типа [инициализатор]; где инициализатор – выражение в круглых Создание динамических переменных указатель = new имя_типа [инициализатор]; где инициализатор – выражение в круглых скобках. Пример int* x=new int(5); 5 int* x

Удаление динамических переменных delete указатель; Пример delete x; Удаление динамических переменных delete указатель; Пример delete x;

Динамические массивы • Операция new для создания одномерного массива имеет следующий формат: new тип_массива[количество_элементов] Динамические массивы • Операция new для создания одномерного массива имеет следующий формат: new тип_массива[количество_элементов] int* a = new int[100]; double* b = new double[10]; • Операция delete освобождает память, выделенную под массив delete[] a; delete[] b;

71 Сортировка_1 Лекция 11_1 71 Сортировка_1 Лекция 11_1

Какую задачу решает функция f 5? void f 5(int c[], int n) { int Какую задачу решает функция f 5? void f 5(int c[], int n) { int t, j, k; for (t=0, j=n-1; t

Реверс массива Реверс массива

76 Что такое сортировка? Сортировка – это расстановка элементов массива в заданном порядке. …по 76 Что такое сортировка? Сортировка – это расстановка элементов массива в заданном порядке. …по возрастанию, убыванию, последней цифре, сумме делителей, по алфавиту, … Алгоритмы: • простые и понятные, но неэффективные для больших массивов время работы ▫ метод пузырька ▫ метод выбора • сложные, но эффективные ▫ «быстрая сортировка» (Quick. Sort) N ▫ сортировка «кучей» (Heap. Sort) ▫ сортировка слиянием (Merge. Sort) ▫ пирамидальная сортировка

Идея сортировок Массив разбивают на две части: отсортированную и неотсортированную. Количество элементов в отсортированной Идея сортировок Массив разбивают на две части: отсортированную и неотсортированную. Количество элементов в отсортированной части растет, а в неотсортированной – уменьшается. Неотсортированная часть Отсортированная часть

При формулировании задачи сортировки одномерного массива может использоваться следующая терминология: 1. упорядочить массив по При формулировании задачи сортировки одномерного массива может использоваться следующая терминология: 1. упорядочить массив по возрастанию: a 1a 2>…>an; 3. отсортировать массив по неубыванию (такая формулировка возможна, если среди элементов есть одинаковые): a 1a 2>a 3=a 4=a 5>a 6=a 8>…>an

79 Метод пузырька (сортировка обменами) Идея: пузырек воздуха в стакане воды поднимается со дна 79 Метод пузырька (сортировка обменами) Идея: пузырек воздуха в стакане воды поднимается со дна вверх. Для массивов – самый маленький ( «легкий» элемент перемещается вверх ( «всплывает» ). 1 -й проход: 4 4 1 5 5 5 1 4 2 2 1 5 5 1 1 2 2 2 3 3 3 • сравниваем два соседних элемента; если они стоят «неправильно» , меняем их местами • за 1 проход по массиву один элемент (самый маленький) становится на свое место

80 Метод пузырька 2 -й проход: 3 -й проход: 4 -й проход: 1 1 80 Метод пузырька 2 -й проход: 3 -й проход: 4 -й проход: 1 1 1 1 1 4 4 4 2 2 2 5 5 2 4 4 4 3 3 3 2 2 5 5 5 3 4 4 4 3 3 3 5 5 ! Для сортировки массива из N элементов нужен N-1 проход (достаточно поставить на свои места N-1 элементов).

81 Метод пузырька 1 -й проход: сделать для j от N-2 до 0 шаг 81 Метод пузырька 1 -й проход: сделать для j от N-2 до 0 шаг -1 если A[j+1]< A[j] то // поменять местами A[j] и A[j+1] единственное отличие! 2 -й проход: 1 сделать для j от N-2 до 1 шаг -1 если A[j+1]< A[j] то // поменять местами A[j] и A[j+1]

82 Метод пузырька for ( i = 0; i < N-1; i++ ) for 82 Метод пузырька for ( i = 0; i < N-1; i++ ) for ( j = N-2; j >= i ; j-- ) if ( A[j] > A[j+1] ) { // поменять местами A[j] и A[j+1] R=A[j]; A[j]=A[j+1]; A[j+1]=R; } ? Как написать метод «камня» ?

Задание ■ • • Напишите программу, в которой сортировка выполняется «методом камня» – самый Задание ■ • • Напишите программу, в которой сортировка выполняется «методом камня» – самый «тяжёлый» элемент опускается в конец массива. for ( i = 0; i < N-1; i++ ) for ( j =0; j <= N-1 -i ; j++ ) if ( A[j] > A[j+1] ) { // поменять местами A[j] и A[j+1] R=A[j]; A[j]=A[j+1]; A[j+1]=R; } 83

Программа: int a[100], b[100]; int n, i, k, R; . . . for (i=n; Программа: int a[100], b[100]; int n, i, k, R; . . . for (i=n; i>1; i--) for (k=0; ka[k+1]) {R=a[k]; a[k]=a[k+1]; a[k+1]=R; } if (b[k]

Задание ■ Упорядочить массив из 6 элементов: 12, 3, 5, 7, 9, 10 по Задание ■ Упорядочить массив из 6 элементов: 12, 3, 5, 7, 9, 10 по неубыванию методом «пузырька» . 86

Модифицированный пузырек • • • • void modif_bubble(int *m, int n) // Модифицированный пузырек Модифицированный пузырек • • • • void modif_bubble(int *m, int n) // Модифицированный пузырек { int i=n, t; // Длина неотсортированной части массива int f; do { f=0; //Предположим, что массив является отсортированным for (int k=0; km[k+1]) { t=m[k]; m[k]=m[k+1]; m[k+1]=t; // Обмен f=1; // Массив был неотсортированным } i--; } while (f && i>1); } 87

Шейкер-сортировка Это модификация метода «пузырька» , которая учитывает два дополнительных требования: 1) устранение «лишних» Шейкер-сортировка Это модификация метода «пузырька» , которая учитывает два дополнительных требования: 1) устранение «лишних» просмотров массива, т. е. если массив уже отсортирован за первые проходы, последующие проходы не делаем. Пример: 12, 3, 5, 7, 9, 10. 2) смена направлений прохода массива: сначала проходим от начала к концу, а затем – от конца к началу, потом снова от начала к концу и т. д. Это позволяет уменьшить число проходов по массиву. Пример: 5, 7, 9, 10, 12, 3.

Шейкер-сортировка ■ ■ ■ Алгоритм уменьшает количество перемещений, действуя следующим образом: ❑ за один Шейкер-сортировка ■ ■ ■ Алгоритм уменьшает количество перемещений, действуя следующим образом: ❑ за один проход из всех элементов выбирается минимальный и максимальный, минимальный элемент помещается в начало массива, а максимальный, соответственно, в конец. Далее алгоритм выполняется для остальных данных. Таким образом, за каждый проход два элемента помещаются на свои места, а значит, понадобится N/2 проходов, где N – количество элементов. 90

Шейкер-сортировка void Shaker_Sort(int n, int *a) { int j, k, l, r; int x; Шейкер-сортировка void Shaker_Sort(int n, int *a) { int j, k, l, r; int x; l=1; //левая граница r=n-1; //правая граница do { // Обратный проход for( j=r; j>=l; j--) if (a[j-1]>a[j]) { x=a[j-1]; a[j-1]=a[j]; a[j]=x; k=j; /* фиксирование места последнего обмена */ } l=k+1; // левая граница // Прямой проход for(j=l; j>=r; j++) if (a[j-1]>a[j]) { x=a[j-1]; a[j-1]=a[j]; a[j]=x; k=j; /* фиксирование места последнего обмена */ } r=k-1; // правая граница } while (l<=r); /* До тех пор пока левая граница небольше правой*/ }

Метод простых вставок Идея метода: левая часть массива является отсортированной, правая часть – неотсортированной. Метод простых вставок Идея метода: левая часть массива является отсортированной, правая часть – неотсортированной. Для первого элемента неотсортированной части массива ищется место в отсортированной, и новый элемент вставляется в нужное место отсортированной части массива:

Пример. Сортировка вставками 93 Пример. Сортировка вставками 93

Программа сортировки вставками. Вариант 1 • • • void sort_insert (int *m, int n) Программа сортировки вставками. Вариант 1 • • • void sort_insert (int *m, int n) { int j, r; for (int i=1; i=0 && m[j]>r) // Ищем новое место вставки, { m[j+1]=m[j]; j--; } // сдвигая на 1 элемент вправо m[j+1]=r; // На освободившееся место вставляется элемент } } 94

Программа сортировки вставками. Вариант 2 • • void sort_insert 1 (int *m, int n) Программа сортировки вставками. Вариант 2 • • void sort_insert 1 (int *m, int n) { int j, r; for (int i=1; i=0 && m[j]>r); m[j+1]=m[j], j--); } 95

Метод вставками с барьером • • • void sort_vs(int *a, int n) {int i, Метод вставками с барьером • • • void sort_vs(int *a, int n) {int i, j; for (i=2; i

Сортировка методом простого выбора (извлечения) ■ ■ Обычно применяется для массивов, не содержащих повторяющихся Сортировка методом простого выбора (извлечения) ■ ■ Обычно применяется для массивов, не содержащих повторяющихся элементов. Алгоритм: ❑ 1) выбрать максимальный элемент массива; ❑ 2) поменять его местами с последним элементом (после этого самый большой элемент будет стоять на своём месте); ❑ 3) повторить пункты 1 -2 с оставшимися n– 1 элементами. 97

Пример ■ Дан массив из пяти элементов: 5, 2, 7, 4, 6. Отсортировать по Пример ■ Дан массив из пяти элементов: 5, 2, 7, 4, 6. Отсортировать по возрастанию методом простого выбора. Элементы массива Примечание Исходный массив 5 2 7 4 6 max=7 Шаг 1 5 2 6 4 7 7↔ 6; max=6 Шаг 2 5 2 4 6 7 4↔ 6; max=5 Шаг 3 4 2 5 6 7 4↔ 5; max=4 Шаг 4 2 4 5 6 7 4↔ 2 98

Сортировка методом простого выбора ■ • • • • Отсортированная часть формируется в конце Сортировка методом простого выбора ■ • • • • Отсортированная часть формируется в конце массива. void sort_vybor (int *a, int n) // Вариант 1 { int k, m; for (int i=n-1; i>=0; i--) { k=i; // Запоминаем номер и m=a[i]; // значение текущего элемента for (int j=0; jm) {k=j; m=a[k]; } if (k!=i) { // Меняем местами с последним a[k]=a[i]; a[i]=m; } } } 99

Сортировка методом простого выбора • • • void sort_vybor 1 (int *a, int n) Сортировка методом простого выбора • • • void sort_vybor 1 (int *a, int n) // Сортировка простым выбором. Вариант 2 { int k, m, j; for (int i=n-1; i>=0; a[k]=a[i], a[i]=m, i--) // Поиск максимального элемента for (k=i, m=a[i], j=0; jm) {k=j; m=a[k]; } } 100

Методы быстрой сортировки ■ ■ ■ Сортировка слияниями Быстрая сортировка (сортировка Хоара, 1962) Пирамидальная Методы быстрой сортировки ■ ■ ■ Сортировка слияниями Быстрая сортировка (сортировка Хоара, 1962) Пирамидальная сортировка 101

Сортировка слияниями ■ ■ Метод слияний – один из первых в теории алгоритмов сортировки. Сортировка слияниями ■ ■ Метод слияний – один из первых в теории алгоритмов сортировки. Он предложен Дж. фон Нейманом в 1945 году. Задача. ❑ ❑ ❑ Объединить ( «слить» ) упорядоченные фрагменты массива A: A[k], . . . A[m] и A[m+1], . . . , A[q] в один A[k], . . . , A[q], естественно, тоже упорядоченный (k≤m≤q). Основная идея решения состоит в сравнении очередных элементов каждого фрагмента, выяснении, какой из элементов меньше, переносе его во вспомогательный массив D (для простоты) и продвижении по тому фрагменту массива, из которого взят элемент. При этом следует не забыть записать в D оставшуюся часть того фрагмента, который не успел себя «исчерпать» . 102

Пример. Сортировка слияниями ■ Пусть первый фрагмент состоит из 4 -х элементов: 2 6 Пример. Сортировка слияниями ■ Пусть первый фрагмент состоит из 4 -х элементов: 2 6 8 11, а второй – из 8 -и: 1 3 5 7 14 17. 2 6 8 11 5 6 Шаг 2 2<3 1 2 Шаг 1 1<2 1 3 Шаг 3 3<6 3 7 8 14 11 14 17 17 Шаг 3 5<6 5 7 103

Программа. Сортировка слияниями • • • void Sl(int m[], int k, int q) { Программа. Сортировка слияниями • • • void Sl(int m[], int k, int q) { // k – нижняя граница упорядоченного фрагмента // q – верхняя граница фрагмента int i, j, t, mid, d[20]; i=k; mid=k+(q-k)/2; j=mid+1; t=1; while (i<=mid && j<=q) { if (m[i]<=m[j]) {d[t]=m[i]; i++; } else { d[t]=m[j]; j++; } t++; } // Один из фрагментов обработан полностью, осталось перенести в D //остаток другого фрагмента • • while (i<=mid) { d[t]=m[i]; i++; t++; } while (j<=q) { d[t]=m[j]; j++; t++; } for (i=1; i<=t-1; i++) m[k+i-1]=d[i]; } 104

Программа. Сортировка слияниями • • • • // Рекурсивная реализация сортировки слиянием void Sort_Sl(int Программа. Сортировка слияниями • • • • // Рекурсивная реализация сортировки слиянием void Sort_Sl(int *m, int i, int j) { int t; if (i

Алгоритм слияния упорядоченных массивов 4 14 27 51 1 3 8 24 31 42 Алгоритм слияния упорядоченных массивов 4 14 27 51 1 3 8 24 31 42 59 void merge(int a[], int b[], int na, int nb, int *c, int &nc) { int ia, ib, ic; ia = 0; ib = 0; ic = 0; while (ia <= na && ib <= nb) do { if (a[ia]