Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Технологии разработки объектно-ориентированных программ на язык C++. Основы структурного программирования на алгоритмическом языке C++

.pdf
Скачиваний:
4
Добавлен:
12.11.2023
Размер:
3.17 Mб
Скачать

 

из массива

qu.push(mas[i]);

 

cout << "Очередь после добавления: ";

print(qu);

// Печать очереди

Подробнее: в цикле (строки 1–4) все элементы очереди переносятся в массив. Затем добавляются первые три элемента (строки 5–6) из массива, после добавляются три новых элемента (строки 7–8) и оставшиеся три из массива (строки 9–10). Очередь печатается.

Пример выполнения работы программы:

5 7 5 10 5 4 3 10 1 4

Очередь после удаления: 5 10 5 4 3 10 Очередь после добавления: 5 10 5 2 9 6 4 3 10

14.12. Реализация очереди через структуры

Рассмотрим решение задачи в гл. 3, реализованное через структуры.

Структура очередь имеет минимум два поля: ключ (значение, которое будет хранить элемент очереди) и указатель на следующий элемент очереди.

struct Queue { int data; Queue* next;

};

Данная структура имеет имя queue и содержит два поля: int data, queue* next.

Создание очереди:

Queue* make_queue(int n, queue* &first, queue* &last) { if (n == 0) return NULL;

Queue* p = new Queue; // Выделение памяти под один элемент

p->data = rand() % 10 + 1;

p->next = NULL; /* Так как он первый, то он ни на что не указывает */

161

first = p;

// Новый элемент является первым

last = p;

// И последним

for (int i = 2; i <= n; i++) { Queue* h = new queue;

// Выделение памяти для нового элемента

h->data =

rand()%10 + 1;

h->next =

p;

// Указываем на следующий элемент

last = h;

 

/*

Показываем, что введенный

 

 

 

элемент стал последним */

p = last;

 

//

Перешли к последнему элементу

}

return first;

}

Подробнее: в строке 4 присваивается первый элемент. Затем в цикле от 2 до n (начальное количество элементов в очереди) присваиваются остальные элементы. В строке 9 выделяется память для нового элемента. Затем в строке 11 указателю нового элемента присваивается указатель на последний элемент в очереди, в строке 12 указателю на последний элемент присваивается указатель на новый элемент. В строке 15 указатель на первый элемент возвращается.

Вывод очереди на экран:

void PrintQueue(Queue* last) {

/* Печать очереди без

 

удаления элементов */

Queue* p = last;

// p указывает на

 

последний элемент

while (p != NULL) { // Печать с конца очереди

cout << p->data << " ";

// Печать

p = p->next;

// Переход к следующему

 

элементу

}

cout << endl;

}

Подробнее: параметром передается указатель на последний элемент очереди. В строке 2 указателю p присваивается указатель на последний элемент очереди. В цикле (строки 3–6) выводятся значения каждого элемента очереди, пока не дойдет до первого элемента.

162

}
p = last;
if (k == 1) {

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

Удаление элемента из очереди:

int pop(Queue* &first, Queue* &last) { // Функция удаления элемента

Queue* p = last;

int k = 0; // Кол-во элементов в очереди while (p != NULL) { // Считаем кол-во элементов

k++;

p = p->next;

/* Если элемент один, то обнуляем указатели и возвращаем последний элемент */

int t = last->data; delete p;

last = NULL; first = NULL; return t;

}

 

else {

// Если больше одного

while (p->next->next != NULL)

// Переходим к предпоследнему элементу p = p->next;

Queue* t = p; // Указатель на предпоследний

 

элемент

int e = p->next->data;

// Сохранение значения последнего элемента

p = p->next;

// Переход к последнему элементу

t->next = NULL;

// Предпоследний указатель

 

указывает на NULL

first = t;

// И он теперь первый элемент

delete p;

// Удаление последнего элемента

return e;

// Возвращение первого элемента

}

}

163

Подробнее: параметром передается указатель по ссылке на первый и последний элементы очереди. В строке 2 объявляется указатель p, чтобы сохранить последний элемент. Подсчет количества элементов в очереди (строки 3–6). Если в очереди находится один элемент, то возвращается значение этого элемента и удаляется из памяти (строки 8–16), а если нет, то осуществляется переход к предпоследнему элементу (строки 18–19) и его указатель сохраняется в переменную t. Переход к последнему элементу, сохранение его значения, чтобы потом возвратить, и удаление элемента. Указателю предпоследнего элемента присваивается NULL, а указателю на первый элемент очереди присваивается указатель предпоследнего элемента.

Добавление элемента в очередь:

Queue* push(int n, queue* &last) {

Queue* p = new queue;

// Выделение памяти для нового

 

элемента

p->data = n;

// Присвоение

p->next = last;

// Наш новый элемент указывает на

 

следующий

last = p;

// Новый элемент стал последним

return last;

 

}

 

Подробнее: параметром передается указатель на последний элемент очереди и значение элемента, который необходимо добавить. Выделяется память для нового элемента (строка 2), присваивается значение, переданное параметром (строки 3–5), указателю нового элемента присваивается указатель на последний элемент очереди (строка 6), а указателю на последний элемент присваивается указатель на новый элемент (строка 7).

Удаление первых двух и последних двух элементов (в главной функции):

pop(first, last);

// Удаление первого элемента

pop(first, last);

// Удаление второго элемента

int mas[6];

 

164

for (int i = 0; i < 6; i++) // Перенос элементов в массив mas[i] = pop(first, last);

pop(first,

last);

//

Удаление

девятого

элемента

pop(first,

last);

//

Удаление

десятого

элемента

for (int i = 0; i < 6; i++) // Перенос элементов в массив push(mas[i], last);

cout << "Очередь после удаления: "; print_queue(last); // Печать очереди

Подробнее: удаляются первые два элемента (строки 1–2) методом pop(). Затем создается массив из шести элементов для временного хранения всех элементов очереди, кроме последних двух. В цикле (строки 4–5) все элементы очереди, кроме двух, переносятся в массив. Удаляются последние два элемента (строки 6–7). Затем все элементы переносятся обратно в очередь (строки 8–9). Очередь печатается (строка 11).

Добавление трех элементов в середину очереди:

for (int i = 0; i < 6; i++) // Перенос элементов в массив mas[i] = pop(first, last);

for (int i = 0; i < 3; i++) // Добавление первой половины из массива

push(mas[i], last);

for (int i = 0; i < 3; i++) // Добавление новых элементов push(rand()% 10 + 1, last);

for (int i = 3; i < 6; i++) // Добавление второй половины из массива

push(mas[i], last);

cout << "Очередь после добавления: "; print_queue(last); // Печать очереди

Подробнее: в цикле (строки 1–2) все элементы очереди переносятся в массив. Затем добавляются первые три элемента (строки 3–4) из массива, после добавляются три новых элемента (строки 5–6) и оставшиеся три из массива (строки 7–8). Очередь печатается.

Главная функция:

int main() { setlocale(LC_ALL, "Rus");

165

srand(time(0));

 

Queue* first,* last;

/* Указатели на первый и последний

 

элементы очереди */

make_queue(10, first, last);

print_queue(last);

// Печать очереди

pop(first, last);

// Удаление первого элемента

pop(first, last);

// Удаление второго элемента

int mas[6];

 

for (int i = 0; i < 6; i++)

// Перенос элементов в массив mas[i] = pop(first, last);

pop(first,

last);

//

Удаление

девятого

элемента

pop(first,

last);

//

Удаление

десятого

элемента

for (int i = 0; i < 6; i++)

// Перенос элементов в массив push(mas[i], last);

cout << "Очередь после удаления: "; print_queue(last); // Печать очереди for (int i = 0; i < 6; i++)

// Перенос элементов в массив mas[i] = pop(first, last);

for (int i = 0; i < 3; i++)

// Добавление первой половины из массива push(mas[i], last);

for (int i = 0; i < 3; i++) // Добавление новых элементов

push(rand()% 10 + 1, last);

for (int i = 3; i < 6; i++) /* Добавление второй половины из массива */

push(mas[i], last);

cout << "Очередь после добавления: "; print_queue(last); // Печать очереди return 0;

}

Пример выполнения работы программы:

3 10 1 7 10 10 7 1 8 3

Очередь после удаления: 1 7 10 10 7 1 Очередь после добавления: 1 7 10 1 1 2 10 7 1

166

14.13. Реализация очереди через класс

Рассмотрим решение задачи в гл. 3, реализованное через класс. Первым шагом создается класс queue со всеми необходимыми

методами.

class Queue {

 

private:

 

int* arr;

// Массив элементов очереди

int MAX;

// Максимальное кол-во элементов очереди

int index;

// Текущий элемент очереди

public:

 

Queue(int);

// Конструктор

~Queue();

// Деструктор

bool push(int);

// Вставка элемента

int pop();

// Удаление элемента

void print();

// Печать очереди

};

 

Скрытые данные: указатель на массив элементов, максимальное количество элементов в очереди, номер текущего элемента в очереди. Публичные методы: конструктор, деструктор, добавление элемента, удаление элемента и печать очереди.

Конструктор и деструктор:

Queue::Queue(int kol) { // Создание очереди c кол-вом

 

элементов = kol

MAX = 100;

// Максимальное кол-во элементов

 

очереди

index = –1;

// Начальный индекс

if (kol <= MAX) {

// Если количество не больше

 

максимума

arr = new int[kol];

MAX = kol;

// Изменение максимума

}

else cout << "Переполнение очереди\n";

}

 

Queue::~Queue() {

// Деструктор

167

delete[] arr;

};

Подробнее: параметром для конструктора передается максимальное количество элементов очереди. Переменной MAX присваивается переданный параметр (строка 6), и выделяется память для массива элементов (строка 5). Если ввели количество элементов больше 100, то выводит ошибку о переполнении очереди (строка 8). В деструкторе удаляется массив (строка 11).

Печать очереди:

void Queue::print() {

for (int i = 0; i <= index; i++) cout << arr[i] << " ";

cout << endl;

}

Подробнее: элементы массива печатаются в прямом порядке

(строки 2–3).

Добавление элемента в очередь:

bool Queue::push(int n) { int t;

if (index == MAX) // Если очередь уже полная return 0;

else {

if (index == –1) // Вставка первого элемента arr[++index] = n;

else { // Вставка остальных элементов for (int i = index; i >= 0; i--) {

// Вставка элементов по очереди arr[i + 1] = arr[i];

arr[i] = n;

}

index++;

}

return 1;

}

};

168

Подробнее: параметром передается значение элемента, который нужно добавить. Если происходит попытка добавить элемент, но места для него уже нет, то возвращается 0 (строка 4), иначе если добавляется первый элемент, то индекс увеличивается на 1 и элемент добавляется в массив (строки 6–7), а если в очереди уже есть элементы, то все элементы массива смещаются вправо и в начало массива добавляется новый элемент (строки 9–13).

Удаление элемента из очереди:

int Queue::pop() {

 

if (index == –1) {

// Если индекс не

 

изменился

cout << "Очередь пуста\n";

 

return 0;

 

}

 

else

 

return arr[index--];

 

};

 

Подробнее: если очередь пустая, то это сообщается пользователю и возвращается 0 (строки 3–4), а если нет, то возвращается элемент, который был добавлен последним (строка 6).

Удаление первых двух и последних двух элементов:

qu.pop();

// Удаление первого элемента

qu.pop();

// Удаление второго элемента

int mas[6];

 

for (int i = 0; i < 6; i++)

// Перенос элементов в массив

mas[i] = qu.pop();

 

qu.pop();

// Удаление девятого элемента

qu.pop();

// Удаление десятого элемента

for (int i = 0; i < 6; i++)

// Перенос элементов в массив

qu.push(mas[i]);

 

cout << "Очередь после удаления: ";

qu.print();

// Печать очереди

Подробнее: удаляются первые два элемента (строки 1–2) методом pop(). Затем создается массив из шести элементов для временного хранения всех элементов очереди, кроме последних двух.

169

В цикле (строки 4–5) все элементы очереди, кроме двух, переносятся в массив. Удаляются последние два элемента (строки 6–7). Затем все элементы переносятся обратно в очередь (строки 8–9). Очередь печатается (строка 11).

Добавление трех элементов в середину очереди:

for (int i = 0; i < 6; i++) // Перенос элементов в массив mas[i] = qu.pop();

for (int i = 0; i < 3; i++) // Добавление первой половины из массива

qu.push(mas[i]);

for (int i = 0; i < 3; i++) // Добавление новых элементов qu.push(rand()%10 + 1);

for (int i = 3; i < 6; i++) // Добавление второй половины

 

из массива

qu.push(mas[i]);

 

 

cout << "Очередь после добавления: ";

 

qu.print();

// Печать

очереди

Подробнее: в цикле (строки 1–2) все элементы очереди переносятся в массив. Затем добавляются первые три элемента (строки 3–4) из массива, после добавляются три новых элемента (строки 5–6) и оставшиеся три из массива (строки 7–8). Очередь печатается.

Главный файл:

#include <iostream> #include <time.h> #include "queue.h" using namespace std; int main() {

setlocale(LC_ALL, "Rus"); srand(time(0));

Queue qu(10); // Очередь имеет максимум 10 элементов for (int i = 0; i < 10; i++)

qu.push(rand() % 10 + 1); qu.print(); // Печать очереди qu.pop(); // Удаление первого элемента qu.pop(); // Удаление второго элемента

170

Соседние файлы в папке книги