Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Структуры данных и алгоритмы. Учебное пособие.pdf
Скачиваний:
0
Добавлен:
15.08.2026
Размер:
1 Мб
Скачать

Структура данных очередь

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

Статическую очередь можно представить:

а) линейным массивом с двумя указателями: на начало и на конец очереди. Указатель на начало определяет позицию очереди (массива), откуда можно взять элемент, указатель на конец – позицию, куда кладем элемент:

struct queue

{

int beg, end; type data[N];

};

0

 

 

K

 

L

 

N - 1 beg

 

end

 

 

 

 

 

 

 

 

 

 

 

 

 

 

data

 

 

 

 

 

 

 

 

 

 

 

K

 

L

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

начало

конец

 

 

 

 

 

 

Задать очередь – это определить переменную типа queue:

queue q;

Для инициализации очереди достаточно определить начальное значение (пустое) указателя на начало и/или конец очереди. Для этого полю end дадим значение, не принадлежащее диапазону от 0 до N - 1 (а полю beg можно задать значение, указывающее на первый элемент

49

очереди – это упростит работу с указателями при включении элемента в очередь): например,

q.beg = 0; q.end = -1;

При включении элемента в очередь увеличивается на единицу значение указателя end, при взятии элемента из очереди значение указателя на начало beg.

Если поле end равно N - 1, то очередь полна. Освободившиеся после взятия элементов из очереди позиции не используются, поэтому возможно мнимое заполнение очереди. Если end равно N - 1 и beg равно 0 – очередь полна, а если beg больше 0, то очередь псевдополна (т. е. из очереди были взяты элементы и в начале массива есть свободные позиции). Обращение к элементу при взятии из очереди: q.data[q.beg], при занесении в очередь: q.data[q.end]. Если в очереди один элемент, то оба указателя показывают на него, т. е. их значения равны, если из очереди взять единственный элемент, она должна стать пустой;

б) линейным массивом с одним указателем на начало или на конец очереди, вторая позиция очереди фиксируется. Например, начало очереди – это первый элемент массива. В таком случае содержимое очереди сдвигается после каждого взятия из нее элемента и уменьшается на единицу поле end. Если поле beg равно 0, а поле end равно N - 1, то очередь полна:

struct queue

{

int end; type data[N];

};

 

0

 

K

 

N - 1

 

end

data

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

К

 

 

 

 

 

 

 

 

 

 

начало

конец

 

 

 

 

 

 

 

 

50

 

 

 

 

в) линейным массивом с двумя указателями (аналогично приведенному выше варианту а). При достижении конца массива (последнего элемента) очередь сдвигается на начало массива (к первому элементу), если есть свободные позиции в начале массива. Если поле beg равно 0, а поле end равно N - 1, то очередь полна;

г) циклическая очередь – линейный массив с двумя указателями (аналогично варианту а), в котором при достижении каким-либо указателем конца массива (последнего элемента) значение этого указателя очереди округляется по модулю N, где N – размер массива. Таким образом, в циклической очереди при достижении конца массива (end = N - 1) и наличии свободных позиций в начале (beg > 0), новый элемент помещается в массив на место с индексом 0, при этом указателю end присваивается значение 0.

Очередь будет полна, если поле end = N - 1, а поле beg = 0 или поле end = K, а beg = K + 1. Здесь 0 K N - 1.

0 1

 

 

 

 

 

N - 1

data

 

 

 

 

 

 

 

 

 

Э3

Э4

 

 

• • •

 

Э1

Э2

 

 

 

 

 

 

 

 

 

 

 

конец

 

 

начало

 

 

 

 

 

 

 

 

 

N - 2

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

beg end

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

а) линейным односвязным списком с двумя указателями:

struct list

{

type data;

list *next = NULL;

};

51

struct queue

{

list *beg = NULL, *end = NULL;

};

Задать динамическую очередь – это определить переменную типа queue:

queue q;

Для инициализации очереди достаточно указателю на начало q.beg и/или на конец q.end присвоить значение NULL, например: q.beg = NULL. При взятии единственного элемента из очереди она должна стать пустой;

 

 

 

 

начало

 

 

 

 

конец

 

 

 

 

 

 

 

 

 

 

 

 

beg

 

 

 

 

 

 

 

 

• • •

 

 

NULL

end

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

б) линейным двусвязным циклическим списком с одним указателем:

struct queue

{

type data;

queue *next = NULL, *prev = NULL;

}

• • •

52

Здесь начало (аналогично конец) очереди можно сделать как в начале, так и в конце списка. Задать динамическую очередь – это определить переменную-указатель на элемент типа queue:

queue *q;

Для инициализации очереди достаточно указателю q присвоить значение NULL:

q = NULL;

Основные операции над очередью аналогичны операциям со стеком (с учетом особенностей этой структуры ).

Примеры операций над статической очередью:

struct queue

{

int beg = 0, end = -1; char elem[N];

};

Очередь инициализируется следующим образом:

beg = 0; end = -1;

– операция положить элемент в очередь вида а:

int push(queue *q, char c)

{

if (q->end == n - 1) return 0;

q->end++;

53

q->elem[q->end] = c; return 1;

}

– операция взять элемент из очереди вида а:

int pop(queue *q, char *c)

{

if (q->end == -1) return 0;

*c = q->elem[q->beg]; if (q->beg == q->end)

{

q->beg = 0; q->end = -1;

}

else q->beg++;

return 1;

}

Примеры операций над динамической очередью:

struct list

{

char elem = 0; list *next = NULL;

};

struct queue

{

list *beg = NULL, *end = NULL;

};

54

Очередь инициализируется следующим образом:

beg = NULL;

– операция положить элемент в очередь

void push(queue *q, char c)

{

list *p = new list; p->elem = c; p->next = NULL;

if (q->beg == NULL) q->end = q->beg = p;

else

{

q->end->next = p; q->end = p;

}

}

– операция взять элемент из очереди

int pop(queue *q, char *c)

{

if (q->beg == NULL) return 0;

*c = q->beg->elem; list *p = q->beg; q->beg = q->beg->next; delete p;

return 1;

}

55

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]