НОВОСТИ
Новости сайта
О САЙТЕ
Содержание сайта
БИБЛИОТЕКА
Структуры и алгоритмы
ОБРАТНАЯ СВЯЗЬ
Связь с автором
Структуры и алгоритмы

Стек

Цель: изучение фундаментальной абстрактной структуры - стека.

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

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

stek.gif (1708 bytes)

В структуре стека важнейшее место занимают операции, добавляющие и удаляющие элементы. Операция Push добавляет в вершину стек, а операция Pop извлекает элемент с вершины стека.

stek1.gif (876 bytes)

type
link = ^node;
node = record
key: integer;
next: link;
end;

Var
head, z: link;

procedure stackinit;
begin
new(head);
new(z);
head^.next:=z;
z^.next:=z;
end;

procedure push(v: integer);
var
t: link;
begin
new(t);
t^.key:=v;
t^.next:=head^.next;
head^.next:=t;
end;

function pop: integer;
var
t: link;
begin
t:=head^.next;
pop:=t^.key;
head^.next:=t^.next;
dispose(t);
end;

Давайте решим задачу с использованием стека.

Нужно так расставить 8 ферзей на шахматной доске, чтобы ни один из них не угрожал другому.

Эта задача демонстрирует очень интересный прием в программировании - поиск с возвращениями.

Хотя на доске 64 клетки, взять 8 из них можно 64!/(56!*8!)=4 426 165 368 способами. Проверять все эти комбинации - большая работа даже для ЭВМ.

Поставим одного ферзя, затем ("безопасно") второго, третьего и т.д.

ferz.gif (4063 bytes)

Для указанного размещения 5 ферзей вы не найдете подходящей позиции для 6-го ферзя. Наступил черед рационализации. Не будем отбрасывать достигнутое! Сделаем лишь один шаг назад - изменим позицию ферзя Ф5, вновь попытаемся поставить Ф6 и лишь при безуспешной попытке сделаем второй шаг назад и т.д. Это стратегия планомерного отступления и прорыва вперед при первой возможности.

Кто бы мог подумать, что будет столько тупиков! К первому полному решению приходим, побывав в 42 тупиках! На месте остается лишь Ф1! Тем не менее перебор резко сокращается и в ЭВМ нахождением 96 полных решений займет краткий миг.

ferz_poz.gif (7065 bytes)

Для маркировки вертикалей вместо букв А..H используем цифры 1..8. Это значения переменной Х. Аналогично переменная Y обозначает текущую горизонталь. Занятые горизонтали отмечаем значениями R[Y]=1; если снимаем ферзя (делаем шаг назад) - R[Y]=0. Для идентификации диагоналей, направленных как главная диагональ, используем значения X+Y, для прочих - значение Y-X. Эти значения суммы и разности одинаковы для всех клеток лежащих на диагонали.

program Stack;
uses
crt;
Const N=8;
type
link = ^node;
node = record
key: integer;
next: link;
end;
Var
R: Array[1..N] of byte;
j,Y,X:Integer;
R1: Array[2..N+N] of Byte;
R2: Array[1-N..N-1] of Byte;
head, z: link;

procedure stackinit;
begin
new(head);
new(z);
head^.next:=z;
z^.next:=z;
end;

procedure push(v: integer);
var
t: link;
begin
new(t);
t^.key:=v;
t^.next:=head^.next;
head^.next:=t;
end;

function pop: integer;
var
t: link;
begin
t:=head^.next;
pop:=t^.key;
head^.next:=t^.next;
dispose(t);
end;

procedure st_print;
var
t: link;
str1, s: string;
i: integer;
begin
str1:='';
t:=head^.next;
while t<>z do
begin
str(t^.key, s);
str1:=str1+s;
t:=t^.next;
end;
for i:=1 to N do
write(str1[N-i+1]+' ');
readln;
end;

procedure stackdestroy;
begin
dispose(head);
dispose(z);
end;

Function Uspeh:Boolean;
Var
j: byte;
usp: Boolean;
Begin
usp:=false;
While (Y < N) And Not usp do
Begin
Y:= Y+1;
If R[Y] + R1[X+Y] + R2[Y-X] = 0 Then
usp:= true
Else
usp:= false
End;
Uspeh:= usp
End;

BEGIN
clrscr;
For Y:= 1 to N do
R[Y]:= 0;
For j:= 2 to N+N do
R1[j]:= 0;
For j:= 1-N to N-1 do
R2[j]:= 0;
stackinit;
j:= 0;
X:= 1;
Y:= 0;
Repeat
If Uspeh Then
Begin
push(Y);
If X < N Then
Begin
R[Y]:=1;
R1[X+Y]:=1;
R2[Y-X]:=1;
X:= X+1;
Y:=0;
End
Else
begin
st_print;
pop;
end;
End
Else
Begin
X:= X-1;
If X > 0 Then
Begin
y:=pop;
R[Y]:= 0;
R1[X+Y]:= 0;
R2[Y-X]:= 0;
End
End
Until X = 0;
Stackdestroy;
Readln;
END.

Заметим, что в основной программе шахматами и "не пахнет". Действительно, метод универсален, он применяется на графах и в других областях.

Итак, на сегодняшнем занятии Вы познакомились с абстрактной структурой данных - стеком.

Почта /// Структуры и алгоритмы