Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ИС / Лабораторные работы / Лабораторная работа#6

.pdf
Скачиваний:
70
Добавлен:
22.03.2015
Размер:
360.09 Кб
Скачать

Лабораторная работа № 6

ПРОГРАММИРОВАНИЕ АЛГОРИТМОВ ОБРАБОТКИ ОДНОМЕРНЫХ МАССИВОВ

Цель занятия

1.Приобретение навыков формирования и преобразования одномерных массивов данных.

2.Знакомство с типовыми алгоритмами обработки одномерных массивов.

Постановка задачи

1.Для заданного варианта разработать алгоритм решения задачи на ЭВМ.

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

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

Содержание отчета

1.Постановка задачи для конкретного варианта.

2.Блок-схема алгоритма.

3.Текст программы и результаты ее выполнения.

Методические указания

Массивы

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

На любой элемент массива можно сослаться, указывая имя массива и номер позиции элемента, заключенный в квадратные скобки ([ ]). Первый элемент каждого массива – это нулевой элемент. Таким образом, первый элемент массива c, указывают как c[0], второй элемент – как c[1], седьмой – как с[6] и вообще i-ый элемент массива c указывают как c[i-1]. Имена массивов должны удовлетворять тем же требованиям, которые предъявляются к другим именам переменных.

Номер позиции, указанный внутри квадратных скобок, называется индексом. Индекс должен быть целым числом или целым выражением. Если программа использует выражение в качестве индекса, то выражение вычисляется с целью определения индекса.

Важно отметить различие между «седьмым элементом массива» и «элементом массива семь». Поскольку индексы массива начинаются с 0, «седьмой элемент массива» имеет индекс шесть, тогда как «элемент массива семь» имеет индекс 7 и на самом деле является восьмым элементом массива. Это – источник ошибок типа завышения (или занижения) на единицу.

Квадратные скобки, внутри которых записывается индекс массива, на самом деле рассматриваются в C++ как операция индексации. Квадратные скобки имеют тот же уровень старшинства, что и круглые скобки.

Объявление массивов

Массивы занимают область в памяти. Программист указывает тип каждого элемента, количество элементов, требуемое каждым массивом, и компилятор может зарезервировать соответствующий объем памяти. Чтобы указать компилятору зарезервировать память для 12 элементов массива целых чисел с, используется объявление

int c [12];

Память может быть зарезервирована для нескольких массивов с помощью одного объявления. Следующее объявление резервирует память для 100 элементов массива целых чисел b и 27 элементов массива целых чисел х.

int b[100], x[27];

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

Ввод значений массива

Элементам массива можно присваивать начальные значения (инициализировать их) в объявлении массива с помощью следующего за объявлением списка (заключенного в фигурные скобки) одинаковых по смыслу и разделенных запятыми начальных значений.

int a[5]={1, 5, 65, 12, 4};

Если начальных значений меньше, чем элементов в массиве, оставшиеся элементы автоматически получают нулевые начальные значения. Например, элементам массива n можно присвоить нулевые начальные значения с помощью объявления

int n[10] = {0};

которое явно присваивает нулевое начальное значение первому элементу и неявно присваивает нулевые начальные значения оставшимся девяти элементам, потому что здесь начальных значений меньше, чем элементов массива. Напомним, что автоматически массивы не получают нулевые начальные значения неявно. Программист должен присвоить нулевое начальное значение, по крайней мере, первому элементу для того, чтобы автоматически были обнулены оставшиеся элементы.

Пример: ввод значений элементов массива с клавиатуры.

#include <iostream.h> main ()

{

int mas[10]; int i; for (i=0; i<10; i++) {

cout << "Ввести" << i+1 <<"элемент" << endl; cin >> mas[i];

}

for (i=0; i<10; i++) {

cout << " mas["<<i<<"]="<< mas[i];

}

cout << endl; system("PAUSE"); return 0;

}

Присвоение элементам массива случайных значений.

#include <iostream.h> #include <stdlib.h> #include <time.h> main ()

{

int mas[10]; int i; srand(time(NULL)); for (i=0; i<10; i++) { mas[i]=rand();

}

for (i=0; i<10; i++) {

cout << " mas["<<i<<"]="<< mas[i];

}

cout << endl; system("PAUSE"); return 0;

}

Функция rand( ) на самом деле генерирует псевдослучайные числа. Повторный вызов rand производит последовательность чисел, которые кажутся случайными.

Это называется рандомизацией и реализуется в законченном виде с помощью стандартной

библиотечной функции srand. Функция srand получает целый аргумент unsigned и при каждом выполнении программы задает начальное число, которое функция rand использует для генерации последовательности квазислучайных чисел.

Функция srand получает значение unsigned int в качестве аргумента. Прототип функции srand находится в заголовочном файле <stdlib.h>.

Прогоните программу несколько раз и понаблюдайте результаты. Заметьте, что при прогоне программы с разными начальными значениями каждый раз получаются разные последовательности случайных чисел.

Если мы хотим рандомизировать не 0432водя каждый раз начальное число, можно использовать оператор, подобный следующему

srand(time(NULL));

При этом для автоматического получения начального числа компьютер считывает показания своих часов. Функция time (с аргументом NULL, как записано в указанном выше операторе) возвращает текущее «календарное время» в секундах. Это значение преобразуется в беззнаковое целое число и используется как начальное значение в генераторе случайных чисел. Прототип функции для time находится в <time.h>.

Сортировка массивов

Сортировка данных (т.е. размещение данных в определенном порядке, таком как возрастание или уменьшение) является одним из наиболее важных применений компьютеров.

Программа сортирует значения массива mas из 10 элементов в возрастающем порядке. Используемая при этом техника получила название пузырьковая сортировка или сортировка погружением, потому что наименьшее значение постепенно «всплывает», продвигаясь к вершине (началу) массива, подобно пузырьку воздуха в воде, тогда как наибольшее значение погружается на дно (конец) массива. Этот прием требует нескольких проходов по массиву. При каждом проходе сравнивается пара следующих друг за другом элементов. Если пара расположена в возрастающем порядке или элементы одинаковы, то мы оставляем значения как есть. Если же пара расположена в убывающем порядке, значения меняются местам в массиве.

#include <iostream.h> #include <stdlib.h> #include <time.h> main ()

{

int mas[10]; int i,j; srand(time(NULL)); for (i=0; i<10; i++) { mas[i]=rand();

}

for (i=0;i<9;i++) for (j=0;j<9;j++)

{

if (mas[j]>mas[j+1]) {

int hold =mas[j]; mas[j]=mas[j+1]; mas[j+1]= hold;

}

}

for (i=0; i<10; i++) {

cout << " mas["<<i<<"]="<< mas[i];

}

cout << endl; system("PAUSE"); return 0;

}

Сначала программа сравнивает mas[0] и mas[1], затем mas[1] и mas[2], потом mas[2] и mas[3] и т.д. до

тех пор, пока проход не закончится сравнением mas[8] и mas[9]. Хотя элементов 10, производится только девять сравнений. При выбранном способе последовательных сравнений большое значение может перемещаться в массиве вниз на много позиций за один проход, но малое значение может быть передвинуто вверх только на одну позицию. При первом проходе наибольшее значение гарантированно опустится на место нижнего элемента массива mas[9]. При втором проходе второе наибольшее значение гарантированно опустится на место mas[8]. При девятом проходе девятое наибольшее значение опустится на место mas[1]. Это оставляет наименьшему значению место mas[0], так что для сортировки массива из 10 элементов нужно только девять проходов.

Сортировка выполняется с помощью вложенного цикла for. Если необходима перестановка, она выполняется тремя присваиваниями

hold =mas[j]; mas[j]=mas[j+1]; mas[j+1]= hold;

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

Однако пузырьковая сортировка выполняется медленно. Это становится очевидным при сортировке больших массивов. Существуют более эффективные варианты пузырьковой сортировки.

#include <iostream.h> #include <stdlib.h> #include <time.h> main ()

{

int mas[10]; int i,j,counter=0; srand(time(NULL));

for (i=0; i<10; i++) mas[i]=rand(); for (i=0;i<9;i++){

for (j=0;j<9;j++)

{

if (mas[j+1]<mas[j]) {

int hold=mas[j]; mas[j]=mas[j+1]; mas[j+1]=hold; counter++;

}

}

if (counter==0) break;

}

for (i=0; i<10; i++) {

cout << " mas["<<i<<"]="<< mas[i];

}

cout << endl; system("PAUSE"); return 0;

}

Отличие данной программы состоит в том, что вводится дополнительный счетчик counter, считающий количество перестановок при каждом проходе. Если на каком-либо проходе перестановок не было, значит, массив отсортирован и происходит принудительный выход из цикла сортировки.

Поиск в массивах: линейный поиск и двоичный поиск

Часто программисту приходится работать с большими объемами данных, хранящимися в виде массивов. Может оказаться необходимым определить, содержит ли массив значение, которое соответствует определенному ключевому значению. Процесс нахождения какого-то элемента массива называют поиском. В этом разделе мы обсудим два способа поиска – простой линейный поиск и более эффективный двоичный поиск – дихотомию.

Метод линейного поиска основан на последовательном сравнении каждого элемента массива с

ключом поиска.

#include <iostream.h> main ()

{

int size;

cout << "Input size" << endl; cin >> size;

float mas[size]; int i; float max=0; for (i=0; i<size; i++) {

cout << "mas["<<i<<"]="; cin >> mas[i];

}

for (i=0;i<size ;i++)

if (mas[i]>max) max=mas[i];

cout << " maximum="<< max << endl; system("PAUSE");

return 0;

}

Метод линейного поиска хорошо работает для небольших или для несортированных массивов. Однако, для больших массивов линейный поиск неэффективен. Если массив отсортирован, можно использовать высокоэффективный метод двоичного поиска.

#include <iostream.h> main ()

{

int size;

cout << "Input size" << endl; cin >> size;

int key; int low=0, high=size, number; int middle; cout << "Input search key" << endl;

cin >> key;

int mas[size]; int i,j; for (i=0; i<size; i++) {

cout << "mas["<<i<<"]="; cin >> mas[i];

}

for (i=0;i<size-1; i++) for (j=0;j<size-1; j++)

{

if (mas[j+1]<mas[j]) {

int hold=mas[j]; mas[j]=mas[j+1]; mas[j+1]=hold;

}

}

for (i=0; i<size; i++)

cout << " mas["<<i<<"]="<<mas[i]; while (low<=high) {

middle=(high+low)/2; if (mas[middle]==key)

{number=middle; break;}

else if (key<mas[middle]) high=middle-1; else low=middle+1;

}

cout << "Number of key = " << number << endl; system("PAUSE");

return 0;

}

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

Вычисление среднего значения, медианы и моды с использованием массивов.

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

Среднее – это среднее арифметическое значений массива. Программа вычисляет среднее путем суммирования элементов массива и деления результата на количество элементов.

#include <iostream.h> main ( )

{

int size;

cout << "Input size" << endl; cin >> size;

int mas[size]; int i,sum=0, mean=0; for (i=0; i<size; i++) {

cout << "mas["<<i<<"]="; cin >> mas[i];

}

for (i=0;i<size;i++) sum=sum+mas[i];

mean=sum/size;

cout << "Mean="<<mean << endl; system("PAUSE")+;

return 0;

}

Медиана – это «середина». Для определения медианы, необходимо отсортировать массив значений в порядке их возрастания, и выбирать средний элемент отсортированного массива. Заметим, что если массив содержит четное число элементов, медиана вычисляется как среднее значение двух элементов в середине массива.

#include <iostream.h> main ( )

{

int size;

cout << "Input size" << endl; cin >> size;

float mas[size]; int i,j, mean=0; float median=0; for (i=0; i<size; i++) {

cout << "mas["<<i<<"]="; cin >> mas[i];

}

for (i=0; i<size-1; i++) for (j=0; j<size-1; j++)

{

if (mas[j+1]<mas[j]) {

float hold=mas[j]; mas[j]=mas[j+1]; mas[j+1]=hold;

}

}

if ((size % 2) !=0) median=mas[size/2]; else median=(mas[size/2-1]+mas[size/2])/2; for (i=0; i<size; i++)

cout << " mas["<<i<<"]="<< mas[i]; cout << endl;

cout << "Median=" << median << endl; system("PAUSE");

return 0;

}

Мода – это наиболее часто встречающееся значение среди значений массива.

#include <iostream.h> main ()

{

int size;

cout << "Input size" << endl; cin >> size;

int mas[size]; int i,j; int max=0, mode=0, c=0, large=0; for (i=0; i<size; i++) {

cout << "mas["<<i<<"]="; cin >> mas[i];

}

for (i=0;i<size ;i++)

if (mas[i]>max) max=mas[i]; for (j=0; j<=max; j++){

c=0;

for (i=0; i<size; i++){ if (mas[i]==j) c++;

}

if (c>large) {mode=j; large=c;}

}

cout << " Moda="<< mode << " Povtor "<<large <<" ras"<<endl; system("PAUSE");

return 0;

}

Многомерные массивы

Массивы в C++ могут иметь много индексов. Обычным представлением многомерных массивов являются таблицы значений, содержащие информацию в строках и столбцах. Чтобы определить отдельный табличный элемент, нужно указать два индекса: первый (по соглашению) указывает номер строки, а второй (по соглашению) указывает номер столбца. Таблицы или массивы, которые требуют двух индексов для указания отдельного элемента, называются двумерными массивами. Заметим, что многомерный массив может иметь более двух индексов. Компиляторы C++ поддерживают по меньшей мере 12-мерные массивы.

Вообще, массивы с m строками и n столбцами называют массивами m на n.

Каждый элемент в массиве a определяется именем элемента в форме a[i][j]; a – это имя массива, а i и j – индексы, которые однозначно определяют каждый элемент в a.

Многомернные массивы могут получать начальные значения в своих объявлениях точно так же, как массивы с единственным индексом. Например, двумерный массив b[2][2] можно объявить и дать ему начальные значения таким образом:

int b[2][2]={{1,2}, {3,4}};

Значения группируются в строки, заключенные в фигурные скобки. Таким образом, элементы b[0][0] и b[0][1] получают начальные значения 1 и 2, а элементы b[1][0] и b[1][1] получают начальные значения 3 и 4. Если начальных значений в данной строке не хватает для их присвоения всем элементам строки, то остающимся элементам строки присваиваются нулевые начальные значения. Таким образом, объявление

int b[2][2]={{1,}, {3,4}};

будет означать что b[0][0] получает начальное значение 1, b[0][1] получает начальное значение 0, b[1][0] получает начальное значение 3 и b[1][1] получает начальное значение 4.

3. Пример программы. Дан одномерный массив, содержащий 6 различных вещественных чисел. Требуется упорядочить массив в порядке возрастания значений его элементов. Операции с элементами массива осуществлять при помощи нотации индексов и указателей.

//Программа сортировки массива с использованием нотации индексов.

#include <iostream.h> main( ) {

float array[10];

//Ввод массива с клавиатуры

for (int i=0; i<9; i++){

cout << "array["<<i<<"]="; cin >> array[i];

cout << endl;

}

// Сортировка массива методом пузырька for (i=0; i<9; i++)

for (int j=0; j<9; j++)

if (array[j]>array[j+1]) { float c=array[j]; array[j]=array[j+1]; array[j+1]=c;

}

// Вывод отсортированного массива на экран for (i=0; i<9; i++){

cout << " array["<<i<<"]="<<array[i]; cout << endl;

}

return 0;

}

Начало

i=0; i<6; i++

Ввод array[i]

i=0; i<5; i++

j=0; j<5; j++

array[j]>array[j+1]

c=array[j];

array[j]=array[j+1];

array[j+1]=c;

i=0; i<6; i++

Вывод отсортированного массива array[i]

Конец

Варианты заданий

1.Дан массив A из 10 целых случайных чисел, с максимальным значением не больше 50. Переслать из массива A в массив B все числа меньше 15. Вывести массивы A и B на печать.

2.В массиве из 20 целых чисел найти наибольший элемент и поменять его местами с первым элементом.

3.В массиве из 10 вещественных случайных чисел, с максимальным значением не больше 25 найти наименьший элемент и поменять его местами с последним элементом.

4.Дан массив X из 10 чисел. Переписать числа из массива X в массив Y в обратном порядке

(Y(1)=X(10),Y(2)=X(9) и т.д.).

5.Дан массив из 15 целых случайных чисел, с максимальным значением не больше 40. Переписать из него в другой массив только четные числа. Содержимое полученного массива вывести на печать.

6.Дан массив A из 13 вещественных чисел со знаком. Переписать в массив B все числа больше нуля.

7.Упорядочить по возрастанию массив, содержащий 20 целых случайных чисел, с максимальным значением не больше 100.

8.Дан массив A, содержащий 15 целых чисел со знаком. Переписать в массив B все числа больше -5 и меньше 30.

9.Дан массив K из 9 целых чисел со знаком. Вывести на печать только отрицательные числа.

10.Упорядочить по убыванию массив, содержащий 10 целых случайных чисел, с максимальным значением не больше 60.

11.Дан массив из 12 чисел со знаком. Найти и вывести на печать наибольший по модулю элемент массива.

12.Дан массив из 10 целых чисел. Вывести на печать числа в диапазоне от 5 до 25.

13.Дан массив A из 12 целых случайных чисел, с максимальным значением не больше 50. Написать программу вывода на печать только нечетных чисел.

14.Дан массив из 9 целых чисел. Найти сумму элементов массива и, если она четная, вывести сообщение "Сумма четная", в противном случае напечатать "Сумма нечетная".

15.Дан отсортированный массив из 15 целых чисел. Найти позицию занимаемую элементом со значением 20, при помощи алгоритма дихотомии.

16.Дан массив из 12 вещественных чисел со знаком. Найти и вывести на печать наибольший элемент массива.

17.Дан массив из 20 чисел со знаком. Найти сумму первого, последнего и центрального элементов массива.

18.Дан массив из 15 целых случайных чисел, с максимальным значением не больше 19. Найти и вывести на печать наименьший элемент массива.

19.Дан массив из 10 чисел со знаком. Найти и вывести на печать наименьший по модулю элемент массива.

20.Дан массив из 15 целых чисел со знаком. Найти медиану массива.

21.Дан массив из 10 целых случайных чисел, с максимальным значением не больше 10. Определить, сколько раз повторяется в нем число 7. Вывести на печать сообщение: "Число 7 повторяется в массиве ... раз".

22.Дан массив из 10 целых случайных чисел, с максимальным значением не больше 5. Вывести на печать все числа больше 2, возведенные в квадрат.

23.Дан массив из 10 целых чисел со знаком. Найти среднее значение массива.

24.Дан массив из N целых чисел, где N – случайное число не более 15. Найти сумму элементов лежащих выше центрального.

25.Дан массив из 10 целых случайных чисел, с максимальным значением не больше 19. Найти сумму квадратов элементов массива.

26.Дан массив из N целых чисел, где N – случайное число не более 15. Найти сумму элементов лежащих ниже центрального.

27.Дан массив A из 10 вещественных чисел со знаком. Переписать в массив B все числа массива A умноженные на 2.

28.Дан массив A из 10 вещественных чисел со знаком. Найти разность между максимальным и минимальным значениями массива.

29.Дан массив из 10 целых случайных чисел, с максимальным значением не больше 19. Найти