Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Операции над односвязными списками.Содержание книги
Поиск на нашем сайте
Основных операций над списками - три.
1) Проход по списку, или переход от элемента к следующему. Как мы уже рассмотрели, это осуществляется с помощью присвоения типа q = q -> next;
2) Включение в список.
Пусть q, r - переменные типа elem*.
Предположи, что необходимо включить новый элемент в список после некоторого элемента, на который указывает q. Создадим этот новый элемент с помощью указателя r и занесем в его информационную часть число 19.
Такое включение осуществляется следующими операторами:
r = new elem; r->data = 19; r->next = q->next; q->next = r;
Проиллюстрируем это на рис. 5.
Рис. 5. Включение элемента в список 3) Исключение из списка.
Пусть теперь значением переменной q является указатель на некоторый, не последний, элемент списка и требуется исключить из списка элемент, следующий за ним. Это можно сделать так:
r = q->next; q->next = q->next->next; r->next = NULL;
Второе из приведенных присваиваний - это собственно исключение из списка, а первое выполняется для того, чтобы сохранить указатель на исключенный элемент, т.е. чтобы после исключения из списка он оставался доступным и с ним можно было бы выполнять некоторые действия. Например, вставить его на другое место или освободить занимаемую им память с помощью операции delete r.
Третье присваивание выполняется для того, чтобы сделать исключение окончательным, т.е. чтобы из исключенного элемента нельзя было бы попасть в список, из которого он исключен.
Реализация односвязных списков. Реализуем понятие списка через механизм классов.
// Файл "list.cpp" #include < iostream.h > #include < stdlib.h > typedef int ETYPE; struct elem { ETYPE data; elem * next; elem (ETYPE e, elem * n) { data = e; next = n;} }; class list { elem *h; // Адрес начала списка. public: list () { h = NULL; } ~list () {release (); } void create (ETYPE); // Добавляет элемент в начало списка. void release (); // Удаляет список. void insert (elem *q, ETYPE c); // Вставляет в список после с. void del0 () { // Удаляет первый элемент. elem *t = h; h = h->next; delete t;} void del (elem * q); // Удаляет элемент после q. void print (); // Распечатывает список. friend class iter; elem *first () { return h; } }; class iter { elem * current; public: iter (list & l) { current = l.h; } elem * operator ++ (); // Продвижение по списку. }; void list::create (ETYPE c){ h = new elem (с, h); } void list::insert (elem *q, ETYPE c){ q->next = new elem (c, q->next);} void list::del (elem *q){ if (q->next = = NULL){ cout << "Конец списка! "<< "Удаление следующего элемента невозможно!\n"; exit (1); } elem * r = q->next; q-> next = q->next->next; r->next = NULL; delete r;} elem* iter::operator ++ (){ /* Возвращает указатель на текущий элемент списка. Осуществляет продвижение по списку. Запоминает новый текущий элемент списка. */ if (current) { elem * tmp = current; current = current->next; return tmp; } return NULL; } void list::release () { iter t (*this); elem *p; while ((p = ++t)!= NULL) {h = h->next; delete p;} } void list::print () { iter t (*this); elem *p; while ((p = ++t)!= NULL) cout << p->data << " "; cout << '\n'; } // Конец файла list.cpp
Здесь реализован односвязный список. Это одна из простых моделей структур управления данным. Класс list, реализующий эту модель - представитель так называемых содержательных, или контейнерных типов. Класс iter создан специально для перебора элементов произвольного списка типа list. Объекты, предназначенные для перебора элементов внутри некоторого набора данных, обычно называют итераторами.
Приведем пример использования односвязного списка.
В файле int.dat расположена непустая последовательность целых чисел A1, A2,,..., An. Определить количество этих чисел n и вывести их в порядке возрастания.
Для решения этой задачи будем строить список, элементы которого упорядочены по возрастанию содержащихся в них целых чисел. Построение выполняется за n шагов. Первый шаг - это создание списка, состоящего из одного элемента, который содержит А1. Очевидно, этот список упорядочен. На i-м шаге (i = 2, 3, …, n) переходим от упорядоченного списка, элементы которого содержат числа А1,..., Ai-1, к упорядоченному списку, элементы которого содержат A1,…, Ai-1, Ai. Для выполнения такого перехода достаточно включить в список новый элемент, содержащий Аi. Его надо вставить непосредственно за последним по порядку элементом, содержащим число, меньшее, чем Аi.
Если же все элементы исходного списка содержат числа, не меньшие, чем Ai, то новый элемент нужно вставить в начало списка.
#include "list.cpp" #include < fstream.h >
void main () { ifstream file ("int.dat"); list lst; int i, n; file >> i; n = 1; lst.create (i); while (fil.peek ()!= EOF) { file >> i; n ++; iter tmp (lst); // Создаем объект-итератор для перебора // элементов списка lst. elem *p, *q; while ((p = ++tmp)!= NULL) if (p->data < i) q = p; else break; if (p = = lst.first ()) lst.create (i); else lst.insert (q, i); } cout <<" В файле чисел: " << n << "\n"; cout <<" Упорядоченный список:\n"; lst.print (); }
В последнем операторе if - else делается проверка p = = lst.first (). Это необходимо из-за того, что механизм вставки звена в начало списка и в список после указателя p различен. Различие возникает из-за того, что у первого элемента нет предыдущего. Иногда для единообразия в начало списка помещают так называемый заглавный элемент, который никогда не удаляют, и перед которым никогда не вставляют элемент. Его информационная часть обычно не используется.
|
||||
Последнее изменение этой страницы: 2016-08-15; просмотров: 583; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.116.89.70 (0.007 с.) |