Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Удаление первой компоненты очереди

Формирование очереди

Опишем предикат, который позволяет вводить последовательно все элементы в очередь. Пусть vvod (N, L) - предикат, реализующий формирование очереди, N - количество элементов очереди, L - заполняемая очередь.

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

vvod (0, []).

vvod (N, L):-

Readint (X),

N1=N-1,

Vvod (N1, LL),

L = [X|LL].

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

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

Когда выполнится граничное условие, из стека последовательно извлекаются введенные элементы в обратном порядке и добавляются в конец очереди.

Добавление компоненты в конец очереди

Опишем предикат, который позволяет добавлять элементы в конец очереди. Пусть add_in_end (S1, S2, S3) - предикат, реализующий добавление компоненты, S1 - очередь, к которой добавляем, S2 - список, содержащий добавляемый элемент (перед вызовом предиката необходимо добавляемый элемент поместить в список S2), S3 - очередь с добавленным элементом.

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

add_in_end ([], S, S).

add_in_end ([X|S1], S2, [X| S3]):-

Add_in_end (S1, S2, S3).

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

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

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

Удаление первой компоненты очереди

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

Spisok = [_|S1].

Spisok - очередь из которой удаляем, S1 - новая очередь.

 

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

По определению, элементы извлекаются из стека в порядке, обратном их добавлению в эту структуру, т.е. действует принцип "последний пришёл — первый ушёл".

Наиболее наглядным примером организации стека служит детская пирамидка, где добавление и снятие колец осуществляется как раз согласно определению стека.

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

Выделим типовые операции над стеком и его элементами:

  • добавление элемента в стек;
  • удаление элемента из стека;
  • проверка, пуст ли стек;
  • просмотр элемента в вершине стека без удаления;
  • очистка стека.

Реализуем эти операции, используя разработанный ранее модуль для однонаправленных списков (см. материал " Динамические структуры данных: списки ").

 

{ Turbo Pascal, файл STACK.PAS } Unit Stack; Interface Uses Spisok; Procedure V_Stack(Var Versh: U; X: BT); Procedure Iz_Stack(Var Versh: U; Var X: BT); Function Pust(Versh: U): Boolean; Function V_Vershine(Versh: U): BT; Procedure Ochistka(Var Versh: U); Implementation Procedure V_Stack; Begin V_Nachalo(Versh, X) End; Procedure Iz_Stack; Begin Iz_Nachala(Versh, X) End; Function Pust; Begin Pust:= Versh = Nil End; Function V_Vershine; Begin V_Vershine:= Versh^.Inf End; Procedure Ochistka; Begin Spisok.Ochistka(Versh) End; Begin End.   /* C++, файл STACK.CPP */ #include "SPIS.CPP" Zveno *V_Stack(Zveno *Versh, BT X) { return V_Nachalo(Versh, X); } Zveno *Iz_Stack(Zveno *Versh) { return Iz_Nachala(Versh); } int SPust(Zveno *Versh) { return!Versh; } BT V_Vershine(Zveno *Versh) { return Versh->Inf; } Zveno *Chistka(Zveno *Versh) { while (!Pust(Versh)) Versh=Iz_Stack(Versh); return Versh; }

 

Используя разработанные здесь библиотеки, решим задачу.

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

Алгоритм решения. Выражение просматривается слева направо. Если встречается число, то его значение (как целое) заносится в стек, а если встречается знак операции, то из стека извлекаются два последних элемента (это операнды данной операции), над ними выполняется операция и ее результат записывается в стек. В конце в стеке остается только одно число — значение всего выражения.

 

{ Turbo Pascal, файл ST2.PAS } Program St2; Uses Spisok, Stack; Const Znak = ['+', '-', '*', '/']; Var S, S1: String; T: Text; I, N: Byte; X, Y: BT; Code: Integer; NS: U; Begin Write('Введите имя файла: '); ReadLn(S1); Assign(T, S1); ReSet(T); NS:= Nil; While Not Eof(T) Do Begin ReadLn(T, S); I:= 1; While I <= Length(S) Do Begin If S[I] In ['0'..'9'] Then Begin N:= I; While S[I] In ['0'..'9'] Do I:= I + 1; Val(Copy(S, N, I - N), X, Code); V_Stack(NS, X); End Else If S[I] In Znak Then Begin Iz_Stack(NS, X); Iz_Stack(NS, Y); Case S[I] Of '+': X:= X + Y; '-': X:= Y - X; '*': X:= X * Y; '/': X:= Y Div X End; V_Stack(NS, X) End; I:= I + 1 End; Iz_Stack(NS, X); WriteLn(S, ' = ', X); End End.   /* C++, файл ST2.CPP */ #include "STACK.CPP" #include < string.h > #include < stdio.h > void main(void) { char S[255]; FILE *T; int I; BT X, Y; Zveno *NS; clrscr(); cout << "Введите имя файла: "; cin >> S; T=fopen(S, "r"); NS = NULL; while (!feof(T)) { fgets(S, 255, T); I = 0; while (I <= strlen(S)-1) { if (S[I]>='0'&&S[I]<='9') { X=0; while(S[I]>='0'&&S[I]<='9') {X=X*10+(S[I]-'0'); I++;} NS=V_Stack(NS, X); } else if (S[I]=='+'||S[I]=='-'||S[I]=='/'||S[I]=='*') { X=V_Vershine(NS); NS=Iz_Stack(NS); Y=V_Vershine(NS); NS=Iz_Stack(NS); switch (S[I]) { case '+': X += Y; break; case '-': X = Y - X; break; case '*': X *= Y; break; case '/': X = Y / X; break;} NS=V_Stack(NS, X); } I++; } X=V_Vershine(NS); NS=Iz_Stack(NS);

 



<== предыдущая лекция | следующая лекция ==>
Визначаємо дозу опромінення яку отримають робітники | Программа итогового зачета по дисциплине
Поделиться с друзьями:


Дата добавления: 2016-10-07; Мы поможем в написании ваших работ!; просмотров: 247 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Студент может не знать в двух случаях: не знал, или забыл. © Неизвестно
==> читать все изречения...

2751 - | 2313 -


© 2015-2024 lektsii.org - Контакты - Последнее добавление

Ген: 0.011 с.