Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Полный+текст.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
245.76 Кб
Скачать

- 38 -

МОСКОВСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСИЙ УНИВЕРСИТЕТ

им. Н.Э.БАУМАНА

О.Б.Пащенко, н.Ю.Рязанова, м.В.Филиппов

Динамические структуры данных в С++

Учебно-методическое пособие по курсу «Информатика»

Москва

Издательство МГТУ им. Н.Э.Баумана

О.Б.Пащенко, н.Ю.Рязанова, м.В.Филиппов

Динамические структуры данных в С++

Учебно-методическое пособие посвящено работе с динамическими структурами данных, которые повсеместно используются при разработке программ. Расссмотрены особенности создания таких даных в среде прогамммирования Borland C++. Подробно описаны наиболее распространенные динамические структуры – однонаправленные и двунаправленные списки и деревья. Приведены многочисленные примеры, иллюстрирующие основные приемы работы со списками и деревьями.

Пособие предназначено для студентов 1-го курса, изущающих язык программирования С++.

УДК 681.3.06

ББК 22.18

ВВЕДЕНИЕ

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

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

Для описания динамических объектов в программе каждому такому объекту ставится в соответствие переменная – указатель, определяющая адрес объекта. По этому адресу осуществляется непосредственный доступ к этому объекту. Вся совокупность динамических объектов размещается в динамической области памяти, называемой “кучей”.

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

  1. Указатели , динамические переменные.

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

Необходимость в динамических структурах данных возникает в следующих случаях:

  1. Когда нужен массив или иная структура, размер которой изменяется в широких пределах.

  2. Когда в определённых частях программы требуется получить дополнительную память под переменные довольно большого размера.

  3. Когда размер переменной (массива или записи) превышает 64 килобайта.

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

Для организации динамических данных выделяется специальная область памяти, называемая "кучей" (heap), непрерывный участок определённого размера. При этом в специальной переменной сохраняется адрес начала этого участка. Такие переменные называют указателями (pointer).

В С++ указатели описываются следующим образом:

Имя_базового_типа * переменная;

где Имя_базового_типа – любой идентификатор типа.

Например:

Int *n; {указатель на целое значение}

Float *s; {указатель на на вещественную переменную}

Компилятор отводит под указатель четыре байта статической памяти.

Указатель может находиться в трёх состояниях:

  1. Неопределённое состояние в начале работы программы (указатель ещё не инициализирован).

  2. Содержит адрес какой-либо переменной (адрес размещения). Операция по заданию адреса указателю называется инициализацией указателя. Общий вид операции:

Указатель &переменная;

Примеры:

Float a, *p;

p &a;

Указатель p получает адрес переменной a.

  1. Содержит значения предопределённой константы NULL, такой указатель называют пустым, т.е. он не указывает ни на какую переменную и содержит "0" в каждом из четырёх байтов.

Указатели можно сравнивать друг с другом, присваивать указателю адрес другого указателя, передавать указатель как параметр.

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

int *P;

* P:= 1;

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

Для выделения динамической памяти используются специальные стандартные функции malloc() и calloc(), требующие подключения заголовочного файла alloc.h. Общий вид обращения к этим функциям:

Указатель =(тип_указателя*)malloc(n);

где n – размер выделяемой памяти в байтах, и

Указатель=(тип_указателя*)calloc(m,sizeof(тип_указателя));

где m – количество переменных, функция sizeof() определяет размер одной переменной заданного типа в байтах.

После завершения работы с динамическими переменными необходимо освободить соответствующий участок в “куче”, для чего используется функция free(). Обращение к этой функции имеет вид:

Free(имя_указателя).

Пример простых действий с указателями (программа инициализации массива):

Вариант 1. Обычные переменные. Вариант 2. Динамические переменные

Int Vect[10] ; int * Vec;

For( i =0; i< 10;i++) Vect (int*)calloc(10,sizeof(int));

Vect[i] = i for( i= 0;i<10;i++)

*(Vect+i) = i;

free(Vect);

В С++ предусмотрены также операторы выделения new и освобождения delete динамическо, треббующие подключения заголовочного файла iostream.h. Общий вид этих операторов:

Указатель = new тип_указателя;

Delete указатель;

Для динамического массива необходимо также указать количество его элементов следующим образом:

Указатель = new тип_указателя[n];

Delete [] указатель;

где n – количество элементов массива.

Примеры:

int P = new int;

float f = new float[10];

delete P;

delete [] f;