Лабораторные работы
.pdfМетод «пузырька». Данный метод относится к сортировкам обменом. Метод «пузырька» получил своё название оттого, что продвижение максимальных элементов массива к его вершине происходит постепенно, подобно всплытию пузырька на поверхность воды. Этот метод требует нескольких проходов массива. На каждом проходе сравнивается пара соседних друг с другом элементов.
Если пара расположена в порядке возрастания, переставляем эти элементы местами. В противном случае элементы остаются на исходных позициях. Процедура должна быть повторена n-1 раз для гарантированного достижения результата. Пример поэтапной работы алгоритма показан на рис. 3. Изображенные на каждом проходе перестановки должны выполняться последовательно слева направо.
проход 1
0 |
5 |
3 |
7 |
9 |
проход 2 |
|
|
|
|
|
|
5 |
3 |
7 |
9 |
0 |
проход 3 |
|
|
|
|
|
|
|
|
|
|
|
|
5 |
7 |
9 |
3 |
0 |
проход 4 |
|
|
|
|
|
|
|
|
|
|
|
|
7 |
9 |
5 |
3 |
0 |
|
|
|
|
|
|
итог |
9 |
7 |
5 |
3 |
0 |
Рис. 3. Алгоритм сортировки «пузырьком»
Листинг программы primer 3_11.c демонстрирует реализацию этого метода.
41
//primer 3_11.c
#include <stdio.h> #include <conio.h> #define n 5
int main ()
{
int i,j, temp=0;
int a[n]={0,5,3,7,9}; for (i=0; i<n-1; i++)
{
for (j=0; j<n-1; j++) if (a[j]<a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
printf ("\n"); for (i=0; i<n; i++)
printf ("%d ", a[i]); getch ();
return 0;
}
Сортировка выбором. Алгоритм состоит в том, что выбирается наименьший элемент массива и меняется местами с первым элементом, затем рассматриваются элементы, начиная со второго, и наименьший из них меняется местами со вторым элементом и так далее n-1 раз (при последнем проходе цикла при необходимости меняются местами предпоследний и последний элементы массива). Последовательность шагов при n = 5 изображена на рис. 4 ниже.
Рис. 4. Алгоритм сортировки выбором
42
Вне зависимости от номера текущего шага i последовательность a[0]...a[i] (выделена курсивом) является упорядоченной. Таким образом, на (n-1)-м шаге вся последовательность, кроме a[n], оказывается отсортированной, а a[n] стоит на последнем месте по праву: все меньшие элементы уже ушли влево.
Листинг программы primer 3_12.c демонстрирует реализацию этого метода:
//primer 3_12.c #include <stdio.h> #include <conio.h>
#define n 7
int main ()
{
int a[n]={1,3,4,5,6,7,1}; int i, j, index, temp; for (i=0; i<n-1; i++)
{
index=i;
for (j=i+1; j<n; j++) if (a[j]<a[i])
{
index=j;
temp=a[i];
a[i]=a[index];
a[index]=temp;}
}
for (i=0; i<n; i++) printf("\n%d ",a[i]);
getch(); return (0);
}
Поиск минимального (максимального) элемента массива.
Алгоритм поиска будет выглядеть следующим образом:
1.Будем считать минимальным (максимальным) элементом первый элемент массива.
2.Последовательно сравнить минимальный (максимальный) элемент с элементами массива, начиная от второго элемента. Если нашелся элемент меньший (больший) минимального (максимального), поместить его на место минимального (максимального) элемента. Ниже приведен соответствующий код программы.
43
//primer 3_13.c #include <stdio.h>
#include <conio.h> #define n 5
int main ()
{
int min, i;
int a[n]={4,2,9,1,3}; min=a[0];
for (i=1; i<n;i++ )
if (a[i]<min) min=a[i]; printf ("\n min=%d", min); getch ();
return 0;
}
Объединение двух одномерных массивов. Типовой алгоритм объ-
единения двух одномерных массивов заключается в применении дополнительного массива, что и продемонстрировано в программе primer 3_14.c. Новая деталь в этой программе – это использование числа вместо имени переменной при задании размера массива.
//primer 3_14.c #include <stdio.h>
#include <conio.h>
int main (){ int i;
int mas[10];
int a[5]={4,2,9,1,3}; int b[5]={5,7,8,11,12}; for (i=0; i<5; i++)
{
mas[i]=a[i]; mas [5+i]=b[i];
}
for (i=0; i<10; i++) printf ("%d ", mas[i]);
getch (); return 0;
}
44
Циклический сдвиг элементов массива. При циклическом сдвиге вправо выталкиваемые элементы с конца массива заполняют освобождающиеся места в начале массива. Например, при сдвиге вправо на 3 разряда массива А (1, 2, 3, 4, 5, 6, 7) получаем массив А (5, 6, 7, 1, 2, 3, 4). Ниже представлена соответствующая программа.
//primer 3_15.c
#include <stdio.h>
#include <conio.h> #include <locale.h > #define n 7
int main ()
{
setlocale(LC_CTYPE, "russian"); int m, i, j;
int a[n]={1, 2, 3, 4, 5, 6, 7}; printf ("введите m\n");
scanf ("%d",&m); m= m % n;
for (i=0; i<m; i++)
{
int temp=a[n-1];
for (j=0; j<n-1; j++)
{
a[n-j-1]=a[n-j-2];
}
a[0]=temp;
}
for (i=0; i<n; i++) printf ("%d ",a[i]);
getch (); return 0;
}
Типовые алгоритмы обработки одномерных массивов применяются для решения самых разнообразных задач. Продемонстрируем применение типовых алгоритмов для решения задачи «Преобразование последовательности»: задана последовательность, содержащая n
45
целых чисел (n >= 3). Необходимо найти число, которое встречается в этой последовательности наибольшее количество раз, а если таких чисел несколько, то найти минимальное из них и после этого переместить все такие числа в конец заданной последовательности. Порядок расположения остальных чисел должен остаться без изменения.
Например, последовательность 1, 2, 3, 2, 3, 1, 2 после преобразования должна превратиться в последовательность 1, 3, 3, 1, 2, 2, 2.
Требуется написать программу, которая решает названную задачу. Выполним структурную декомпозицию программы. Анализ условия задачи показывает, что ее решение можно разбить на следу-
ющие подзадачи:
1.Основная программа: ввод - вывод элементов массива.
2.Нахождение в одномерном массиве последовательности наибольшей длины.
3.Сдвиг элементов одномерного массива.
Подзадача «Нахождение в одномерном массиве последователь-
ности наибольшей длины» разбивается на две подзадачи: сортировка и подсчет количества вхождений.
Подзадача «Сдвиг элементов массива» является типовой и не требует разбивки на подзадачи. Следовательно, на первом шаге декомпозиции с использованием метода пошаговой детализации полу-
чаем (рис. 5).
ОСНОВНАЯ
ПРОГРАММА
НАХОЖДЕНИЕ |
|
СДВИГ |
|
ПОСЛЕДОВАТЕЛЬНОСТИ |
|
ЭЛЕМЕНТОВ |
|
ЧИСЕЛ НАИБОЛЬШЕЙ |
|
||
|
МАССИВА |
||
ДЛИНЫ |
|
||
|
|
||
|
|
|
|
|
|
|
|
СОРТИРОВКА
ПОДСЧЕТ КОЛИЧЕСТВА ВХОЖДЕНИЙ
Рис. 5. Структурная декомпозиция программы
46
Первая подзадача. Так как размер массива задается с клавиатуры и значения элементов массива не заданы, выбираем способ заполнения массива – ввод с клавиатуры.
Вторая подзадача «Нахождение последовательности чисел наибольшей длины» разбивается на две типовые подзадачи:
1)сортировка одномерного массива;
2)нахождение последовательности чисел наибольшей длины. Первая подзадача. Используем любую известную сортировку,
например сортировку пузырьком.
Вторая подзадача. Поиск числа, входящего в последовательность наибольшее количество раз. Идея решения: перебираем элементы массива, сравнивая два соседних элемента. Если они равны,
впеременной k накапливаем длину и сохраняем в переменной max. Как только числа стали неравны, содержимое переменной k = 1. Так как массив отсортирован по возрастанию, если найдется большее по значению число с таким же количеством вхождений, оно не заменит минимальное.
Третья подзадача. По окончании подсчета числа вхождений
впеременной temp останется минимальное из чисел, входящих в последовательность наибольшее количество раз. Для сохранения порядка следования элементов, не равных temp, можно использовать другой массив размера исходного массива. Используем для этой цели массив а. Идея решения: просматривать элементы массива b, если элемент не равен temp, записываем его в массив a и подсчитываем количество этих элементов для того, чтобы с индекса k+1 поставить элемент, хранящийся в temp. Блок-схема алгоритма программы представлена на рис. 6.
47
|
Начало |
|
Ввод n |
|
нет |
да |
n<3 |
|
|
|
i=0; i<n; i++ |
Ввод a[i]
да
a[i]>32767 || a[i] < -32768
Вывод «Error”
нет
i=0; i<n; i++
b[i]=a[i]
C
A
Основная программа
Рис. 6. Алгоритм программы примера (см. также с. 49, 50)
48
C
да
temp=a[j]
a[j]=a[j+1]
a[j+1]=temp
да
k=k+1
да
max=k;
temp=a[i]
a[j]=b[i]
j=j+1 k=j-1
A
|
Нахождение последова- |
|
i=0; i<n-1; i++ |
тельности наибольшей |
|
длины |
||
|
||
j=0; j<=n-i; j++ |
|
a[j]>a[j+1]
нет
Поиск числа max=0; k=1; min=a[0] вхождений
i=0; i<n-1; i++
нет
a[i]=a[i+1]
k=1
max<k
нет
|
|
Сдвиг эле- |
|
J=0 |
|||
|
ментов |
||
|
|
|
|
|
|
|
i=0; i<n; i++
temp<>b[i]
C
В
Рис. 6. Продолжение
49
C |
В |
|
i=k+1; i<n; i++ |
|
a[i]=temp |
Основная
программа
i=0; i<n; i++
Вывод a[i]
конец
Рис. 6. Окончание
Полный текст программы приведен ниже:
//primer 3_16.c
#include <stdio.h>
#include <conio.h>
#define m 100 //резервируем память под 100 элементов массива
int main ()
{
int a[m],b[m];
int n, i, j, temp, max, k, min;
do {
printf ("input n\n"); scanf ("%d", &n);
}
while (n<3);
printf ("\n input massiv\n"); for (i=0; i<n; i++)
{
scanf("%d", &a[i]);
if (a[i]>32767 || a[i]<-32768) printf ("Input Error\n"); break;
}
for (i=0; i<n; i++) printf("%d ", a[i]);
50