Опубликован: 03.09.2010 | Доступ: свободный | Студентов: 2841 / 488 | Оценка: 4.11 / 3.69 | Длительность: 10:38:00
Лекция 5:

Работа с динамической памятью

< Лекция 4 || Лекция 5: 1234 || Лекция 6 >

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

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

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

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

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

type 
    pnode =  ^node;
    node = record
        d : word;                           { информационная }
        s : string;                         {          часть }
        p : pnode;          { указатель на следующий элемент }
     end;
ПРИМЕЧАНИЕ Обратите внимание, что тип указателя pnode на запись node определен раньше, чем сама запись. Это не противоречит принципу "использование только после описания", поскольку для описания переменной типа pnode информации вполне достаточно.

Рассмотрим принципы работы с основными динамическими структурами.

Стеки

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

Говорят, что стек реализует принцип обслуживания LIFO (last in — first out, последним пришел — первым обслужен). Стеки широко применяются в системном программном обеспечении, компиляторах, в различных рекурсивных алгоритмах.

Для работы со стеком используются две статические переменные: указатель на вершину стека и вспомогательный указатель.

var top, p : pnode;

Тип указателей должен соответствовать типу элементов стека.

В пример 5.1 приведена программа, которая формирует стек из пяти целых чисел и их текстового представления и выводит его на экран. Функция занесения в стек по традиции называется push, а функция выборки — pop.

program stack;
const n = 5;
type pnode = ^node;
     node = record                                { элемент стека }
         d : word;
         s : string;
         p : pnode;
     end;
var  top : pnode;                    { указатель на вершину стека }
     i   : word;
     s   : string;
const text : array [1 .. n] of string = ('one', 'two', 'three', 'four', 'five');
{ ------------------------------ занесение в стек --------------------------- }
function push(top : pnode; d : word; const s : string) : pnode;
var p : pnode;
begin
    new(p);
    p^.d := d; p^.s := s;  p^.p := top;
    push := p;
end;
{ ------------------------------ выборка из стека --------------------------- }
function pop(top : pnode; var d : word; var s : string) : pnode;
var p : pnode;
begin
    d := top^.d; s := top^.s;
    pop := top^.p;
    dispose(top);
end;
{ ------------------------------- главная программа ----------------------------- }
begin
    top := nil;
    for i := 1 to n do top := push(top, i, text[i]);        { занесение в стек: }
    while top <> nil do begin                               { выборка из стека: }
        top := pop(top, i, s);     writeln(i:2, s);
    end;
end.
Листинг 5.1. Использование стека

Очереди

Очередь — это динамическая структура данных, добавление элементов в которую выполняется в один конец, а выборка — из другого конца. Другие операции с очередью не определены. При выборке элемент исключается из очереди. Говорят, что очередь реализует принцип обслуживания FIFO (first in — first out, первым пришел — первым обслужен). В программировании очереди применяются очень широко — например, при моделировании, буферизованном вводе-выводе или диспетчеризации задач в операционной системе.

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

var beg, fin, p : pnode;

Тип указателей должен соответствовать типу элементов, из которых состоит очередь.

В пример 5.2 приведена программа, которая формирует очередь из пяти целых чисел и их текстового представления и выводит еe на экран. Для разнообразия операции с очередью оформлены в виде процедур. Процедура начального формирования называется first, помещения в конец очереди — add, а выборки — get.

program queue;
const n = 5;
type pnode = ^node;
     node = record                                            { элемент очереди }
         d : word; 
         s : string; 
         p : pnode;
     end;
var  beg, fin : pnode;                    { указатели на начало и конец очереди }
    i         : word; 
    s         : string;
const text : array [1 .. n] of string = ('one', 'two', 'three', 'four', 'five');
{ ------------------ начальное формирование очереди --------------------------- }
procedure first(var beg, fin : pnode; d : word; const s : string);
begin
    new(beg);
    beg^.d := d; beg^.s := s;  beg^.p := nil;
    fin := beg;
end;
{ --------------------- добавление элемента в конец --------------------------- }
procedure add(var fin : pnode; d : word; const s : string);
var p : pnode;
begin
    new(p);
    p^.d := d; p^.s := s;  p^.p := nil;
    fin^.p := p;
    fin := p;
end;
{ ---------------------- выборка элемента из начала --------------------------- }
procedure get(var beg : pnode; var d : word; var s : string);
var p : pnode;
begin
    d := beg^.d; s := beg^.s;
    p := beg; beg := beg^.p; 
    dispose(p);
end;
{ ------------------------------- главная программа --------------------------- }
begin
    { занесение в очередь: }
    first(beg, fin, 1, text[1]); 
    for i := 2 to 5 do add(fin, i, text[i]);
    { выборка из очереди: }
    while beg <> nil do begin
        get(beg, i, s);
        writeln(i:2, s);
    end;
end.
Листинг 5.2. Использование очереди
< Лекция 4 || Лекция 5: 1234 || Лекция 6 >
София Шишова
София Шишова

Я завершила экзамен 90 баллов на 5. Сертификат не заказала. Сейчас пытаюсь найти как его заказать. у меня указано экзамен пройден баллы оценка видно, а чтоб заказать сертификат нигде не видно.

Иван Огородников
Иван Огородников
Россия, Ханты-Мансийск
Иван Шихалев
Иван Шихалев
Россия, Екатеринбург