Материал: 695_Poletajkin_A.N._Uchebno-metodicheskoe_posobie_Realizatsija_zhiznennogo_ch.1_

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

б) вставка нового узла в конец

Рис. 17. Графическое представление операции InsertAtBack

Метод RemoveFromFront удаляет первый узел из списка и возвращает ссылку на удаленные данные. Метод выдает исключение EmptyListException, если программист пытается удалить узел из пустого списка. В противном случае метод возвращает ссылку на удаленные данные. Данный метод состоит из четырех шагов (показаны на рисунке 18):

1.Присвоение firstNode.Data (удаляемые из списка данные) ссылке removeItem.

2.Если объекты, на которые ссылаются элементы firstNode и lastNode, являются одним объектом, тогда список имеет только один элемент перед попыткой удаления. В этом случае метод задает значение null элементам firstNode и lastNode для вывода из потока (удаления) узла из списка (список остается пустым).

3.При наличии в списке более одного узла до операции удаления метод оставляет ссылку lastNode как есть и просто присваивает элемент firstNode.Next ссылке firstNode. Таким образом, firstNode делает ссылку на узел, который был вторым до вызова метода RemoveFromFront.

4.Возвращение ссылки removeItem.

На рис. 18, а показан список до операции удаления, а на рис. 18, б – фактические манипуляции ссылкой.

а) список до удаления первого узла

61

б) изменение ссылки

Рис. 18. Графическое представление операции RemoveFromFront.

Метод RemoveFromBack удаляет последний узел списка и возвращает ссылку на удаленные данные. Данный метод выбрасывает исключение EmptyListException, если программа делает попытку удаления узла из пустого списка. Метод состоит из нескольких шагов (рисунок 19):

1.Присвоить lastNode.Data (удаляемые из списка данные) ссылку removeItem.

2.Если объекты, на которые ссылаются firstNode и lastNode, являются одним объектом, тогда список имеет только один элемент перед попыткой удаления. В этом случае метод задает элементам firstNode и lastNode значение null для удаления узла из списка (список остается пустым).

3.Если перед операцией удаления список содержит более одного узла, создать ссылку current класса ListNode и присвоить ей элемент firstNode.

4."Проход списка" ссылкой current до ссылки на предпоследний узел списка: цикл while присваивает current.Next ссылке current, пока current.Next не равно lastNode.

5.После определения местоположения предпоследнего узла присвоить current элементу lastNode для удаления из списка последнего узла.

6.Задать значение null свойству current.Next в новом последнем узле списка для обеспечения надлежащего завершения списка.

7.Возвратить ссылку removeItem.

На рисунке 19, а представлен список до операции удаления, на рисунке 19, б — фактические манипуляции ссылкой.

62

а) список до удаления последнего элемента

б) изменение ссылки

Рис. 19. Графическое представление операции RemoveFromBack

Работа с указанными записями.

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

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

Метод RemoveFrom(int n)

Метод RemoveFrom удаляет указанную запись из списка. Данный метод также выбрасывает исключение EmptyListException, если программа делает попытку удаления узла из пустого списка.

1.Присвоить RemuveItem данные первой записи.

2.Если первый узел является последним, то очистить список и выйти.

3.Если «выбран» первый элемент, то следующий элемент сделать первым, то есть удалить первый элемент.

63

4.Во всех остальных случаях перейти к элементу, предшествующему «выбранному».

5.Сохранить данные следующего за текущим («выбранного») элемента.

6.Если «выбранный» элемент является последним, то последним узлом сделать текущий и «заглушить» список (удалить последний элемент).

7.Если «выбранный» элемент не последний, то ссылку next предыдущего элемента установить на элемент, следующий за «выбранным».

8.Возвратить удаленные данные.

Метод EditRow(PData newItem, int posItem)

Метод RemoveFrom заменяет данные на статическую запись PData в указанной записи списка. Здесь метод выполняет поиск указанной записи списка, сохраняет ее данные, задает их как аргумент newItem и возвращает сохраненную запись.

Виртуальный вывод на консоль. Метод Print(string s, bool pak)

Метод Print сначала определяет степень заполнения списка. Если список пуст, тогда метод Print отображает строку, содержащую слово "Пустой" и название списка (name), после чего возвращает 0 и передает управление в вызывающий метод. В противном случае метод Print выдает данные в списке.

Вывод. Метод распечатывает строку s и название name. Затем создается ссылка current класса ListNode, которая инициализируется элементом firstNode. Пока ссылка current не равна null, в списке имеется несколько элементов. Следовательно, метод распечатывает элемент current.Data, после чего присваивает current.Next ссылке current для перехода к следующему узлу списка. После выполнения цикла, если pak истинно, то программа приостанавливается до нажатия любой клавиши. Метод возвращает количество узлов в списке.

Виртуальный вывод в файл. Метод Printf(string s)

Метод Printf также проверяет список на пустоту. Если список пуст, тогда метод отображает строку, что "Список с именем (name) пуст" и название списка, после чего возвращает false и передает управление в вызывающий метод. В противном случае метод Printf выводит данные в файл data(s).txt, где s

– аргумент метода, представляющий собой следующий номер по порядку файлов формата «data*.txt» в исследуемой директории «D:\».

Для вывода в данный файл создается ссылка на пишущий поток. При помощи стандартного его метода WriteLine производится вывод названия списка и его элементов, подобно выводу в методе Print.

После цикла файл закрывается и возвращается true, означая успех произведенной операции вывода.

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

64

6.4. Организация пользовательского интерфейса

Организацию интерфейса пользователя рассмотрим на примере следующего текстового меню:

1.Создание нового списка

2.Загрузка списка из файла

3.Модификация списка...

3.1.добавление записи в начало списка

3.2.добавление записи в конец списка

3.3.изменение выбранной записи...

3.4.удаление выбранной записи...

3.5.удаление первой записи

3.6.удаление последней записи

3.7.возврат в главное меню

4.Специальные операции с записями…

4.1.операция1

4.2.операция2

4.3.возврат в главное меню

5.Статистическая обработка данных из списка

6.Сохранение списка

7.Выход в Windows

Простейший интерфейс для выбора одного элемента из нескольких может быть реализован в теле двойного цикла (см. листинг 6) в три этапа:

1.Вывод на консоль инструкции пользователю, включающей в себя приглашение к выбору, перечень возможных вариантов и указания по управлению. В данном примере операции 1 – 2 осуществляют создание списка, а операции 3 – 6 связаны с обработкой существующего списка, поэтому во внешнем цикле объявлена переменная k0, которая инициализируется значением 3, если объект list, созданный пустым в начале метода Main, так и остался пустым, и значением 7 в случае наличия данных в объекте list.

2.Управление осуществляется чаще всего посредством клавиатуры. Для этого во внутреннем цикле после очистки консоли и вывода инструкции запрашивается чтение целочисленной величины в переменную item. При ввода чего-либо нецелочисленного выводится сообщение и происходит переход к следующей итерации. Выход из внутреннего цикла осуществляется, если item находится в промежутке между 1 и k0, и в этом случае в переменной item содержится номер выбранного действия.

Для выбора пункта меню может быть реализовано перемещение указателя по пунктам, что делается с помощью обработки нажатия клавиш со стрелками, а также Tab, Esc и Enter, во внешнем цикле.

3.Обработка результатов выполняется с использованием структурного оператора switch case, который размещается во внешнем цикле интерфейса сразу после завершения внутреннего (см. листинг 6). После завершения оператора switch проверяется значение item,

65