Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
методичка по программированию СУА.doc
Скачиваний:
15
Добавлен:
11.11.2019
Размер:
1.3 Mб
Скачать

5.11.3. Объединения

Особым видом структур данных является объединение. Определение объединения напоминает определение структуры, только вместо ключевого слова struct используется union. В отличие от структуры, все атрибуты объединения располагаются по одному адресу. Под объединение выделяется столько памяти, сколько нужно для хранения наибольшего атрибута объединения. Объединения применяются в тех случаях, когда в один момент времени используется только один атрибут объединения и, прежде всего, для экономии памяти. Предположим, нам нужно определить структуру, которая хранит "универсальное" число, т.е. число одного из предопределенных типов, и признак типа. Это можно сделать следующим образом:

struct Value {

enum NumberType { ShortType, LongType,

DoubleType };

NumberType type;

short sx; // если type равен ShortType

long lx; // если type равен LongType

double dx; // если type равен DoubleType

};

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

Value shortVal;

shortVal.type = Value::ShortType;

shortVal.sx = 15;

Хотя память выделяется под все три атрибута sx, lx и dx, реально используется только один из них. Сэкономить память можно, используя объединение:

struct Value {

enum NumberType { ShortType, LongType,

DoubleType };

NumberType type;

union number {

short sx; // если type равен ShortType

long lx; // если type равен LongType

double dx; // если type равен DoubleType

} val;

};

Теперь память выделена только для максимального из этих трех атрибутов (в данном случае dx). Однако и обращаться с объединением надо осторожно. Поскольку все три атрибута делят одну и ту же область памяти, изменение одного из них означает изменение всех остальных. На рисунке поясняется выделение памяти под объединение. В обоих случаях мы предполагаем, что структура расположена по адресу 1000. Объединение располагает все три своих атрибута по одному и тому же адресу.

Рис. 5.3 – Использование памяти в объединениях.

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

5.12. Динамические структуры данных

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

К динамическим структурам данных относятся различные виды списков. Обычно элемент списка содержит смысловую часть (собственно хранимые данные) и ссылку на другой или другие элементы списка. Для программирования списков используют структуры или классы. Различают односвязные списки, двусвязные списки и деревья.

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

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

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

Списки получили значительное распространение при работе с данными.