Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Стек, заданный списком, на Паскале. (http://forum.oszone.net/showthread.php?t=136428)

ManHack 31-03-2009 20:02 1080364

Стек, заданный списком, на Паскале.
 
Есть стек, который задаётся списком (т.е. с динамическими переменными, а не через массив).
Т.к. стек действует по принципу LIFO, в нём элементы списка должны записаться в обратном порядке.
Вопрос: как вывести стек на экран? (как вывести список - понятно, нужно вывести именно стек)

Busla 31-03-2009 21:21 1080440

А вот фигушки - ничего не ответим, пока не покажешь решения Паскаль и NaN! :tongue:

ManHack 31-03-2009 21:36 1080462


pva 01-04-2009 12:33 1080981

Цитата:

Цитата ManHack
нужно вывести именно стек »

В чём отличие при выводе стека и списка?

ManHack 01-04-2009 15:21 1081122

Список выводит элементы попорядку, а стек - в обратном порядке.

Код:

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 не пользоваться ^^

pva 01-04-2009 20:59 1081395

ну так действия такие:
вариант 1:
1. загнать всё в массив (задом-наперёд)
2. вывести массив на экран (передом-назад)
вариант 2:
перевернуть монитор вниз-головой или смириться с ситуацией любым другим образом. Например пусть есть таблица логов. Её можно отрисовать по возрастанию даты, а можно по убыванию - так даже удобней будет.

Alan85 01-04-2009 21:44 1081437

Принципиально не верно стек сделан - последний элемент должен хранить адрес предыдущего т.е. 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;

Но это стирает стек - полностью его выталкивает, поэтому для отображения не верно все же :)

Busla 01-04-2009 23:37 1081526

Если надо исключительно через стек реализовать, то создать второй и перепихать в него результаты - получится обратный порядок. Эффективнее, конечно же, решать задачу не через стек.

Alan85, а если не стирает - это уже не стек ;)

Alan85 02-04-2009 07:52 1081670

Не ну одно дело вывести содержимое (посмотреть) а другое выкинуть его весь.. а вообще я бы все переписал с нуля - реально не уютно этим кодом пользоваться- интуиция. Да и процедуру push тоже надо переписать если идти от конца к началу.

ManHack 07-04-2009 23:48 1087360

А как идти от конца к началу?


Время: 10:22.

Время: 10:22.
© OSzone.net 2001-