Показать полную графическую версию : Стек, заданный списком, на Паскале.
Есть стек, который задаётся списком (т.е. с динамическими переменными, а не через массив).
Т.к. стек действует по принципу LIFO, в нём элементы списка должны записаться в обратном порядке.
Вопрос: как вывести стек на экран? (как вывести список - понятно, нужно вывести именно стек)
А вот фигушки - ничего не ответим, пока не покажешь решения Паскаль и NaN (http://forum.oszone.net/thread-128870.html)! :tongue:
http://www.animereactor.ru/forum/style_emoticons/default/catty26.gif
нужно вывести именно стек »
В чём отличие при выводе стека и списка?
Список выводит элементы попорядку, а стек - в обратном порядке.
type
tData = integer;
tPtr = ^tNode;
tNode = record
data: tData;
next: tPtr;
end;
tStack = record
first, last: tPtr;
end;
var
S: tStack;
D: tData;
function NotEmpty (var S: tStack): boolean; {проверка стека на пустоту}
begin
NotEmpty := S.First <> nil;
end;
procedure Build (var S: tStack; D: tData); {первоначальное заполнение стека}
var
f: text;
p: tPtr;
begin
assign (f,'stack.txt');
reset (f);
S.First := nil;
S.Last := nil;
while not eof(f) do begin
New(p);
readln (f, D);
p^.data := D;
if S.First = nil then
S.First := p
else
S.Last^.next := p;
S.Last := p;
end;
close(f);
end;
procedure Push (var S: tStack; D: tData); {добавить элемент}
var
p: tPtr;
begin
write ('Item = ');
readln (D);
New(p);
p^.data := D;
S.Last^.next := p;
D := 0;
end;
procedure Pop (var S: tStack; var D: tData); {изъять элемент}
var
p: tPtr;
begin
if NotEmpty(S) then begin
D := S.Last^.data;
p^ := S.Last^;
S.Last := S.Last^.next;
p^.next := nil;
{ Dispose(p); }
end;
end;
procedure Clear;
begin
end;
procedure Echo (S: tStack); {вывод стека на экран}
var
p: tPtr;
begin
{p^ := S.Last^;}
while S.Last <> nil do begin
Pop (S, D);
writeln (D);
Echo (S);
end;
end;
В данном случае ECHO возвращает последний элемент стека и два нолика.
Почему?
Может я и правда каких-то серьёзных ошибок в этом коде не вижу?
Если что, хотелось бы пользоваться только p^.next, а p^.prev не пользоваться ^^
ну так действия такие:
вариант 1:
1. загнать всё в массив (задом-наперёд)
2. вывести массив на экран (передом-назад)
вариант 2:
перевернуть монитор вниз-головой или смириться с ситуацией любым другим образом. Например пусть есть таблица логов. Её можно отрисовать по возрастанию даты, а можно по убыванию - так даже удобней будет.
Принципиально не верно стек сделан - последний элемент должен хранить адрес предыдущего т.е. 1<-2<-3<-4... а тут 1->2->3->4. Поэтому после выдавливания последнего элемента указатель last теряется... - адреса 3 элемента не найдет (если только перебором от 1 до 3).
Вот как подправил я:
procedure Build (var S: tStack; D: tData); {первоначальное заполнение стека}
var
f: text;
p: tPtr;
begin
assign (f,'stack.txt');
reset (f);
S.First := nil;
S.Last := nil;
while not eof(f) do begin
New(p);
readln (f, D);
p^.data := D;
if S.First = nil then begin
S.First := p; s.last:=p end
else
begin
p^.next := s.last;
S.Last := p;
end;
end;
close(f);
end;
procedure Echo (var S: tStack); {вывод стека на экран}
var
p: tPtr;
begin
{p^ := S.Last^;}
while S.last <> s.first do begin
Pop (S, D);
write (D,' ');
// Echo (S);
end;
Pop (S, D);
write (D,' ');
end;
Но это стирает стек - полностью его выталкивает, поэтому для отображения не верно все же :)
Если надо исключительно через стек реализовать, то создать второй и перепихать в него результаты - получится обратный порядок. Эффективнее, конечно же, решать задачу не через стек.
Alan85, а если не стирает - это уже не стек ;)
Не ну одно дело вывести содержимое (посмотреть) а другое выкинуть его весь.. а вообще я бы все переписал с нуля - реально не уютно этим кодом пользоваться- интуиция. Да и процедуру push тоже надо переписать если идти от конца к началу.
А как идти от конца к началу?
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.