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

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

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

t = head; // Обнуление t

for (int i = 0; i < p – 1; i++) // Переходим к элементу перед

удаляемым

t = t->next; t->next = e;

//Указываем на ранее сохраненный элемент

if (p != size – 1)

/* Если

 

удалялся

 

не последний

 

элемент */

t->next->prev = t;

 

 

/* Переходим к нему и указываем

 

на тот, с которого перешли */

}

 

size--;

// Уменьшаем

 

размер списка

return 1;

 

}

}

}

Подробнее: параметром передается индекс элемента, который необходимо удалить (строка 1). Если список пуст, то возвращается 0, так как удаление невозможно (строка 2). Если индекс, который ввели, не существует, то выводится на консоль сообщение, что такого индекса нет (строка 5), и также возвращается 0. Если удаляется первый элемент в списке, то указатель на первый элемент сохраняется в переменную del и указателю на первый элемент присваивается указатель на второй элемент, а del удаляется (строки 10–17). Если удаляется не первый элемент, то в цикле доходим до удаляемого элемента и сохраняем его указатель в переменную e (строка 23), а указатель элемента, который находится после удаляемого элемента, сохраняем в переменную y (строка 24). Затем доходим до элемента, который находится перед удаляемым, и ему присваиваем указатель e, а после доходим до элемента, который находится после удаляемого, и ему присваиваем указатель y.

141

Удаление элементов по значению:

bool list::delete_element_by_value(int ar) {

if (head == nullptr)

 

return 0;

 

else {

 

bool f = false;

 

int index = 0;

 

Node* t = head;

 

int kol = 0;

// Кол-во удаляемых элементов

while (t) {

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

if (t->data == ar) { f = true; kol++;

}

t = t->next;

}

if (!f) return 0; // Если такого элемента нет else {

for (int i = 0; i < kol; i++) { t = head;

if (t == nullptr) return 1;

while (t->data != ar) { /* Находим индекс удаляемого элемента */

t = t->next; index++;

}

delete_element_by_number(index); // Иначе удаление по индексу

}

}

return 1;

}

}

142

// Удаление элемента
// Добавление элементов
/* Вставка элементов в начало списка

Подробнее: параметром передается значение элемента, который необходимо удалить (строка 1). Если список пуст, то возвращается 0, так как удаление невозможно (строка 2). Считается количество удаляемых элементов (строки 7–11). Если получилось так, что количество удаляемых элементов равно 0, то возвращается 0 (строка 12). Если количество удаляемых элементов больше 0, то в цикле находятся индексы удаляемых элементов (строка 18), а затем они удаляются с помощью метода удаления по индексу (строка 20).

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

#include <iostream>

 

#include <time.h>

 

#include "LishTwo.h"

 

using namespace std;

 

int main() {

 

setlocale(LC_ALL, "Rus");

 

srand(time(0));

 

List list;

// Список

for (int i = 0; i < 10; i++) {

// Создание списка

list.push_back(rand()%10 + 1);

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

 

в конец списка */

}

list.print(); // Печать списка

cout << "Введите число, которое хотите удалить: "; int n;

// Число, которое нужно удалить cin >> n; list.delete_element_by_value(n);

cout << "Новый список: "; list.print(); // Печать списка for (int i = 0; i < 3; i++) {

list.push_back(rand()%10 + 1);

*/

143

}

cout << "Список после добавления: ";

 

list.print();

 

// Печать списка

 

return 0;

 

 

 

}

 

 

 

 

 

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

 

8

8 9 7 3 8 4 6

6 9

 

 

Введите число, которое хотите удалить: 8

 

Новый список: 9

7 3

4 6 6 9

 

Список после добавления: 9 7 3 4 6 6 9 2

10 5

Задание для самостоятельной работы:

Реализовать двунаправленный список из 10 элементов тремя способами. Написать программу, которая сортирует список по возрастанию и удаляет 4 наименьших элемента, добавляет 5 новых элементов в середину списка.

14.6. Стеки

Стек (рис. 14.3) – абстрактный тип данных, представляющий собой список элементов, организованных по принципу LIFO (англ. last in – first out – «последним пришел – первым вышел»). Это значит, что мы будем иметь доступ только к последнему добавленному элементу.

Рис. 14.3. Структура стека

144

Абстрактный тип данных – это математическая модель для типов данных, где тип данных определяется поведением (семантикой) с точки зрения пользователя данных, а именно – в терминах возможных значений, возможных операций над данными этого типа и поведения этих операций [21].

Базовые операции над стеком:

инициализация стека;

помещение элемента в стек;

удаление элемента из стека;

определение верхнего элемента без его удаления;

печать стека;

определение пустоты стека;

удаление стека.

14.7. Реализация стека через библиотеку STL

Необходимо реализовать стек, используя класс stack библиотеки STL. Программа должна создавать стек из n (задается пользователем) элементов, где n > 3, удалять первые три добавленных элемента и добавлять три новых элемента перед последним добавленным элементом.

Пример: 1 2 3 4 5 6 – изначальный стек, 1 2 3 – стек после удаления, 1 7 8 9 2 3 – стек после добавления.

Подключаем необходимые библиотеки, русский язык и генератор случайных чисел:

#include <iostream>

#include <stack> // Заголовок стека #include <time.h>

using namespace std; int main() {

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

return 0;

}

145

Создание стека:

stack<int> st;

//

Создали пустой стек

int n;

//

Количество элементов стека

cout << "Введите количество элементов стека (больше 3): "; cin >> n;

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

st.push(rand()%10 + 1); // Добавление элементов в

стек

 

print(st);

// Печать стека

Подробнее: в строке 1 создается стек типа int, затем вводится количество элементов в стек (строка 4), и в цикле от 0 до n методом push() в стек добавляются случайные элементы от 1 до 10. В конце стек печатается.

Печать стека:

void print(stack<int> st) { int p = st.size();

// Сохранили размер стека в переменную

for (int i = 0; i < p; i++) { // Печать элементов

стека

cout << st.top() << " "; st.pop();

}

cout << endl;

}

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

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

stack<int> st2; // Создали второй стек for (int i = 0; i < n – 3; i++) {/* Перенос всех элементов,

 

кроме последних трех */

st2.push(st.top());

/* Перенос верхнего элемента

 

1-го стека во 2-й стек */

146

st.pop();

// Удаление верхнего

 

элемента 1-го стека

}

 

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

 

st.pop();

// Удаление оставшихся трех

 

элементов

for (int i = 0; i < n – 3; i++) { /* Перенос элементов

 

обратно в 1-й стек */

st.push(st2.top());

/* Перенос верхнего

 

элемента

 

2-го стека в 1-й стек */

st2.pop();

// Удаление верхнего

 

элемента 2-го стека

}

 

cout << "Стек после удаления: ";

 

print(st); // Печать стека

 

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

(строки 8–11).

Добавление трех элементов перед первым:

int h = st.top();

// Сохранили верхний

 

элемент

st.pop();

 

//И удалили его, чтобы получить доступ к следующему for (int i = 0; i < 3; i++)

st.push(rand() % 10 + 1); // Добавление трех элементов st.push(h);

//Возвращаем ранее удаленный элемент

cout << "Стек после добавления: ";

print(st);

// Печать стека

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

147

элемента (строки 3–4), и удаленный элемент возвращается в стек

(строка 5).

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

Введите количество элементов стека (больше 3): 10

6 10 8 6 9 7 9 1 5 10

Стек после удаления: 6 10 8 6 9 7 9 Стек после добавления: 6 1 3 5 10 8 6 9 7 9

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

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

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

struct Stack {

// Структура стек

int data;

// Значение элемента

Stack* prev;

// Указатель на нижний элемент

};

 

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

Создание стека:

Stack* make_stack(int size) {

if (size == 0) return

NULL;

Stack *first, *p;

// first – указатель на верхний

 

 

элемент стека

first = NULL;

// Пока он ни на что не указывает

p = new Stack;

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

p->data = rand() %

10 + 1;

p->prev = NULL;

// Так как он первый, то снизу

 

 

элементов нет

first = p;

/* Показываем, что введенный элемент

 

 

стал первым */

for (int i = 2; i <= size; i++) {

148

Stack* h = new Stack;

// Выделение памяти для нового элемента h->data = rand() % 10 + 1;

h->prev = first; // Указываем на нижний элемент first = h; /* Показываем, что введенный

элемент стал первым */

}

return first;

}

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

Вывод стека на экран:

void print_stack(Stack* first) {

Stack* p = first; // p указывает на первый элемент while (p != NULL) { // Пока существуют элементы

cout << p->data << " "; // Вывод ключа

p = p->prev; // Переход к следующему элементу

}

cout << endl;

}

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

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

149

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

int pop(Stack* &first) { // Возвращение первого элемента и его удаление

Stack* p = first;

int k = 0; // Кол-во элементов в стеке

while (p != NULL) { // Считаем кол-во элементов

k++;

 

 

p = p->prev;

 

 

}

 

 

p = first;

 

 

if (k == 1) {

/* Если элемент один, то обнуляем

 

 

указатели и возвращаем последний

 

 

элемент */

int t = first->data;

 

delete p;

 

 

first = NULL;

 

 

return t;

 

 

}

 

 

else { // если больше 1

 

Stack* t = p->prev;

// Указатель на второй элемент

int u = p->data;

 

/* Сохранение значения

 

 

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

first = t;

 

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

delete p;

 

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

return u;

 

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

}

 

 

}

Подробнее: параметром передается указатель по ссылке на первый элемент стека. В строке 2 объявляется указатель q, чтобы сохранить первый элемент. Объявляется перемення val, в которой будет храниться возвращаемое значение (строка 3). Указателю на первый элемент присваивается указатель на следующий элемент (строка 4), а переменной val присваивается значение элемента, который необходимо удалить. Элемент удаляется (строка 5), и его значение возвращается (строка 6).

150

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