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

Метод_материалы / Учебники / Программирование_С

.pdf
Скачиваний:
66
Добавлен:
16.03.2016
Размер:
2.31 Mб
Скачать

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

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

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

Однако при таком представлении исключается возможность идентификации заголовка списка по наличию –1 в поле данных. При новом представлении элемент заголовка может содержать в этом поле, например, число 5, что является разрешенным значением и для любого другого элемента списка. Эту проблему можно решить несколькими способами. Мы остановимся на варианте, который предполагает поддержание дополнительного внешнего указателя pt_head на заголовок списка. Дополнительный указатель указывает на заголовок, если его значение равно значению основного внешнего указателя (который фиксирован). В противном случае элемент с указателем pt_head не является заголовком.

Используя рассмотренное выше представление, мы можем написать функцию, которая сравнивает абсолютные значения двух целых чисел, представленных двунаправленными связанными списками. Выходная переменная функции устанавливается: в 1, если первое число имеет большее абсолютное значение; в – 1, если второе число имеет большее абсолютное значение; в 0, если числа равны.

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

3.2.3.3. Моделирование с применением связанных списков

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

221

ситуации. Таким образом, можно проанализировать ситуацию из реального мира без фактического наблюдения за ней.

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

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

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

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

Напишем программу, имитирующую действия посетителей. По прибытию посетителя с ним связаны два известных факта — время прибытия и продолжительность выполнения банковской операции (предполагается, что прибывший посетитель знает, с какой целью он пришел). Каждому посетителю из входного потока программы сопоставляется строка с двумя числами — время прибытия (в минутах с момента открытия банка) и время, необходимое для выполнения операции (также в минутах). Строки упорядочены по возрастанию времени прибытия. Поток входных данных завершается строкой, в которой время прибытия и время выполнения операции равны нулю.

Четыре очереди в банке представлены четырьмя очередями в программе. Каждый элемент очереди имитирует посетителя, стоящего в очереди, а элемент в начале очереди имитирует посетителя, обслуживаемого в данный момент кассиром. Что вызывает изменение состояния очереди? Либо в банк заходит новый посетитель и в этом случае к одной из очередей добавляется дополнительный элемент, либо посетитель, стоящий первым в одной из очередей, завершает соответствующие действия и покидает очередь. Следовательно, возможны пять событий, вызывающие изменение состояния очереди (вход в банк нового посетителя и четыре возможные ситуации выхода посетителя из очереди).

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

222

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

Элемент, отражающий прибытие посетителя, называется элементом прибытия, а элемент, отражающий уход посетителя из банка, — элементом отправления. В процессе моделирования в каждый момент времени необходимо знать, какое событие произойдет следующим. По этой причине список событий упорядочен по возрастанию времени таким образом, что первый элемент списка событий отражает событие, происходящее первым.

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

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

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

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

223

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

Разработайте необходимые структуры данных и напишите программу моделирования работы банка.

3.2.3.3.2. Моделирование работы фабрики Рассмотрим фабрику, изготавливающую изделия из более мелких узлов.

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

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

3.2.3.3.3. Моделирование работы фабрики — 2 Напишите программу, которая считывает набор списков, созданных

предыдущей задачей. Эта программа печатает для каждой неэлементарной детали список всех элементарных деталей, из которых она состоит.

3.2.3.4. Другие задачи на линейные списки

3.2.3.4.1. Очереди и стеки, находящиеся в одном массиве Напишите набор программ, работающих с несколькими очередями и стеками,

находящимися в одном массиве.

Напишите программы, выполняющие следующие операции.

3.2.3.4.2.Добавление элемента к концу списка

3.2.3.4.3.Сцепление двух списков

3.2.3.4.4.Освобождение всех элементов в списке

3.2.3.4.5.Инвертирование списка

при котором первый элемент становится последним.

3.2.3.4.6.Удаление последнего элемента из списка

3.2.3.4.7.Удаление n-го элемента из списка

3.2.3.4.8.Объединение двух упорядоченных списков в один упорядоченный список.

3.2.3.4.9.Создание объединения списков

представляющего собой (по операции ИЛИ) объединение элементов двух списков.

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

224

3.2.3.4.11.Вставка элемента после n-го элемента списка

3.2.3.4.12.Удаление из списка каждого второго элемента

3.2.3.4.13.Размещение элементов списка в возрастающем порядке

3.2.3.4.14.Вычисление суммы целочисленных значений элементов списка.

3.2.3.4.15.Вычисление числа элементов в списке

3.2.3.4.16.Перемещение заданного элемента списка

на n позиций вперед по списку.

3.2.3.4.17.Создание копии списка

3.2.3.4.18.Определение среднего арифметического

программа находит среднее арифметическое элементов непустого списка. 3.2.3.4.19. Замена в списке всех вхождений одного числа на другое программа заменяет в списке все вхождения одного числа на другое, оба

заданны.

3.2.3.4.20. Замена в списке мест первого и последнего элементов Программа меняет местами первый и последний элементы непустого списка.

3.2.3.4.21.Проверка упорядоченности элементов списка Программа проверяет, упорядочены ли элементы списка.

3.2.3.4.22.Нахождение суммы последнего и предпоследнего элементов

списка Программа находит сумму последнего и предпоследнего элементов списка,

содержащего не менее двух элементов.

3.2.3.4.23.Построение двух списков из исходного

Программа по исходному списку строит два новых списка: первый — из положительных элементов и второй — из остальных элементов списка.

3.2.3.4.24. Вставка в список заданного элемента за каждым вхождением другого

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

3.2.3.4.25. Вставка нового элемента в неупорядоченный список Программа вставляет в список новый элемент перед первым вхождением

другого элемента, если этот элемент входит в список. 3.2.3.4.26. Вставка двух новых элементов в список

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

3.2.3.4.27. Удаление из списка второго элемента Программа удаляет из списка второй элемент, если такой есть.

3.2.3.4.28. Удаление из списка элемента за вхождением после заданного Программа удаляет из списка за каждым вхождением заданного элемента

один элемент, если такой есть и он отличен от заданного. 3.2.3.4.29. Удаление из списка первого отрицательного элемента

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

225

3.2.3.4.31.Проверка на равенство двух списков Программа проверяет на равенство два списка

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

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

3.2.3.4.34.Построение двух списков из исходного

Программа переносит в конец непустого списка его первый элемент. 3.2.3.4.35. Построение двух списков из исходного Программа переносит в начало непустого списка его последний элемент. 3.2.3.4.36. Построение двух списков из исходного

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

элементы другого списка, если заданный элемент входит в первый список. 3.2.3.4.38. Построение двух списков из исходного Программа в списке из каждой группы подряд идущих равных элементов

оставляет только один.

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

элементов.

3.2.3.4.40. Смена мест n-го и k-го элементов списка

Напишите программу, меняющую местами n-й и k-й элементы списка. 3.2.3.4.41. Помещение элементов списка в другой список Напишите программу, помещающую элементы списка, начиная с элемента

n, общим числом k в другой список, начиная с позиции i в нем. Напечатайте сообщение об ошибке при некорректной операции.

3.2.3.4.42. Возвращение указателя на элемент списка Напишите программу , воспринимающую указатель на список целых чисел и

целое число X и возвращающую указатель на элемент X, если он существует, а в противном случае нулевой указатель.

3.2.3.4.43. Нахождение дубликатов в списке чисел Разработайте алгоритм для нахождения дубликатов в списке чисел, не

использующий бинарное дерево. Напишите программу. 3.2.3.4.44. Некоторые задачи со списками слов -1

Напишите программу, подсчитывающую количество слов списка, которые а) начинаются и оканчиваются одной и той же литерой, б) начинаются с той же литеры, что и следующее слово, в) совпадают с последним словом.

3.2.3.4.45. Некоторые задачи со списками слов –2 Напишите программу, которая:

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

б) печатает текст из первых букв всех непустых слов списка,

226

в) удаляет из непустых слов списка их первые буквы, г) печатает все непустые слова списка,

д) определяет количество слов в непустом списке, отличных от последнего. 3.2.3.4.46. Многочлен

P(x) = an x n + an1 x n1 +... + a1 x + a0

с целыми коэффициентами можно представить в виде списка (рис. 3.9, а), причем если ai = 0 , то соответствующее звено не включается в список (на рис. 3.9, б

показано представление многочлена S(x) = 52x40 3x8 + x .

Описать списочный тип данных, соответствующий такому представлению многочленов, и определить следующие функции для работы с этими спискамимногочленами:

а) функцию, проверяющую неравенство многочленов р и q;

б) функцию, вычисляющую значение многочлена р в целочисленной точке х; в) функцию, которая строит многочлен р — производную многочлена q;

г) функцию, которая строит многочлен р сумму многочленов q и r;

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

Рис. 3.9. Представление многочлена в виде списка

3.2.3.4.47. Задачи с двунаправленным циклическим списком —1. Напишите программу, которая:

а) подсчитывает количество элементов списка, у которых равные «соседи»;

227

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

в) переставляет в обратном порядке все элементы между первым и последним вхождениями заданного элемента, если этот элемент входит в список не менее двух раз;

г) удаляет из списка первый отрицательный элемент, если такой есть; 3.2.3.4.48. Задачи с двунаправленным циклическим списком — 2 а) из списка, содержащего не менее двух элементов, удаляет все элементы, у

которых одинаковые «соседи» (первый и последний элементы считать соседями); б) добавляет в конец списка новый элемент; в) в списке удваивает каждое вхождение заданного элемента;

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

3.2.4.Задачи на деревьях

3.2.4.1.Поиск всех дубликатов в списке чисел.

Простейший способ выполнения этой задачи состоит в сравнении каждого числа с последующими, но для этого требуется большое число сравнений. Путем использования бинарного дерева число сравнений может быть уменьшено. Считывается первое число и помещается в корень, затем из входного потока формируется дерево бинарного поиска (как мы видели ранее, содержащее любое число ровно один раз). При этом для каждого последующего числа из потока производится попытка добавить его в ДБП. Если на каком — то шаге этого процесса новое значение совпадает со значением текущего узла, то это дубликат и следует напечатать эту информацию. Процесс просмотра/добавления для этого числа прекращается.

Алгоритм:

//прочитать первое число и поместить его в бинарное дерево, состоящее из одного узла

{

read number;

tree = IniTree (number);

while (//еще есть числа на вводе)

{

read number; q=tree; p=tree;

while (q!=NULLl) and (number!=data.p)

{

p = q;

if (number<data.p) q=left.p

228

else q=right.p);

}

if (number==data.p)

printf //number есть дубликат; else

if (number<data.p) setleft (p, number);

else

setright(p, number);

}

}

Напишите программу, реализующую этот алгоритм.

3.2.4.2. Представление арифметических выражений

Представим выражение, содержащего операнды и бинарные (не унарные) операторы, в виде строго бинарного дерева. Корень такого бинарного дерева содержит оператор, который должен быть применен к результату вычисления выражений, представленных левым и правым поддеревьями. Узел, представляющий оператор, имеет два непустых поддерева, а узел, представляющий операнд — два пустых поддерева. На рис. 3.10 показаны примеры выражений и их представления в виде деревьев. Отметьте, что при этом не требуется скобок, так как структура дерева определяет порядок операций.

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

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

Прохождение в симметричном порядке, очевидно, должно дать инфиксную форму выражения. Действительно, при прохождении бинарного дерева рис. 3.10, а получается инфиксное выражение А+В*С. Однако бинарное дерево рассмотренного типа не содержит скобок, и поэтому нельзя отменить обычные правила старшинства операций, то есть инфиксная форма может получиться некорректной.

Напишите программу, которая позволяет вручную сформировать рассмотренное ДБП и затем записывает соответствующее выражение во всех трех формах.

229

Рис. 3.10. Представление арифметических выражений в виде бинарных деревьев

3.2.4.3. Представление предметного указателя

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

Разработайте структуру данных для представления такого предметного указателя и напишите следующую программу для печати предметного указателя по входным данным. Каждая входная строка начинается либо с символа М (основной термин), либо с символа S (подтермин). Строка с символом М содержит вслед за ним основной термин и число n (возможно, равное 0), за которым следуют n номеров страниц, на которых встречается основной термин. Строка с символом S строится аналогично, за исключением того, что она содержит не основной термин, а подтермин.

Входные строки не появляются на вводе в каком-либо конкретном порядке: единственное условие: каждый подтермин считается подтермином последнего, предшествующего основного термина. Для одного основного

230

Соседние файлы в папке Учебники