Главная » Все файлы » Просмотр файлов из архивов » PDF-файлы » Язык Си. Реализация списков с помощью цепочек динамических объектов

Язык Си. Реализация списков с помощью цепочек динамических объектов (А.А. Вылиток - Лекции)

PDF-файл Язык Си. Реализация списков с помощью цепочек динамических объектов (А.А. Вылиток - Лекции) Операционные системы (37189): Лекции - 3 семестрЯзык Си. Реализация списков с помощью цепочек динамических объектов (А.А. Вылиток - Лекции) - PDF (37189) - СтудИзба2019-05-08СтудИзба

Описание файла

Файл "Язык Си. Реализация списков с помощью цепочек динамических объектов" внутри архива находится в папке "А.А. Вылиток - Лекции". PDF-файл из архива "А.А. Вылиток - Лекции", который расположен в категории "". Всё это находится в предмете "операционные системы" из 3 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .

Просмотр PDF-файла онлайн

Текст из PDF

А. А. ВылитокЯзык Си. Реализация списков с помощью цепочекдинамических объектовВ языке Си нет встроенных типов данных и операций для работы со списками.Программируя на языке Паскаль (в котором также нет стандартных типов для списков),мы представляли списки цепочками динамических объектов. Аналогичная реализациявозможна и в языке Си.1. Стандартные функции для работы с динамической памятьюДля работы с динамическим объектами в Си есть аналоги паскалевскиxпроцедур new и dispose — это функции стандартной библиотеки malloc и free. Для ихиспользования нужно включить в программу заголовочный файл ‹stdlib.h›. В этомфайле также вводится обозначение NULL для пустого (нулевого) указателя.void *malloc (size_t size)malloc возвращает указатель на место в памяти для объекта размера size.Выделенная память не инициализируется.

Если память отвести не удалось, торезультат работы функции — NULL. (Тип size_t — это беззнаковый целый тип,определяемый в файле ‹stddef.h›, результат операции sizeof имеет тип size_t). Какправило, обобщенный указатель, возвращаемый этой функцией, явноприводится к указателю на тип данных. Например, создать динамическуюпеременную типа double и присвоить значение, возвращаемое malloc,переменной dp — указателю на double, можно с помощью выраженияdp = (double*) malloc (sizeof (double)).Созданная динамическая переменная существует вплоть до завершения работыпрограммы, или до момента, когда она явно уничтожается с помощью функцииfree.void free (void *p)free освобождает область памяти, на которую указывает p; если p равно NULL,то функция ничего не делает.

Значение p должно указывать на область памяти,ранее выделенную с помощью функций malloc или calloc После освобожденияпамяти результат разыменования указателя p непредсказуем; результат такженепредсказуем при попытке повторного обращения к free c этим же указателем.Приведем описание еще одной функции распределения памяти в Си. Ею удобнопользоваться, когда нужно разместить массив в динамической памяти.void *calloc (size_t nobj, size_t size)calloc возвращает указатель на место в памяти, отведенное для массива nobjобъектов, каждый из которых имеет размер size. Выделенная область памятипобитово обнуляется.

(Заметим, что это не всегда равнозначно присваиваниюнулевых значений соответствующим элементам массива. В некоторыхреализациях в побитовом представлении нулевого указателя или значения 0.0 сплавающей точкой могут быть ненулевые биты). Если память отвести неудалось, то результат работы функции — NULL.2. Представление списков цепочками звеньевДля хранения отдельного элемента списка создается динамический объект —структура с двумя членами, называемая звеном.

В одном из членов (информационном)располагается сам элемент, а другой член содержит указатель на звено, содержащееследующий элемент списка, или пустой указатель, если следующего элемента нет. Спомощью указателей звенья как бы сцеплены в цепочку. Зная указатель на первое звеноможно добраться и до остальных звеньев, то есть указатель на первое звено задаёт весьсписок. Пустой список представляется пустым указателем.Приведём соответствующие описания на языке Си. В качестве типа элементасписка выбран тип char. Списки с элементами других типов описываются аналогично.#include <stdio.h>#include <stdlib.h>typedef struct Node *link;typedef char elemtype;/* указатель на звено/* тип элемента списка*/*/typedef struct Node {elemtype elem;link next;} node;/* звено состоит из двух полей:/* – элемент списка,/* – указатель на следующее звено*/*/*/typedef link list;/* список задается указателем на звено */list lst;/* переменная типа список*/Переменная lst представляет в программе список.Обратите внимание на то, что в описании типа link используется незавершенныйтип struct Node.

Описание указателей на незавершенный тип допустимо в Си. Тип structNode становится завершенным при описании типа node. Тип list объявляетсясинонимом типа link.В примерах мы будем обозначать обсуждаемые списки в виде кортежей, как этопринято в математике. Так, конструкция 〈'a', 'b', 'c'〉 означает список из трех элементов.Первый элемент в этом списке — 'a', второй — 'b', третий — 'c'. Пустой списоквыглядит так 〈 〉.Пример. Список символов 〈'a', 'b', 'c'〉, представленный цепочкой звеньев,изображается следующим образом (в переменной lst — указатель на первое звено):lst'a''b''c'NULLПри этом в программе выражение lst означает указатель на первое звено в цепочке; *lstозначает само первое звено, (*lst).elem — первый элемент списка. По-другому первыйэлемент обозначается с помощью операции доступа к члену структуры через указатель:lst−>elem.

Выражение lst−>next означает указатель на второе звено. Далее,*lst−>next— само второе звено,lst−>next−>elem— второй элемент списка,lst−>next−>next— указатель на третье звено,*lst–>next−>next— само третье звено,lst−>next−>next−>elem — третий элемент списка,lst−>next−>next−>next — пустой указатель (конец списка).Выражение lst имеет и другой смысл. Оно обозначает список в программе,поскольку, зная указатель на первое звено, мы имеем доступ ко всем остальнымзвеньям, т.е. «знаем» весь список. С этой точки зрения выражение lst−>next в нашемпримере обозначает список1 〈'b', 'c'〉, а выражение lst−>next−>next−>next — пустойсписок.Заметим, что соседние звенья цепочки располагаются в оперативной памятипроизвольно относительно друг друга, в отличие от соседних компонент массива,всегда занимающих смежные участки памяти.

Такое расположение звеньев облегчаетоперации вставки и удаления, так как нет необходимости перемещать элементы, как этобыло бы в случае реализации списков массивами. Поясним это на примерах.Пусть из списка 〈'a', 'b', 'c'〉, представленного в программе переменной lst,требуется удалить второй элемент. Для этого достаточно исключить из цепочки второезвено – «носитель» второго элемента. Изменим указатель в поле next первого звена:lst−>next = lst−>next−>next.Теперь после первого звена в цепочке идёт звено, содержащее элемент 'c'.Получился список 〈'a', 'c'〉. Чтобы исключённое звено не занимало места в памяти, егоследует уничтожить с помощью функции free, предварительно запомнив указатель нанего во вспомогательной переменной q.

Итак, окончательное решение таково:q = lst−>next; lst−>next = lst−>next−>next; free(q);Покажем на рисунке происходящие после каждого действия изменения.1По правилам языка Си имена link и list обозначают один и тот же тип, и мы вправе рассматриватьlst−>next как переменную типа list, означающую список.q = lst–>next;'a'lst'b''c'NULL'c'NULLqlst–>next = lst–>next–>next;'a'lst'b'qfree(q);lst'a''c'NULLqПусть теперь требуется вставить 'd' после первого элемента списка 〈'a', 'c'〉.Решение состоит из двух этапов.

Во-первых, необходимо создать «носитель» — звенодля хранения вставляемого элемента, и занести этот элемент в поле elem «носителя».Во-вторых, путём изменения указателей включить созданное звено в цепочку послепервого звена. Первый этап реализуется фрагментомq = (link) malloc(sizeof (node)); q−>elem = 'd';где q — вспомогательная переменная типа link. Фрагментq−>next = lst−>next; lst−>next = q;осуществляет второй этап вставки.

Следующий рисунок иллюстрирует этапы вставки.q = (link) malloc(sizeof (node)); q−>elem = 'd';lstq'a''c'NULL'd'q–>next = lst–>next; lst–>next = q;lstq'a''c'NULL'd'Из примеров видно, что длина цепочки (количество звеньев в ней) можетдинамически изменяться, т.е. изменяться в процессе выполнения программы. Подобноцепочкам можно сконструировать и более сложные структуры, в которых объектысвязаны между собой с помощью указателей. Такого рода структуры данныхназываются динамическими.3.

Некоторые операции со спискамиПриведём описание нескольких функций для работы со списками.Создание спискаФункция create (s) создает и возвращает в качестве результата список изсимволов параметра-строки s.list create (char *s){int i;link cur;/* указатель на текущее звено спискаlist res;/* возвращаемый списокif ( *s == '\0' ) return NULL; /* если строка пуста, то возвращаемпустой списокиначе строим непустой списокres = cur = ( link ) malloc ( sizeof (node)); /* создаем первое звено спискаcur−>elem = *s++;/* заполняем поле elem и переходим к*/*/*/*/следующему элементу строки*/while ( *s != '\0' ) {/* пока не конец строки*/cur = cur−>next = (list) malloc( sizeof (node)); /* присоединяем в конецсписка новое звено*/cur−>elem = *s++;/* помещаем в новое звено очередной элементи переходим к следующему элементустроки*/}cur−>next = NULL;/* последнее звено должно иметь нулевойуказатель*/return res;/* возвращаем список (указатель на первоезвено)*/}Условие *s != '\0' можно заменить на *s, а *s == '\0' заменить на !*s .Печать элементов списка/* print: печатает в стандартный выходной поток элементы спискаvoid print ( list p ){while ( p != NULL ) {/*пока не конец списка,putchar ( p−>elem ); /*печатаем очередной элементp = p−>next;/*и переходим к следующему звену}putchar ( '\n' );}*/*/*/*/Заголовок while-цикла можно было записать как while ( p ).

Однако, выражениеp != NULL более информативно — по нему можно догадаться, что p скорее всегоявляется указателем, даже не видя его описания.Опишем функцию печати, используя цикл for./* print: печать в стандартный выходной поток элементов спискаверсия с циклом forvoid print ( list p ){for ( ; p ; p = p−>next )/* пока не конец списка, т.е. p!=NULL/* печатаем очередной элементputchar ( p−>elem );и переходим к следующему звенуputchar( '\n' ) ;}*/*/*/Здесь мы использовали p в качестве условия продолжения цикла, а не p != NULL,так как рядом стоящее p –>next (в третьем выражении заголовка for), говорит о том,что p — указатель.Вычисление свойств и характеристик списков/* is_empty: возвращает 1, если список пуст, иначе — 0int is_empty ( list ls){return ls == NULL;}*//* count: подсчитывает число вхождений элемента elem в список lsint count ( list ls, elemtype elem){int c = 0; /* счетчик вхожденийfor ( ; ls ; ls = ls−>next )if ( ls−>elem == elem ) c++ ;return c;}*/*/Можно обойтись без условного оператора в теле цикла for, записав вместо негооператор-выражение:c += ( ls−>elem == elem);/* length: вычисляет длину списка lsint length ( list ls ){int c;for ( c = 0; lst ; lst = lst−>next, c++);return c;}*/Теперь опишем рекурсивную версию функции length.

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5224
Авторов
на СтудИзбе
428
Средний доход
с одного платного файла
Обучение Подробнее