Цель лекции: изучить понятия, объявления, особенности доступа к данным и работы с памятью в стеках и очередях, научиться решать задачи с использованием стеков и очередей в языке C++.
Стек и очередь – это частные случаи линейного списка.
В списках доступ к элементам происходит посредством адресации, при этом доступ к отдельным элементам не ограничен. Но существуют также и такие
). В стеках используется
Стек – это список, у которого доступен один элемент (одна позиция). Этот элемент называется вершиной стека. Взять элемент можно только из
(рис 30.1) Стек и его организацияОписание стека выглядит следующим образом:
struct имя_типа {
информационное поле;
адресное поле;
};
где информационное поле – это поле любого ранее объявленного или стандартного типа;
адресное поле – это указатель на объект того же типа, что и определяемая структура, в него записывается адрес следующего элемента стека.
Например:
struct list {
type pole1;
list *pole2;
} stack;
Стек как NULL.
Описание элементов стека аналогично описанию элементов линейного однонаправленного списка. Поэтому объявим стек через объявление линейного однонаправленного списка:
struct Stack {
Single_List *Top;//вершина стека
};
. . . . . . . . . .
Stack *Top_Stack;//указатель на вершину стека
Основные операции, производимые со стеком:
Реализацию этих операций рассмотрим в виде соответствующих функций, которые, в свою очередь, используют функции операций с линейным однонаправленным списком. Обратим внимание, что в функции создания стека используется функция добавления элемента в
//создание стека
void Make_Stack(int n, Stack* Top_Stack){
if (n > 0) {
int tmp;//вспомогательная переменная
cout << "Введите значение ";
cin >> tmp; //вводим значение информационного поля
Push_Stack(tmp, Top_Stack);
Make_Stack(n-1,Top_Stack);
}
}
//печать стека
void Print_Stack(Stack* Top_Stack){
Print_Single_List(Top_Stack->Top);
}
//добавление элемента в вершину стека
void Push_Stack(int NewElem, Stack* Top_Stack){
Top_Stack->Top =Insert_Item_Single_List(Top_Stack->Top,1,NewElem);
}
//извлечение элемента из вершины стека
int Pop_Stack(Stack* Top_Stack){
int NewElem = NULL;
if (Top_Stack->Top != NULL) {
NewElem = Top_Stack->Top->Data;
Top_Stack->Top = Delete_Item_Single_List(Top_Stack->Top,0);
//удаляем вершину
}
return NewElem;
}
//проверка пустоты стека
bool Empty_Stack(Stack* Top_Stack){
return Empty_Single_List(Top_Stack->Top);
}
//очистка стека
void Clear_Stack(Stack* Top_Stack){
Delete_Single_List(Top_Stack->Top);
}
Пример 1. Дана строка символов. Проверьте правильность расстановки в ней круглых скобок.
В решении данной задачи будем использовать стек. Приведем главную функцию и функцию для проверки правильности расстановки круглых скобок.
//главная функция
int _tmain(int argc, _TCHAR* argv[]){
char text[255];
printf("Введите текст, содержащий \"(\" и \")\" \n");
gets(text);
Check_Brackets (text);
system("pause");
return 0;
}
//функция проверки правильности расстановки скобок
void Check_Brackets (char *text){
int i;
int flag=1;
Stack *Top_Stack;
Top_Stack = new Stack();
for(i=0;i<strlen(text); i++) {
if(text[i]==')' ) {
if(Empty_Stack(Top_Stack)) {
//Попытка удалить нулевой элемент стека
flag=0;
break;
}
if(Top_Stack->Top->Data == '(')
Pop_Stack(Top_Stack);
else {
flag=0;
break;
}
}
if(text[i]=='(')
Push_Stack(text[i],Top_Stack);
}
if(flag!=0 Empty_Stack(Top_Stack))
printf("Верно!");
else printf("Неверно!");
Clear_Stack(Top_Stack);
printf("\n");
}
). В очереди доступны два элемента (две позиции): начало очереди и конец очереди. Поместить элемент можно только в конец очереди, а взять элемент только из ее начала. Примером может служить обыкновенная очередь в магазине.
(рис 30.2) Очередь и ее организацияОписание очереди выглядит следующим образом:
struct имя_типа {
информационное поле;
адресное поле1;
адресное поле2;
};
где информационное поле – это поле любого, ранее объявленного или стандартного, типа;
адресное поле1, адресное поле2 – это указатели на объекты того же типа, что и определяемая структура, в них записываются адреса первого и следующего элементов очереди.
Например:
1 способ: адресное поле ссылается на объявляемую структуру.
struct list2 {
type pole1;
list2 *pole1, *pole2;
}
2 способ: адресное поле ссылается на ранее объявленную структуру.
struct list1 {
type pole1;
list1 *pole2;
}
struct ch3 {
list1 *beg, *next ;
}
Очередь как NULL.
Описание элементов очереди аналогично описанию элементов линейного
struct Queue {
Double_List *Begin;//начало очереди
Double_List *End; //конец очереди
};
. . . . . . . . . .
Queue *My_Queue;//указатель на очередь
Основные операции, производимые с очередью:
Реализацию этих операций приведем в виде соответствующих функций, которые, в свою очередь, используют функции операций с линейным двунаправленным списком.
//создание очереди
void Make_Queue(int n, Queue* End_Queue){
Make_Double_List(n,(End_Queue->Begin),NULL);
Double_List *ptr; //вспомогательный указатель
ptr = End_Queue->Begin;
while (ptr->Next != NULL)
ptr = ptr->Next;
End_Queue->End = ptr;
}
//печать очереди
void Print_Queue(Queue* Begin_Queue){
Print_Double_List(Begin_Queue->Begin);
}
//добавление элемента в конец очереди
void Add_Item_Queue(int NewElem, Queue* End_Queue){
End_Queue->End = Insert_Item_Double_List(End_Queue->End,
0, NewElem)->Next;
}
//извлечение элемента из начала очереди
int Extract_Item_Queue(Queue* Begin_Queue){
int NewElem = NULL;
if (Begin_Queue->Begin != NULL) {
NewElem = Begin_Queue->Begin->Data;
Begin_Queue->Begin=Delete_Item_Double_List(Begin_Queue->Begin,0);
//удаляем вершину
}
return NewElem;
}
//проверка пустоты очереди
bool Empty_Queue(Queue* Begin_Queue){
return Empty_Double_List(Begin_Queue->Begin);
}
//очистка очереди
void Clear_Queue(Queue* Begin_Queue){
return Delete_Double_List(Begin_Queue->Begin);
}
Пример 2. Дана последовательность ненулевых целых чисел. Признаком конца последовательности является число 0. Найдите среди них первый наибольший отрицательный элемент. Если такого элемента нет, то выведите сообщение об этом.
В данной задаче будем использовать основные операции для работы с очередью, рассмотренные ранее. Приведем главную функцию и функцию для реализации поиска первого наибольшего отрицательного элемента.
//главная функция
int _tmain(int argc, _TCHAR* argv[]){
int n;
Queue *My_Queue;
My_Queue = new Queue();
Make_Queue(1,My_Queue);
while (My_Queue->End->Data != 0){
cout << "Введите значение ";
cin >> n;
Add_Item_Queue(n,My_Queue);
}
cout << "\nОчередь: \n";
Print_Queue(My_Queue);
Find_Max_Negative_Element(My_Queue);
system("pause");
return 0;
}
//функция поиска первого наибольшего отрицательного элемента
void Find_Max_Negative_Element(Queue* Begin_Queue){
int tmp;
int max=Extract_Item_Queue(Begin_Queue);
while (Begin_Queue->Begin->Data != 0) {
tmp = Extract_Item_Queue(Begin_Queue);
if (max > 0 || tmp < 0 abs(tmp) < abs(max))
max = tmp;
}
if (max > 0) printf("Элементов нет!");
else printf("Есть такой элемент: %d", max);
}
FIFO (First Input – First Output) – это
LIFO (Last Input – First Output) – это
Вершина стека – это доступный элемент стека.
Конец очереди – это позиция доступного для вставки в очередь элемента.
Начало очереди – это позиция доступного для извлечения из очереди элемента.
Очередь – это структура данных, представляющая собой последовательность элементов, образованная в порядке их поступления.
Стек – это структура данных, в которой новый элемент всегда записывается в ее начало (вершину) и очередной читаемый элемент также всегда выбирается из ее начала.
Цель работы: изучить понятия, объявления, особенности доступа к данным и работы с памятью в стеках и очередях, научиться решать задачи с использованием стеков и очередей в языке C++.
При выполнении лабораторной работы для каждого задания требуется написать программу на языке С++, в которой выполнено формирование очереди или стека в соответствии с постановкой задачи, ввод данных элементов очереди или стека с учетом типа информационного поля, их обработка и вывод на экран в указанном формате. Для хранения данных динамических структур следует использовать ресурсы динамической памяти. Ввод данных осуществляется с клавиатуры с учетом требований к входным данным, содержащихся в постановке задачи. Ограничениями на входные данные являются максимальный размер строковых данных, диапазоны числовых типов полей структуры и допустимый размер области динамической памяти в языке С++.
Теоретические сведения.
Ознакомьтесь с материалом лекции 30.
Задания к лабораторной работе.
Выполните приведенные ниже задания.
Указания к выполнению работы.
Каждое задание необходимо решить в соответствии с изученными методами формирования, вывода и обработки данных очередей и стеков в языке С++. Обработку очередей или стеков следует выполнить на основе базовых алгоритмов: поиск, вставка элемента, удаление элемента, удаление всей динамической структуры. При объявлении списков выполните комментирование используемых полей. Задачи 2 и 4 носят исследовательский характер, поэтому при составлении отчета к ним следует подробно описать предлагаемый метод оценки максимального размера очереди или стека. Программу для решения каждого задания необходимо разработать методом процедурной абстракции, оформив комментарии к коду.
Следует реализовать каждое задание в соответствии с приведенными этапами:
Требования к отчету.
Отчет по лабораторной работе должен соответствовать следующей структуре.
Контрольные вопросы
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.