Министерство образования и науки Российской Федерации Федеральное агентство по образованию

реклама
Министерство образования и науки Российской Федерации
Федеральное агентство по образованию
Государственное образовательное учреждение
высшего профессионального образования
«Ростовский государственный университет»
Е.С. НЕВСКАЯ, А.А. ЧЕКУЛАЕВА
Структура данных  массив
Часть 1
Методические указания для студентов 1 и 2 курсов
(дневного и вечернего отделений)
механико-математического факультета
Ростов-на-Дону
2006
Печатается по решению кафедры прикладной математики и программирования механико-математического факультета РГУ от 16 февраля 2006
года, протокол № 6 .
АННОТАЦИЯ
Методические указания
предназначены для поддержки основного
курса, связанного с методами программирования, «Системное программирование». Особое внимание уделяется описанию операций с массивом в виде
процедур и функций.
Методические указания содержат список задач для индивидуальной
работы студентов. Методические указания предназначены для студентов вечернего и дневного отделений механико-математического факультета.
Авторы : Е.С.Невская, А.А. Чекулаева
@ Е.С.Невская, А.А. Чекулаева
2
СОДЕРЖАНИЕ
ВВЕДЕНИЕ ................................................................................................................................................................. 3
1. ОПРЕДЕЛЕНИЕ МАССИВА И ЕГО НАЗНАЧЕНИЕ ................................................................................... 4
2. ОПИСАНИЕ МАССИВА И ПРЕДСТАВЛЕНИЕ ЕГО В ПАМЯТИ КОМПЬЮТЕРА ............................ 6
3. ОДНОМЕРНЫЕ МАССИВЫ. КЛАССИФИКАЦИЯ ОПЕРАЦИЙ ............................................................ 8
3.1. ОПЕРАЦИИ ВВОДАВЫВОДА............................................................................................................................. 8
3.2. ПОИСК ЭЛЕМЕНТА В МАССИВЕ ....................................................................................................................... 10
3.3. ОПЕРАЦИИ, ИЗМЕНЯЮЩИЕ СОСТОЯНИЕ МАССИВА........................................................................................ 16
3.4. ОБРАБОТКА ЭЛЕМЕНТОВ МАССИВА ................................................................................................................ 24
3.5. СОРТИРОВКА МАССИВА .................................................................................................................................. 26
4. СПИСОК ЗАДАЧ ................................................................................................................................................ 30
ЛИТЕРАТУРА ......................................................................................................................................................... 42
ВВЕДЕНИЕ
3
Методические указания предназначены для студентов, изучающих
программирование с использованием алгоритмического языка Pascal. Здесь
рассматривается часто использующаяся структура данных  массив.
Методические указания представлены в двух частях. Первая часть посвящена одномерным массивам; вторая часть  двумерным массивам.
Одномерный массив  это такая структура данных, с помощью которой отображаются такие математические понятия, как последовательность,
вектор с n  координатами, множество. Кроме того, программист может сам
ввести абстрактное понятие, соответствующее его задаче, и представить его
с помощью массива.
В первой части определяются типичные для последовательности операции, а именно, поиск, редактирование, включающее операции добавить,
вставить, удалить. Далее рассматриваются простые операции обработки элементов последовательности: определить максимальный элемент последовательности, определить скалярное произведение двух векторов. Кроме того,
разбираются простейшие методы сортировки элементов последовательности: метод вставки, метод выбора и метод пузырька (метод обмена).
Методические указания содержат список задач, которые являются индивидуальными заданиями для студентов по теме «Одномерные массивы».
Предполагается, что для решения этих задач необходимо использовать введенные операции, а также вводить новые операции, соответствующие задаче,
и определять их с помощью процедур и функций алгоритмического языка
Pascal. Алгоритм решения задачи следует формулировать в терминах введенных операций.
Вторая часть методических указаний посвящена двумерным массивам.
1. ОПРЕДЕЛЕНИЕ МАССИВА И ЕГО НАЗНАЧЕНИЕ
4
Массивы относятся к структурированным типам данных. Переменная,
имеющая
структуру
массива,
является
совокупностью
элементов-
переменных одного и того же типа. Каждый элемент массива явно обозначен и к нему имеется прямой доступ. Число элементов массива определяется
при его описании и в дальнейшем не меняется.
Для обозначения элементов используется имя переменной массива и
индекс, который однозначно определяет элемент. Индексы должны иметь
один из доступных типов данных, который называется типом индекса массива. Типами индексов могут быть только скалярные типы, кроме типа
real. Элементы массива упорядочены по месту расположения:
a1, a2,…,an.
Тип индекса задает множество значений, которые могут использоваться для обращения к элементам массива.
Определение типа для массива включает описание типа элементов и
типа индексов:
Type
T=[1..20];
Tip=integer;
Arr=array[T] of Tip;
где Arr – идентификатор нового типа, T – тип индекса, Tip – тип
элементов.
Опишем переменную типа Arr:
var
a : Arr;
Элемент массива a, соответствующий значению индекса i, обозначается как a[i], его математическое обозначение
5
ai .
Массив с одним индексом называют одномерным. В этом случае элементы относятся к скалярному типу. Если элемент массива является структурным типом, например, одномерным массивом, то массив называется двумерным ( математическое понятие − матрица).
Массив предназначен для отображения таких математических понятий, как последовательность, множество, многомерный вектор, отношение,
матрица.
Структуру данных массив удобно использовать, когда известно, что
количество элементов в нем не будет превышать некоторого заданного значения, которое определяется в разделе констант. Фактическое количество
элементов может меняться, но не должно превышать заданной константы.
2. ОПИСАНИЕ МАССИВА И ПРЕДСТАВЛЕНИЕ ЕГО В
ПАМЯТИ КОМПЬЮТЕРА
Синтаксис описания массива:
var <имя массива>: array[<список индексных типов>]
of <тип элемента>;
где имя массива  идентификатор,
<список индексных типов>  список одного или нескольких индексных типов, разделенных запятыми.
Возможен другой способ описания массива:
type < имя типа>= array[<список индексных типов>]
of <тип элемента>;
var <имя массива> : <имя типа>;
где имя типа  идентификатор.
Здесь вводится новое понятие  < имя типа>, которое в дальнейшем и
используется. Такое описание массива является предпочтительней.
6
В качестве примера опишем вектор A[1..N].
const N=20;
type Tip = integer;
Первый способ.
var A : array[1..N] of Tip;
Второй способ.
Type
vect= array[1..N] of Tip;
Var A:vect;
Массиву выделяется сплошная область памяти. Это значит, что элементы вектора
a1, a2,…,an располагаются последовательно друг за дру-
гом.
Пусть описан одномерный массив:
var
a:array[m..n] of
Tip;
Если предположить, что элемент типа Tip занимает p байт памяти, то
адресом элемента массива с индексом i будет:
a+ (i-m)*p,
где a – адрес первого элемента массива.
Приведенные формулы вычисления адреса содержат обычные арифметические операции. При неправильном значении индексов будет получен неправильный адрес. Программист должен предусматривать возможность возникновения таких ошибок, включая проверки правильности значений индексов, а именно, проверку нахождения индексов внутри границ диапазона. Если использовать директиву компилятора {$R+}, то проверка будет выполняться автоматически.
7
Следует отметить, что вычисление адреса связано с выполнением дополнительных операций, поэтому по возможности рекомендуется уменьшать использование переменных с индексами.
3. ОДНОМЕРНЫЕ МАССИВЫ. КЛАССИФИКАЦИЯ ОПЕРАЦИЙ
3.1. Операции вводавывода
Опишем процедуру Input ввода массива a[1..n] с клавиатуры:
const n_max=20;
type vect=array[1..n_max] of integer;
procedure Input(var n:integer;
var a:vect);
var i:integer;
begin
writeln(‘Задайте кол  во, не превышающее’,n_max);
read(n);
writeln(‘Задайте элементы’);
for i:=1 to n do
read(a[i]);
end;
Опишем процедуру Output вывода массива a[1..n]:
const n_max=20;
type vect=array[1..n_max] of integer;
procedure Output(n:integer;
const a:vect);
var i:integer;
begin
writeln;
for i:=1 to n do
write(a[i]:5);
writeln
end;
8
Данные удобно хранить в файле на диске. Пусть создан текстовый
файл Dan.txt, в котором содержатся элементы массива. Файл с данными создается аналогично тому, как создается программный текст на языке
PASCAL Опишем процедуру Input_D ввода массива a[1..n] с диска:
const n_max=20;
type vect=array[1..n_max] of integer;
procedure Input_D(var n:integer;
var a:vect);
var f:text;
begin
assign(f,’DAN.txt’);
reset(f);
n:=0;
while not eof(f) and (n<n_max) do
begin
n:=n+1;
read(f,a[n]);
end;
close(f)
end;
Замечания.
1) f:text; описание файловой переменной;
2) assign(f,’DAN.txt’); оператор связывания файловой переменной с
файлом на диске;
3) reset(f);
файл DAN.txt открывается для чтения ( указатель
чтения устанавливается в начало файла);
4) eof(f) − булевская функция, которая имеет значение true, если достигнут
конец данных в файле ( end of file − конец файла), значение false − в
противном случае;
5) read(f,a[n]); оператор чтения очередной записи из файла и сдвиг указателя
чтения на следующую запись в файле;
6) close(f) − оператор, по которому закрывается файл;
7) переменная n после выхода из цикла получает значение количества элементов
массива, не превышающее n_max;
8) если количество элементов в файле больше n_max, то файл прочитан не до
конца.
9
3.2. Поиск элемента в массиве
Поиск элемента в массиве предполагает, что необходимо найти первое
вхождение некоторого значения в массив.
Алгоритмы рассмотренных ниже трех задач имеют общую характерную черту: в худшем случае требуется, чтобы циклический процесс выполнялся n раз, то есть просматриваются все элементы массива. Такие алгоритмы называют линейными.
Задача 1. Найти элемент x в массиве a[1..n].
Постановка задачи.
Входные данные: n  количество элементов массива,
n  N (множеству натуральных чисел);
a[1], a[2], … , a[n]  элементы массива,
a[1..n]  Z (множеству целых чисел);
x  Z (значение, которое требуется найти в массиве).
Выходные данные: если x содержится в массиве: x = a[i], то i
его номер; если x отсутствует в массиве, то i = n+1.
Метод решения.
Определим, что нужно найти, используя формальный язык:
( i:1in:a[i]= x) or ( i:1in:a[i] x)and (i=n+1)
Если первый дизъюнктивный член имеет значение true (в этом случае
in и a[i]= x ), то значение x есть в массиве и его номер i.
Если второй дизъюнктивный член имеет значение true (в этом случае
in и a[i] x ), то значения x нет в массиве (i=n+1).
10
Из математического определения задачи следует, что для организации
просмотра элементов массива необходимо использовать оператор цикла
while… или repeat….
Описание алгоритма (с использованием repeat …).
i:=0;
repeat
i:=i+1
until (a[i]= x) or (i=n);
if a[i]  x then i:=n+1;
Описание алгоритма (с использованием while …)
i:=1;
while (in)and (a[i]  x )
i:=i+1;
Предполагается, что при in происходит выход из цикла без проверки условия a[i]  x (i=n+1).
Задача 2. Поиск с барьером.
Задача поиска часто используется в других более сложных задачах, поэтому ее алгоритм должен быть эффективным, то есть кратким и быстро выполнимым.
Метод решения.
Упростим составное условие в заголовке цикла, используя следующий
прием:
 добавим к массиву еще один элемент a[n+1];
 новому элементу присваивается значение x (a[n+1]:=x) и
оно служит граничным признаком.
Этот метод называют поиском с барьером.
11
Описание алгоритма (поиск с барьером).
a[n+1]:=x;
i:=0;
repeat
i:=i+1
until (a[i]= x);
Опишем алгоритм в виде функции. Так как одним из параметров
функции является массив, то следует определить тип массива и возможное
количество элементов так, как это делалось при описании процедур ввода−вывода. Необходимо не забыть, что в массиве будут находиться n+1
элементов.
const n_max=20;
type vect=array[1..n_max] of integer;
function search(n:integer;const a:vect;
x:integer):integer;
var i:integer;
begin
a[n+1]:=x;
i:=0;
repeat
i:=i+1
until (a[i]= x);
search:=i
end;
Задача 3. Поиск элемента в упорядоченном массиве. Линейный поиск.
Постановка задачи.
Входные данные: n  количество элементов массива n  N);
a[1], a[2], … , a[n]  элементы массива,
a[1..n]  Z (множеству целых чисел);
12
x  Z (значение, которое требуется найти в массиве).
Выходные данные: если a[i]=x, то i является найденным номером, в противном случае x(a[i];a[i+1]), 1i<n,
Метод решения.
Приведем математическое определение упорядоченности по неубыванию элементов массива a[1..n]:
(i:1i<n:a[i]≤a[i+1])
Для упорядоченного массива удобно ввести ограничение:
a[1]≤ x <a[n].
Тогда то значение x, которое требуется найти удовлетворяет условию:
(1i<n)and(a[i]x<a[i+1]).
Это значит, что если a[i]=x, то i является найденным номером,
в противном случае x(a[i];a[i+1]), 1i<n,
то есть пока (i+1<n)and(a[i+1]x), продолжаем поиск i:=i+1.
Условие a[i+1]x использует упорядоченность массива, ограничение a[1]≤ x <a[n] позволяет упростить логическое выражение в заголовке цикла, тогда получим : пока a[i+1]x , продолжаем поиск.
Описание алгоритма.
if (a[1]x) and (x<a[n]) then
begin
i:=1;
while (a[i+1]x) do
i:=i+1;
end;
Опишем алгоритм в виде функции search_Lin.
сonst n_max=20;
13
type vect=array[1..n_max] of integer;
function search_Lin(n:integer; const a:vect;
x:integer):integer;
var i:integer;
begin
if a[1]>x then search_Lin:=0;
if a[n]<=x then search_Lin:=n;
if (a[1]<= x) and (x<a[n]) then
begin
i:=1;
while (a[i+1]x) do
i:=i+1;
search_Lin:=i
end
`end;
Сложность линейных алгоритмов определяется количеством элементов в массиве и записывается так O(n) (читается: порядка n). Сложность
определяет затраты на выполнение циклического процесса.
Задача 4. Поиск элемента в упорядоченном массиве. Бинарный поиск.
Метод решения.
Найдем середину массива − индекс k.
Сравним a[k] и x. Возможны три случая:
1) a[k] = x
− искомый элемент найден;
2) a[k] < x
− искомый элемент находится в правой части массива;
3) a[k] > x
− искомый элемент находится в левой части массива.
Описание алгоритма.
i:=1; j:=n
q:=false;
repeat
k:=(i+j) div 2;
if a[k] = x then q:=true
else if a[k] < x then i:=k+1
else i:k-1
until q or (i>j);
14
Этот алгоритм называется бинарным поиском (или двоичным поиском, или дихотомическим поиском).
Сложность этого алгоритма порядка log2(n) .
С помощью этого алгоритма можно определить, содержится ли в массиве заданный элемент x и каков его номер (k). Для того, чтобы определить
отрезок, на котором находится x , эффективней воспользоваться алгоритмом,
который опишем в виде функции search_Bin.
const n_max=20;
type vect=array[1..n_max] of integer;
function search_Bin(n:integer; const a:vect;
x:integer):integer;
var i,j:integer;
begin
if (a[1]> x) then j:=0;
if (a[n]<= x) then j:=n;
if (a[1]<= x) and (a[n]> x) then
begin
i:=1; j:=n;
repeat
k:=(i+j) div 2;
if a[k] <= x then i:=k+1;
if a[k] >= x then j:=k-1
until (i>j);
if a[k]= x then j:=k
end;
search_Bin:=j
end;
Этот алгоритм определяет отрезок, которому принадлежит заданный
элемент x, а именно,
x[a[j];a[j+1]), 1j<n. Если x=a[j],
то j – индекс значения x в массиве.
15
3.3. Операции, изменяющие состояние массива
К операциям, изменяющим состояние массива, относятся следующие:
изменить, вставить, добавить, удалить элементы.
Операция изменить.
Задача 5. Сдвинуть элементы массива на один элемент вправо, устанавливая последний элемент на первое место. Такой сдвиг называется циклическим.
Постановка задачи.
Входные данные: n  количество элементов массива (n  N);
a[1..n]  Z (множеству целых чисел);
Выходные данные: измененный массив a[1..n].
Метод решения.
1) Запомнить последний элемент ( переменная x).
2) Для всех i от n-1 до 1 выполнить сдвиг: a[i+1]:=a[i].
3) Установить последний элемент (x) на первое место.
Описание алгоритма.
x:=a[n];
for i:=n-1 downto 1 do
a[i+1]:=a[i];
a[1]:=x;
Замечания:
1) использование служебного слова downto позволяет счет вести
с шагом (-1);
2) получили измененный массив.
Задача 6. Выполнить циклический сдвиг вправо элементов массива на
заданное количество.
Постановка задачи.
16
Входные данные: n  количество элементов массива,
a[1..n]  Z (множеству целых чисел);
k  количество сдвигов.
Выходные данные: измененный массив a[1..n].
Опишем алгоритм в виде процедуры Sdvig_k. Введем тип элементов массива для того, чтобы показать независимость алгоритма от типа элементов. Если изменяется тип элементов, то достаточно изменить значение
имени Tip.
const n_max=20;
type
Tip= integer;
vect=array[1..n_max] of Tip;
proctdure Sdvig_k(n:integer; var a:vect;
k:integer);
var i,j:integer;
x:Tip;
begin
for j:=1 to k mod n do
begin
x:=a[n];
for i:=n-1 downto 1 do
a[i+1]:=a[i];
a[1]:=x;
end
end;
Операция добавить.
Задача 7. Добавить x к массиву a[1..n].
Описание алгоритма.
a[n+1]:=x;
При выполнении операции добавить осуществляется изменение количества элементов массива и n+1 ый элемент получает значение x.
Операция вставить.
17
Операция вставить аналогично операции добавить изменяет количество элементов массива и состояние массива.
Задача 8. Вставить заданное значение на k – тую позицию массива.
Постановка задачи.
Входные данные: n  количество элементов массива (n  N),
a[1..n]  Z (множеству целых чисел);
k  позиция;
x  заданное значение.
Выходные данные: измененный массив a[1..n+1].
Метод решения.
1) сдвинуть все элементы вправо, начиная с n до k;
2) a[k]:=x;
Описание алгоритма.
for i:=n downto k do
a[i+1]:=a[i];
a[k]:=x;
Задача 9. Вставить заданное значение после заданного элемента массива.
Постановка задачи.
Входные данные: n  количество элементов массива (n  N),
a[1..n]  Z (множеству целых чисел);
x заданное значение, которое требуется вставить;
b элемент массива.
Выходные данные: измененный массив a[1..n+1].
18
Метод решения:
1) определить позицию элемента b в массиве, используя функцию
search ( k – его индекс);
2) сдвинуть все элементы вправо, начиная с n до k;
3) a[k]:=x.
Описание алгоритма.
k:=search(n,a,b);
for i:=n downto k do
a[i+1]:=a[i];
a[k]:=x;
Замечание: если элемент b отсутствует в массиве, то k=n+1 и x
добавится в массив.
Операция вставить в упорядоченный массив.
Задача 10. Вставить заданное значение в упорядоченный по неубыванию массив так, чтобы не нарушилась упорядоченность.
Постановка задачи.
Входные данные: n  количество элементов массива(n  N);
a[1..n]  Z (множеству целых чисел);
x заданное значение, которое требуется вставить.
Выходные данные: измененный массив a[1..n+1].
Метод решения 1.
1) определить позицию элемента b в массиве, используя функцию
search_Lin ( k – его индекс);
2) сдвинуть все элементы вправо, начиная с n до k+1;
3) a[k+1]:=x.
19
Описание алгоритма.
k:=search_Lin;
for i:=n downto k+1 do
a[i+1]:=a[i];
a[k+1]:=x;
Замечания:
1) можно воспользоваться функцией search_Bin; но если массив
небольшого
размера,
то
эффективней
использовать
функцию
search_Lin, так как ее циклический процесс содержит меньше операций;
2) этот алгоритм содержит два последовательных цикла: для определения позиции элемента и для сдвига элементов массива..
Метод решения 2.
Рассмотрим алгоритм вставки в упорядоченный массив, основанный на
следующей идее: искать позицию для значения x будем с одновременным
сдвигом элементов вправо.
Опишем алгоритм в виде процедуры Insert.
const n_max=20;
type
Tip= integer;
vect=array[1..n_max] of Tip;
Procedure Insert( n:integer; var a:vect;
x:Tip);
var i:integer;
begin
i:=n;
while (i>0 ) and (a[i] > x) do
begin
a[i+1]:=a[i]; i:=i-1
end;
a[i+1]:=x;
end;
20
Замечание. В алгоритме не предусматривается изменение количества
элементов в массиве. Если для конкретной задачи это важно, то следует внести в процедуру следующие изменения:
 в заголовке процедуры объявить n выходным параметром
(var n:integer);
 в теле процедуры добавить оператор n:=n+1;
Операция удалить.
Задача 11. Удалить из массива все вхождения заданного значения.
Постановка задачи.
Входные данные: n  количество элементов массива (n  N),
a[1..n]  Z (множеству целых чисел);
x заданное значение, которое требуется удалить.
Выходные данные: k- количество элементов в измененном массиве
a[1..k].
Промежуточные данные:
i– индекс для просмотра элементов массива.
Метод решения.
Идея метода удаления заключается в следующем: если очередной элемент массива
a[i]≠x, то он записывается в массив по индексу k:
a[k]:=a[i].Здесь индекс k является счетчиком элементов в выходном
массиве.
Описание алгоритма.
k:=0;
for i:=1 to n do
if a[i]<>x then
begin
k:=k+1;
end;
a[k]:=a[i]
21
Опишем алгоритм в виде процедуры Delete, считая, что удаление
происходит из массива a[m..n] (1≤m<n).
const n_max=20;
type
Tip= integer;
vect=array[1..n_max] of Tip;
Procedure Delete(m,n:integer; var a:vect;
x:Tip;var k:integer);
var i:integer;
begin
k:=m-1;
for i:=m to n do
if a[i]<>x then
begin
k:=k+1;
a[k]:=a[i]
end;
end;
Задача 12. Удалить из массива повторяющиеся элементы.
Например, пусть дан массив : 4 8 4 2 5 8 4 1 5.
После удаления повторяющихся элементов получим массив:
4 8 2 5 1, то есть отсутствуют дублированные элементы.
Постановка задачи.
Входные данные: n  количество элементов массива,
a[1..n]  Z (множеству целых чисел).
Выходные данные: k- количество элементов в измененном массиве
a[1..k].
Промежуточные данные:
i– индекс для просмотра элементов массива.
Метод решения.
Для решения задачи используем процедуру задачи 11 Delete.
22
Описание алгоритма.
i:=1;
while (i< n) do
begin
Delete(i+1,n,a,a[i],k);
n:=k;
i:=i+1
end;
В алгоритме нельзя использовать цикл for… , так как кратность цикла
меняется на каждом шаге циклического процесса.
Для того, чтобы добиться эффективности, необходимо вместо вызова
процедуры
Delete(i+1,n,a,a[i],k);
подставить ее тело, заменяя в нем формальные параметры на фактические.
Опишем полученный алгоритм в виде процедуры, назовем ее
Pack (сжа-
тие).
const n_max=20;
type
Tip= integer;
vect=array[1..n_max] of Tip;
Procedure Pack(var n:integer; var a:vect);
var i,j,k:integer;
x:Tip;
begin
i:=1;
while (i< n) do
begin
{ Delete(i+1,n,a,a[i],k);}
k:=i; x:=a[i];
for j:=i+1 to n do
if a[j]<>x then
begin
k:=k+1; a[k]:=a[j]
end;
n:=k;
i:=i+1
end;
end;
23
3.4. Обработка элементов массива
Остановимся на некоторых, часто использующихся задачах.
Задача 13. Найти максимальный элемент в массиве.
Постановка задачи.
Входные данные: n  количество элементов массива,
a[1..n]  Z (множеству целых чисел).
Выходные данные: k- индекс максимального элемента.
Промежуточные данные:
i– индекс для просмотра элементов массива.
Метод решения:
1) пусть максимальным будет первый элемент массива ( k :=1);
2) анализируем остальные элементы:
если a[i]>a[k], то k:=i.
Описание алгоритма.
k :=1;
for i:=2 to n do
if a[i]>a[k] then k:=i;
Задача 14. Определить в массиве количество вхождений заданного
значения.
Постановка задачи.
Входные данные: n  количество элементов массива,
a[1..n]  Z (множеству целых чисел);
x − заданное значение.
24
Выходные данные: k- количество вхождений .
Промежуточные данные:
i– индекс для просмотра элементов массива.
Описание алгоритма.
k:=0;
for i:=1 to n do
if a[i]=x then k:=k+1;
Задача 15. Определить скалярное произведение двух векторов.
Постановка задачи.
Входные данные: n  количество элементов вектора,
a[1..n], b[1..n]  R (множеству вещественных чисел).
Выходные данные: s- скалярное произведение.
Промежуточные данные:
i– индекс для просмотра элементов массива.
Метод решения.
Математическое описание задачи:
n
s=  a[i] * b[i] .
i 1
Представим эту сумму в виде рекуррентного соотношения:
s0=0,
si=si-1+ a[i]*b[i], i = 1, 2, …,n.
Опишем алгоритм в виде функции Skal_P.
const n_max=20;
type
Tip= real;
25
vect=array[1..n_max] of Tip;
function Skal_P( n:integer; const a,b:vect):Tip;
var i:integer;
s:Tip;
begin
s:=0;
for i:=1 to n do
s:=s + a[i]*b[i];
Skal_P:=s
end;
3.5. Сортировка массива
Сортировка массива относится к операциям, изменяющим состояние
массива без изменения количества элементов в нем. Остановимся на трех
простых методах: метод вставки (включения), метод выбора и метод обмена
(метод пузырька). Алгоритмы этих методов описаны в [1]. Сложность этих
алгоритмов определяется как O(n2).
Сортировку будем осуществлять в порядке неубывания элементов массива, то есть выходной массив должен удовлетворять условию:
(i:1i<n:a[i]≤a[i+1])
Постановка задачи.
Входные данные: n  количество элементов массива,
a[1..n]  Z (множеству целых чисел).
Выходные данные: измененный массив a[1..n].
Промежуточные данные:
26
i,j– индексы для просмотра элементов массива.
Метод вставки (включения):
1) предполагается, что массив из одного элемента упорядочен;
2) для всех остальных элементов ( 2≤j ≤n) выполнить следующее
действие: вызвать процедуру вставки в упорядоченный массив
Insert(j-1,a,a[j]).
Опишем алгоритм сортировки в виде процедуры Sort_Ins, причем вместо вызова процедуры
Insert(j-1,a,a[j]) подставим ее
тело, заменяя формальные параметры на фактические.
const n_max=20;
type
Tip = integer;
vect = array[1..n_max] of Tip;
Procedure Sort_Ins( n:integer; var a:vect);
var i,j : integer;
x : Tip;
begin
for j:=2 to n do
begin
i:=j-1;
x:=a[j];
while (i>0 ) and (a[i]>x) do
begin
a[i+1]:=a[i]; i:=i-1
end;
a[i+1]:=x;
end
end;
Уменьшим количество операций, выполняющихся
во внутреннем
цикле. Для этого воспользуемся методом барьера, а именно: элемент x , ко27
торый ищется в массиве, установим в нулевую позицию:
a[0]:=x, тогда
определение типа vect нужно изменить:
vect =array[0..n_max] of Tip;
Опишем алгоритм в виде процедуры
Sort_Ins_0.
const n_max=20;
type
Tip = integer;
vect = array[0..n_max] of Tip;
Procedure Sort_Ins_0( n:integer; var a:vect);
var i,j : integer;
x : Tip;
begin
for j:=2 to n do
begin
i:=j-1; x:=a[j]; a[0]:=x;
while (a[i]>x) do
begin
a[i+1]:=a[i]; i:=i-1
end;
a[i+1]:=x;
end
end;
Метод выбора.
Идея метода выбора заключается в следующем: определяется индекс k
максимального элемента в массиве и осуществляется обмен между k−тым и
последним элементами. Индекс последнего элемента будем менять от n до 2.
Опишем алгоритм в виде процедуры Sort_Max.
const n_max=20;
type
Tip = integer;
vect = array[1..n_max] of Tip;
Procedure Sort_Max( n:integer; var a:vect);
var i,j,k : integer;
x : Tip;
begin
28
for j:=n downto 2 do
begin
{ определение индекса максимального элемента k}
k :=1;
for i:=2 to j do
if a[i]>a[k] then k:=i;
{ обмен между a[k] и a[j] }
`x:=a[k]; a[k]:=a[j]; a[j]:=x
end
end;
Метод обмена (метод пузырька).
Идея метода заключается в следующем: с помощью операции обмена
максимальный элемент сдвигается на последнее место массива. Индекс последнего элемента следует менять от n до 2.
Описание алгоритма.
for j:=n downto 2 do
{ сдвиг максимального элемента на j-тое место}
for i:=1 to j-1 do
if a[i]>a[i+1] then
begin
`x:=a[i]; a[i]:=a[i+1]; a[i+1]:=x
end;
При некотором j<n может наступить ситуация, что a[i]≤a[i+1]
для всех
1≤i<j. Это значит, что массив уже отсортирован и продолжать
выполнять внешний циклический процесс не нужно. Поэтому заголовок
внешнего цикла сформулируем так: пока осуществляется обмен во внутреннем цикле, продолжать работу, иначе выйти из цикла.
29
Для реализации этого алгоритма введем булевскую переменную
flag. Начальное значение переменной flag:= true. Перед внутренним циклом переменная должна изменить значение
flag:=false.
Если обмен выполнится, то переменная должна получить значение true
для продолжения процесса, иначе произойдет выход из внешнего цикла, так
как flag=false.
Опишем рассмотренный алгоритм в виде процедуры Sort_Swap.
const n_max=20;
type
Tip = integer;
vect = array[1..n_max] of Tip;
Procedure Sort_Swap( n:integer; var a:vect);
var
i,j : integer;
x : Tip;
flag : Boolean;
begin
j:=n;
flag:= true;
while flag do
begin
flag:= false;
{ сдвиг максимального элемента на j-тое место}
for i:=1 to j-1 do
if a[i]>a[i+1] then
begin
flag:= true;
`x:=a[i]; a[i]:=a[i+1]; a[i+1]:=x
end;
j:=j-1
end
end;
4. СПИСОК ЗАДАЧ
30
Задачи разбиты на 5 группы по следующему принципу:
1) приведены простые задачи, требующие, кроме операций вводавывода массива, дополнительно одну операцию, которую следует описать в
виде процедуры или функции;
2) в этой группе требуется вводить несколько дополнительных операций;
3) задачи связаны с преобразованием массива;
4) задачи связаны с построением массива;
5) задачи повышенной трудности.
Группа 1.
1. В целочисленном массиве нечётные элементы увеличить в 2 раза, а у
элементов с чётными номерами изменить знаки на противоположные.
2. Напечатать те элементы массива, индексы которых являются степенями двойки (1, 2, 4, 8, …).
3. Напечатать те элементы массива, индексы которых являются полными квадратами (1, 4, 9, 16, …).
4. Напечатать те элементы массива, индексы которых являются:
числами Фибоначчи (1, 2, 3, 5, 8, 13, …).
5. По заданным вещественным числам an , an1 , ...a1 , a0 , x вычислить значение многочлена
a n x n  a n 1 x n 1  ...  a1 x  a 0 ,
его первую и вторую производные в точке x.
n
6. Вычислить произведение p   ai  bi и их сумму.
i 1
7 Дан массив целых чисел. Проверить, является ли массив симметричным относительно своего центрального элемента.
31
8. Дан массив вещественных чисел. Проверить, все ли элементы массива положительны.
9. Дан массив целых чисел. Проверить, есть ли в массиве хотя бы один
элемент, имеющий чётное значение.
10. Дан массив целых чисел. Проверить, расположены ли в массиве
элементы в порядке возрастания.
11. Дан массив целых чисел. Проверить, содержатся ли в массиве подряд два нулевых элемента.
12. Дан массив целых чисел. Проверить, образуют ли элементы массива знакочередующуюся последовательность.
13. Найти количество элементов в массиве, отличающихся меньше,
чем на  от среднего арифметического элементов массива.
14. Найти сумму элементов с номерами 1,2,3,… и сумму элементов с
номерами 2,4,6,… Проверить, равны ли эти суммы.
15. Дан вещественный массив. Распечатать те числа массива, которые
удовлетворяют условию xi  i 2 .
16. Дан массив целых положительных чисел. Напечатать те числа, в
состав которых входит заданная цифра.
Группа 2.
1. Найти сумму элементов массива, расположенных между максимальным и минимальным элементами (в сумму включить максимальный и минимальный элементы).
2. Найти отношение суммы элементов, расположенных до максимального элемента, к сумме элементов, расположенных после максимального
элемента.
32
3. Найти сумму элементов, расположенных между первым и последним нулями.
4. Найти среднее арифметическое элементов массива, максимальный
элемент массива и величину отклонения среднего арифметического от максимального.
5. Найти количество вхождений максимального и минимального элементов в заданный массив.
6. Вычислить
y  x1  x1 x2  x1 x2 x3  ...  x1 x2 ...xm , где m - либо номер пер-
вого отрицательного элемента массива х, либо число n, если в массиве х нет
отрицательных элементов.
7. В массиве найти номер минимального элемента и проверить оставшуюся часть массива на содержание в ней только положительных элементов.
8. В массиве найти номер первого нулевого элемента и проверить на
убывание оставшуюся часть массива.
9. В массиве натуральных чисел A[1..n] найти наибольший общий делитель этих чисел и определить, является ли наибольший общий делитель
элементом массива.
10. Дан массив. Определить, сколько раз в нём встретились два подряд
идущих нулевых элемента.
11. Дан массив целых чисел. Для каждого числа, входящего в массив,
указать, сколько раз оно содержится в массиве.
12. Дан массив целых чисел. Выяснить, имеется ли в массиве хотя бы
одна пара совпадающих чисел.
13. Дан массив целых чисел. Напечатать все числа, входящие в массив
по одному разу.
14. Дан массив целых чисел. Найти число различных элементов массива.
33
15. Даны координаты точек на плоскости: x1 , y1, ..., x n , y n . Найти номера
двух точек, расстояние между которыми наибольшее (считать, что такая пара
точек единственная).
16. Дан массив из целых чисел. Определить количество инверсий в
массиве (т. е таких пар элементов, в которых большее число находится слева
от меньшего: xi  x j при i>j ).
17. Дан массив. Найти среди его элементов два элемента, модуль разности которых имеет наименьшее значение.
18. Дан массив. Найти пару соседних элементов, наиболее близко расположенных друг к другу.
19. Элементами массива являются 0 и 1.Проверить, существует ли
строгое чередование 0 и 1.
20. Среди элементов массива найти к наибольших элементов.
21. Пусть числовая ось разбита на отрезки точками a1 , a2 ,..., an . Проверить, образуют ли точки упорядоченную последовательность. Если да, то
определить, какому отрезку принадлежит значение х. В противном случае
проверить, принадлежит ли х последовательности.
22. Найти количество элементов, удовлетворяющих условию 2 i  ai  i! ,
а также проверить, удовлетворяет ли этому условию максимальный элемент
массива.
23. Среднестатистическим назовём элемент массива, если для него модуль разности его значения и среднего арифметического элементов массива
достигает минимума. Уникальным будем называть элемент, для которого та-
34
кой модуль разности достигает максимума. В массиве A(n) найти номера
(индексы) среднестатистического и уникального элементов.
24. Дан вещественный массив. Найти элемент массива, значение которого наиболее близко к какому-нибудь целому числу.
25. Если количество нулей в массиве A[1..n] больше количества нулей
в массиве B[1..m], то в каждом массиве найти максимальный элемент, иначе
найти сумму элементов в массиве A и сумму элементов в массиве B. Описать функции: для подсчёта нулей в массиве, для нахождения максимального
элемента и для нахождения суммы элементов.
26. Если максимальный элемент массива A[1..n] больше максимального
элемента
n
ai  ai /  ai ,
i 1
массива
B[1..m],
то
преобразовать
массивы:
m
bi  bi /  bi . Описать функцию нахождения максимального
i 1
элемента в массиве, функцию нахождения суммы элементов массива и процедуру деления элементов массива на заданное число.
27 Если первые ненулевые элементы массивов A[1..n] и B[1..m] различны, то в каждом массиве найти максимальные элементы после первого
ненулевого элемента, иначе в каждом массиве все элементы возвести в квадрат. Описать необходимые процедуры и функции.
Группа 3.
1. Преобразовать массив по правилу: если ai  0 , то увеличить a i на
квадрат наименьшего элемента массива, иначе увеличить a i на квадрат
наибольшего элемента массива.
2. Преобразовать массив х[1..n] по следующему правилу ( x k'  значе'
ние кго элемента после преобразования):
x k'  max xi
при 1  i  k ;
35
3. Преобразовать массив х[1..n] по следующему правилу ( x k' - значение
'
к-го элемента после преобразования):
x1'  x1 , x n'  x n , xk  ( xk 1  xk  xk 1 ) / 3 при к=2, 3, … , n-1.
'
4. Каждый j-ый элемент массива (кроме первого) заменить средним
значением первых j элементов.
5. В массиве из чётного количества элементов каждый элемент с чётным
индексом
поменять
с
предыдущим
элементом,
т.е.
получить
z 2 z1 z 4 z 3 ...z 2n z 2n1 . Вспомогательный массив не заводить.
6. Удалить из массива элемент, расположенный перед максимальным
элементом.
7. Удалить из массива первые К элементов.
8. Удалить из массива все вхождения максимального и минимального
элементов.
9. Удалить из массива значение элемента с заданным номером, затем
проверить наличие отрицательного элемента в изменённом массиве.
10. Из каждого положительного элемента массива вычесть предыдущий. Вспомогательный массив не заводить.
11. Имеется целочисленный массив. Необходимо ’сжать’ массив, выбросив из него нулевые элементы. Если нулевых элементов нет, сообщить,
что сжатие невозможно. Дополнительный массив не применять.
12. Вставить в массив А[1..n] элемент с1 перед каждым элементом со
значением с2.
13. Вставить в массив А[1..n]
максимальный элемент после мини-
мального элемента, получая массив A[1..n+1];
36
14. Вставить в массив А[1..n] заданное значение после элемента с заданным номером и проверить, является ли полученный массив упорядоченным по неубыванию.
15. Дан массив Х. Переслать в другой массив все элементы, значения
которых принадлежат отрезку [а;b].
16. Переслать в массив Y все элементы массива X с нечётными номерами, а в массив Z, элементы массива X, значения которых кратны 5.
17. Элементы, расположенные в массиве между минимальным и максимальным элементами (включая эти элементы), расположить в обратном
порядке.
18. Вставить в массив А на заданную позицию максимальный элемент
массива В.
19. Наименьший элемент массива заменить на среднее арифметическое отрицательных элементов.
20. Сравнить два массива: массив A[1..n] и массив B[1..n+1] после того,
как из второго массива удалён его максимальный элемент.
21. Проверить, упорядочены ли по убыванию массивы A[1..n] и
B[1..m]. Если оба массива упорядочены по убыванию, то построить новый
массив C[1..n+m] слиянием массивов A и B без нарушения упорядоченности.
В противном случае в массиве С расположить вначале все элементы массива
A, затем все элементы массива B.
22. Каждый элемент массива А(n) (кроме двух крайних) заменить выражением ai' 
ми a1' 
a1  a2
;
2
ai 1  2ai  ai 1
, i  2,3,..., n  1, а крайние элементы – выражения4
an 
an1  an
.
2
23. Удалить из массива A(n) “лишние”(кроме первого) элементы так,
чтобы оставшиеся образовали возрастающую последовательность.
37
24. Описать функцию нахождения среднего арифметического элементов массива, значения которых отличны от заданного числа С, и функцию
нахождения номера максимального элемента массива. Воспользоваться
функциями для замены в массиве A[1..n] максимального элемента на среднее
арифметическое элементов, отличных от заданного числа X и для замены в
массиве B[1..m] максимального элемента на среднее арифметическое элементов, отличных от заданного числа Y.
25. Удалить из каждого массива A[1..n] и B[1..m] первый отрицательный элемент, если он имеется в массиве. Описать функцию нахождения номера первого отрицательного элемента (или номеру присвоить ноль) и процедуру удаления из массива элемента с заданным номером.
Группа 4.
1. Построить массив из n вещественных чисел
1/2, 3/4, 5/6, …
2. Построить массив из n вещественных чисел
1, 1+1/2, 1+1/2+1/3, …
3. Дан массив X целых положительных чисел. Сумму цифр каждого
числа поместить в массив Y.
4. Сформировать массив, элементами которого являются числа
1, 3, 5, …, n-1, n, n-2, n-3, …, 2.
5. Сформировать массив, элементами которого являются числа
2, 1, 4, 3, 6, 5, …, n, n-1.
6. Сформировать массив, элементами которого являются числа
1, n, 2, n-1, 3, n-2, … ,n div 2, n div 2+1.
38
7. Сформировать массив по правилу ai  x i (x – задано, i=1,2,…,n).
8. Сформировать массив по правилу ai  x n  i! (x, n – заданы,
i=1,2,…,n).
9. Сформировать массив из 2n элементов, элементами которого являются числа
1, -1, 2, -2, …, n, -n.
10. Дан массив из n 2 элементов. Найти сумму каждых n элементов и
поместить в массив из n элементов.
b1 a 1 ...  a n , b2  a n 1  ...  a 2 n ,
..., bn  a ( n 1) n 1  ...  a n 2 .
11. Даны два массив A[1..n] и B[1..n]. Получить массив C[1..n], элементы
которого
вычисляются
по
правилу:
c1  a1  bn , c 2  a 2  bn 1 , ..., c n  a n  b1 . В полученном массиве подсчитать коли-
чество нулевых элементов.
12. Рассматривая массивы А и В как последовательности цифр десятичной записи некоторых неотрицательных целых чисел, получить в массиве
С – аналогичное представление для суммы этих двух чисел.
13. Рассматривая массивы А и В как последовательности цифр двоичной записи некоторых неотрицательных целых чисел, получить в массиве С
– аналогичное представление для суммы этих двух чисел.
14. Рассматривая массивы А и В как последовательности цифр десятичной записи некоторых неотрицательных целых чисел, получить в массиве
С – аналогичное представление для разности этих двух чисел.
15. Преобразовать массив по следующему правилу: все отрицательные
элементы массива перенести в его начало, а все остальные - в конец, сохраняя исходное взаимное расположение как среди отрицательных, так и среди
39
всех остальных. Выполнить два варианта: воспользоваться вспомогательным массивом и не использовать вспомогательный массив.
16. Преобразовать массив по следующему правилу: все отрицательные
элементы массива перенести в его конец, все положительные – в начало, все
равные нулю - в середину, сохраняя исходное взаимное расположение как
среди отрицательных, так и среди всех остальных. Выполнить два варианта:
воспользоваться вспомогательным массивом и не использовать вспомогательный массив.
17. Найти коэффициенты к – го многочлена Чебышева (к=2, 3, … ,n).
Многочлены Чебышева определяются по формулами
T 1( x)  x;
Tn ( x)  2 xTn1 ( x)  Tn2 ( x),
T0 ( x)  1;
n=2, 3, …
18. Целое число М задано массивом своих двоичных цифр. Напечатать
массив двоичных цифр числа М+1.
Группа 5.
1.
Рациональное
алгебраическое
выражение
n
z   a i x ki ,
i 1
i=1,2,…,n задано своим массивом a[1..n]
k i  m,
коэффициентов a i и массивом
k[1..n] соответствующих показателей степеней k i . Привести в нём подобные
члены и сформировать массив коэффициентов полученного многочлена
Pm (x) (по возрастанию степеней x).
2. Из элементов массива A(2n) получить массивы B(n) и C(n) следующим образом. Выбрать из массива A два наиболее близких по значению элемента, меньший из них поместить в массив B, а больший- в массив C. Продолжить выбор из оставшихся элементов до полного заполнения массивов B
и C.
40
3. В массиве A(n) наименьший элемент поместить на первое место,
наименьший из оставшихся – на последнее место, следующий по величинена второе место, следующий- на предпоследнее и так далее – до середины
массива.
4. В массиве, все элементы которого различны, найти и удалить к
наименьших элементов, сдвигая элементы массива к началу и сохраняя порядок следования остальных элементов.
5. Переменной t присвоить значение true или false в зависимости от
того, есть ли среди элементов массива хотя бы одно число Фибоначчи.
6. Даны два массива целых чисел. Найти наименьшее среди тех элементов первого массива, которые не входят во второй массив (считать, что
хотя бы одно такое число имеется).
7. По массиву коэффициентов многочлена
Pn ( x)  p 0 x n  p1 x n 1  ...  p n 1 x  p n
получить R – массив коэффициентов многочлена (x-a)P(x);
8. По массиву коэффициентов многочлена
Pn ( x)  p 0 x n  p1 x n 1  ...  p n 1 x  p n
получить Q  массив коэффициентов многочлена P(x+a).
9. В массиве найти (напечатать) номера (индексы) локальных максимумов, т.е. таких a , что ai 1  ai  a . Найти сумму и произведение остальi
i 1
ных элементов.
10. Если массив А[1..n] упорядочен по неубыванию, изменить в нём
порядок следования элементов на обратный. В противном случае найти сумму элементов до первого нарушения упорядоченности.
11. Дан массив A[1..n] , содержащий повторяющиеся элементы. Все
неповторяющиеся элементы массива А, поместить в другой массив.
41
12. type element=0..99;
mnojestvo = array[element] of boolean;
var x, y, z : mnojestvo;
t : boolean;
Рассматривая массивы x,y,z как представления некоторых множеств из объектов типа element (x[k]=true, если элемент k принадлежит множеству x, и
x[k]=false иначе и т.п.), реализовать следующие операции над этими массивами-множествами:
а) переменной t присвоить значение true, если множество x является
подмножеством множества y, и значение false иначе;
б) z  x  y - пересечение множеств;
в) z  x  y -объединение множеств;
г) z=x\y - разность множеств (в z входят все элементы из x, которые не
входят в y).
ЛИТЕРАТУРА
1..Минакова Н.И. Методы программирования. Учебное пособие
/ Н.И.Минакова,
Е.С.
Невская,
Г.А.
Угольницкий,
А.А.
Чекулаева,
М.И. Чердынцева. – М.: Вузовская книга, 2000. –280 с. –ISBN 5-89522-038-X.
2. Невская Е.С., Чекулаева А.А., Чердынцева М.И. Искусство программирования. – М.: Вузовская книга, 2002. – 240 с. – ISBN 5-9502-0003-9.
42
3. Фаронов В.В. Турбо Паскаль 7.0. Начальный курс. – М.: «Нолидж»,
1997. – 616 с. ISBN 5-89251-012-3.
4. Епанешников А.М., Епанешников В.А. Программирование в среде
Turbo Pascal 7.0 – М.: «Диалог – МИФИ», 1996 – 288 с. – ISBN 5-86404-0290.
43
Скачать