Паскаль - Динамический связный список

Ответить
creble
Сообщения: 4
Зарегистрирован: 27 мар 2008, 09:28

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

Код: Выделить всё

program KUR2;
uses crt;
const
n=4;
type
  pnode=^node;
  node=record
    inf:string[12];
    next :p node;
  end;
var
i:integer;
head,p :p node;
procedure View;
  begin
  if p^.next <> nil then
    begin
      writeln(p^.inf);
      p:=p^.next;
      View;
    end
  else exit;
  end;
begin
new(head);
head^.inf:='information';
head^.next:=nil;
p:=head;
for i:=1 to n do
  begin
    new(p^.next);
    p^.next^.inf:='information';
    p^.next^.next:=nil;
    p:=p^.next;
  end;
view;
repeat until keypressed;
end.
По моей задумке, программа должна выдать четыре надписи "information", помогите исправить.
Serge_Bliznykov
Сообщения: 375
Зарегистрирован: 31 авг 2007, 03:06

Измените процедуру вывода View на, например такой код:

Код: Выделить всё

procedure View;
begin
  p:=head;
  WriteLn('All elements of list...');
  while p <> nil do
    begin
      writeln(p^.inf);
      p:=p^.next;
    end
end;
второе. я бы не рекомендовал для тестирования использовать ОДНИ И ТЕ ЖЕ ДАННЫЕ !!
ну, хотя бы так:

Код: Выделить всё

var s : string;
...
  head^.inf:='Head Info';
      ...
  for i:=1 to n do
    begin
      new(p^.next);
      Str(i:1,S);
      p^.next^.inf:= S + ' information';
   ...
Serge_Bliznykov
Сообщения: 375
Зарегистрирован: 31 авг 2007, 03:06

&quot писал(а):По моей задумке, программа должна выдать четыре надписи "information", помогите исправить.
кстати, почему четыре?? один раз вы заносите в head
и потом цикл for i:=1 to n do, где n = 4 - т.е. плюс ещё четыре ^.inf:='information';
всего пять.... :-)
BBB
Сообщения: 1298
Зарегистрирован: 27 дек 2005, 13:37

creble, в Вашем таксте после цикла добавления p указывает на последний элемент списка, а p^.next равен Nil. Так что пр-ра View сразу же пойдет на else exit;
Попробуйте так, как написал Serge_Bliznykov. Использование рекурсии там, где без этого можно обойтись - не очень хорошая идия :)
creble
Сообщения: 4
Зарегистрирован: 27 мар 2008, 09:28

BBB
Нужно именно рекурсивную процедуру, к сожалению, задания составлял не я.
Воспользовавшись вашими советами, привел все к виду:

Код: Выделить всё

program KUR2;
uses crt;
const
n=4;
type
  pnode=^node;
  node=record
    inf:string;
    next :p node;
  end;
var
i:integer;
S:string;
head,p :p node;
procedure View;
begin
  while p <> nil do
    begin
      writeln(p^.inf);
      p:=p^.next;
      View;
    end
end;
begin
new(head);
head^.inf:='Head information';
head^.next:=nil;
p:=head;
for i:=1 to n do
  begin
    new(p^.next);
    str(i:1,S);
    p^.next^.inf:='Element #'+S+' information';
    p^.next^.next:=nil;
    p:=p^.next;
  end;
writeln('All elements of list...');
p:=head;
View;
repeat until keypressed;
end.
Всем спасибо за помощь!
BBB
Сообщения: 1298
Зарегистрирован: 27 дек 2005, 13:37

creble писал(а):Нужно именно рекурсивную процедуру, к сожалению, задания составлял не я.
Тогда, мне кажется, симпатичнее было бы не использовать в качестве текущей позиции при просмотре списка глобальную переменную (p), а передавать ее параметром.
Да и ЦИКЛ, пожалуй, ненужен, можно вернуться к Вашему первоначальному варианту с if-ом. Точнее, даже if не нужен получается. Пр-ру View, по-сути надо называть ViewSubList, т.к. ее действия заключаются в выводе информации о "текущем" узле и рекурсивный вызов для следющего узла списка.

Примерно так:

Код: Выделить всё

procedure ViewSubList (pCurrent : pnode);
begin
  if (pCurrent <> nil) then
    begin
      writeln (pCurrent^.inf);
      ViewSubList (pCurrent^.next);
    end;
end;
 
begin
  .........................
  writeln('All elements of list...');
  ViewSubList (head);
  repeat until keypressed;
end.
konstantine
Сообщения: 4
Зарегистрирован: 01 сен 2010, 10:40

Здравствуйте Ребята.
Пишу курсовую по предмету Структуры обработки Алгоритмов данных

Решил использовать двусвязные списки и разобраться как работают с указателиями в delphi.
Вот программа(не работаеющая) ругается при выводе списка на экран.

Код: Выделить всё

type
  Plog = ^log;
    log = Record
      Wday:       String[3];
      Month:      String;
      MonthN:     Integer;
      Time:       String[8];
      Yea:        String[4];
      Duration:   integer;
      IP:         String;
      CODE:       String;
      Bytes:      integer;
      Metod:      String;
      URL:        String;
      Client:     String;
      IerarcheCode: String;
      TypeInfo:   String;
      Next,Prev:  Plog;
  end;
  ST = array[1..14] of String;

type
  TForm1 = class(TForm)
    Vivod: TButton;
    StringGrid1: TStringGrid;
    Zamena: TButton;
    Delete: TButton;
    Sort: TButton;
    procedure VivodClick(Sender: TObject);
    procedure CreateList(List: Plog);
    procedure AddToList(List: Plog; A: ST);
    procedure ViewList(List: Plog; i: integer);
    procedure DelToList(List, Kyrsor: Plog);
//Дважды связный список Лог (ОСиАЛД стр. 48)

var
  Tlog,head,foot: Plog;
  Form1: TForm1;

implementation

{$R *.xfm}



procedure TForm1.AddToList(List: Plog; A: ST);
var P: Plog;
begin
  if List<>nil then
    begin
    New(P);
    P.Wday:=A[1];
    P.Month:=A[2];
    P.MonthN:=StrToInt(A[3]);
    P.Time:=A[4];
    P.Yea:=A[5];
    P.Duration:=StrToInt(A[6]);
    P.IP:=A[7];
    P.CODE:=A[8];
    P.Bytes:=StrToInt(A[9]);
    P.Metod:=A[10];
    P.URL:=A[11];
    P.Client:=A[12];
    P.IerarcheCode:=A[13];
    P.TypeInfo:=A[14];
    P^.Next:=Nil;
    P^.Prev:=List.Next;
    List^.Next:=P.Prev;
    //Сдвигаем указатель КОНЦА списка
    Foot:=P;
    end
  else
    begin
    List.Wday:=A[1];
    List.Month:=A[2];
    List.MonthN:=StrToInt(A[3]);
    List.Time:=A[4];
    List.Yea:=A[5];
    List.Duration:=StrToInt(A[6]);
    List.IP:=A[7];
    List.CODE:=A[8];
    List.Bytes:=StrToInt(A[9]);
    List.Metod:=A[10];
    List.URL:=A[11];
    List.Client:=A[12];
    List.IerarcheCode:=A[13];
    List.TypeInfo:=A[14];
    List^.Next:=NIL;
    List^.Prev:=NIL;
    //Устанавливаем указатели НАЧАЛА и КОНЦА списка
    Head:=List;
    Foot:=List;
    end;
end;

procedure TForm1.CreateList(List: Plog);
begin
//Создаём "голый" список
New(List);
List.Next:=NIL;
List.Prev:=NIL;
end;


procedure TForm1.DelToList(List,kyrsor: Plog);
begin
//обработка удаления
end;

procedure TForm1.ViewList(List: Plog; i: integer);
begin
while List<>nil do
  begin
    StringGrid1.Cells[1,i]:=List^.Wday;
    StringGrid1.Cells[2,i]:=List^.Month;
    StringGrid1.Cells[3,i]:=IntToStr(List^.MonthN);
    StringGrid1.Cells[4,i]:=List^.Time;
    StringGrid1.Cells[5,i]:=List^.Yea;
    StringGrid1.Cells[6,i]:=IntToStr(List^.Duration);
    StringGrid1.Cells[7,i]:=List^.IP;
    StringGrid1.Cells[8,i]:=List^.CODE;
    StringGrid1.Cells[9,i]:=IntToStr(List^.Bytes);
    StringGrid1.Cells[10,i]:=List^.Metod;
    StringGrid1.Cells[11,i]:=List^.URL;
    StringGrid1.Cells[12,i]:=List^.Client;
    StringGrid1.Cells[13,i]:=List^.IerarcheCode;
    StringGrid1.Cells[14,i]:=List^.TypeInfo;
//    List:=List^.Next;
    i:=i+1;
//    ViewList(List,i);
    ViewList(List^.Next,i);
  end;
end;

procedure TForm1.VivodClick(Sender: TObject);
var
f: TextFile;
P: Plog;
i,k,r: integer;
S: String;
A: ST;
z: boolean;
begin

AssignFile(f,'C:\Documents and Settings\qwerty\Рабочий стол\CAOD\access.log');
Reset(f);  //Открытие файла на чтение
k:=1;

CreateList(Tlog);
//Считываем файл по строчно
//while not EOF(f) do
while (StringGrid1.RowCount<=500) do
  begin
  //Открывем файл на чтение
  Read(f,S);
  //Очищаем на временный массив
  for i:=1 to k do
    A[i]:='';

  i:=1;
  r:=0;
  k:=1;
  //Начинаем разбирать считанную строку на слова и запихивать в НАШ СПИСОК
  while i<=length(S) do
    begin
    if (S[i]<>' ') then
      begin
      r:=1;
      A[k]:=A[k]+S[i];
      end
      else
        if r=1 then
          begin
          r:=0;
          k:=k+1;
          end;
    i:=i+1;
    end; { while i<=length(S) }
  Readln(f); //Переходим на новую строку

  AddToList(Tlog,A);

{  //Выводим на экран
  for i:=1 to k do
    StringGrid1.Cells[i,StringGrid1.RowCount]:=A[i]; }

  StringGrid1.RowCount:=StringGrid1.RowCount+1;
  end;

  ViewList(Head,1);

CloseFile(f);
end;

end.

Всё сообщение не влазиет в 5000 символов
konstantine
Сообщения: 4
Зарегистрирован: 01 сен 2010, 10:40

Суть работы программы такой она хватает файлик и начинает по строчно считывать из него данные. Считав строку она каждое слово строки загоняет в массив и потом уже этот массив заноситься двусвязный список(мне пока так удобней чес сразу непосредственно в список загонять). Так вот далее я просто тупо пытаюсь вывести этот список на экран в поля объекта StringGrid1.
Пока в данный момент времени программа считывает только первые 500 строк, а не весь файл, потому что он 190Мб и дальше я буду учиться сортировать эти данные по различным атрибутам, удалять/добавлять/изменять строки. но это ещё рано т.к. не могу разобраться с синтаксисом и работой с указателями.

Не моглибы помочь где ошибка в синтаксисе и в логике.
konstantine
Сообщения: 4
Зарегистрирован: 01 сен 2010, 10:40

Сейчас пока победил проблему работы программы вот этим:


я подставил в процедуре
procedure TForm1.AddToList(List: Plog; A: ST);
var P: Plog;
begin
if List<>nil then
begin
New(P);
P.Wday:=A[1];
P.Month:=A[2];
P.MonthN:=StrToInt(A[3]);
P.Time:=A[4];
P.Yea:=A[5];
P.Duration:=StrToInt(A[6]);
P.IP:=A[7];
P.CODE:=A[8];
P.Bytes:=StrToInt(A[9]);
P.Metod:=A[10];
P.URL:=A[11];
P.Client:=A[12];
P.IerarcheCode:=A[13];
P.TypeInfo:=A[14];
P^.Next:=Nil;
P^.Prev:=List.Next;
List^.Next:=P.Prev;
Foot:=P;
end
else
begin
New(List); // <<<<<<------ вот что я подставил....
List.Wday:=A[1];
List.Month:=A[2];
List.MonthN:=StrToInt(A[3]);
List.Time:=A[4];
List.Yea:=A[5];
List.Duration:=StrToInt(A[6]);
List.IP:=A[7];
List.CODE:=A[8];
List.Bytes:=StrToInt(A[9]);
List.Metod:=A[10];
List.URL:=A[11];
List.Client:=A[12];
List.IerarcheCode:=A[13];
List.TypeInfo:=A[14];
List^.Next:=NIL;
List^.Prev:=NIL;
Head:=List;
Foot:=List;
end;
end;

+ при пошаговой отработке алгоритма я заметил что в процедуру не передаётся Список Tlog, т.е. если первый раз Tlog сохдаётся он пуст и равен = null и он сам непосредственно заполняется данными, то второй раз при заходе в этой процедуре при проверке if List<>nil then список опять оказывается пустым, как будто он не передаётся в процедуру через аргумент....
konstantine
Сообщения: 4
Зарегистрирован: 01 сен 2010, 10:40

Всё пока разобрался получилось так:

Код: Выделить всё

//Создание и добавления в список
procedure TForm1.AddToList(List: Plog; A: ST);
var P: Plog;
begin
  if TLog<>nil then
    begin
    New(P);
    P^.Wday:=A[1];
    P^.Month:=A[2];
    P^.MonthN:=StrToInt(A[3]);
    P^.Time:=A[4];
    P^.Yea:=A[5];
    P^.Duration:=StrToInt(A[6]);
    P^.IP:=A[7];
    P^.CODE:=A[8];
    P^.Bytes:=StrToInt(A[9]);
    P^.Metod:=A[10];
    P^.URL:=A[11];
    P^.Client:=A[12];
    P^.IerarcheCode:=A[13];
    P^.TypeInfo:=A[14];
    P^.Next:=Nil;
    P^.Prev:=TLog;
    TLog^.Next:=P;
    Tlog:=P;
    Foot:=Tlog;
    end
  else
    begin
    New(TLog);
    TLog^.Wday:=A[1];
    TLog^.Month:=A[2];
    TLog^.MonthN:=StrToInt(A[3]);
    TLog^.Time:=A[4];
    TLog^.Yea:=A[5];
    TLog^.Duration:=StrToInt(A[6]);
    TLog^.IP:=A[7];
    TLog^.CODE:=A[8];
    TLog^.Bytes:=StrToInt(A[9]);
    TLog.Metod:=A[10];
    TLog.URL:=A[11];
    TLog.Client:=A[12];
    TLog.IerarcheCode:=A[13];
    TLog.TypeInfo:=A[14];
    TLog^.Next:=NIL;
    TLog^.Prev:=NIL;
    Head:=TLog;
    Foot:=TLog;
    end;
end;

//Вывод головы
procedure TForm1.ViewListHead(List: Plog);
var i: integer;
begin
i:=1;
while List<>nil do
  begin
    StringGrid1.Cells[1,i]:=List^.Wday;
    StringGrid1.Cells[2,i]:=List^.Month;
    StringGrid1.Cells[3,i]:=IntToStr(List^.MonthN);
    StringGrid1.Cells[4,i]:=List^.Time;
    StringGrid1.Cells[5,i]:=List^.Yea;
    StringGrid1.Cells[6,i]:=IntToStr(List^.Duration);
    StringGrid1.Cells[7,i]:=List^.IP;
    StringGrid1.Cells[8,i]:=List^.CODE;
    StringGrid1.Cells[9,i]:=IntToStr(List^.Bytes);
    StringGrid1.Cells[10,i]:=List^.Metod;
    StringGrid1.Cells[11,i]:=List^.URL;
    StringGrid1.Cells[12,i]:=List^.Client;
    StringGrid1.Cells[13,i]:=List^.IerarcheCode;
    StringGrid1.Cells[14,i]:=List^.TypeInfo;
    i:=i+1;
    List:=List^.Next;
  end;
end;

//Вывод ног
procedure TForm1.ViewListFoot(List: Plog);
var i: integer;
begin
i:=1;
while List<>nil do
  begin
    StringGrid1.Cells[1,i]:=List^.Wday;
    StringGrid1.Cells[2,i]:=List^.Month;
    StringGrid1.Cells[3,i]:=IntToStr(List^.MonthN);
    StringGrid1.Cells[4,i]:=List^.Time;
    StringGrid1.Cells[5,i]:=List^.Yea;
    StringGrid1.Cells[6,i]:=IntToStr(List^.Duration);
    StringGrid1.Cells[7,i]:=List^.IP;
    StringGrid1.Cells[8,i]:=List^.CODE;
    StringGrid1.Cells[9,i]:=IntToStr(List^.Bytes);
    StringGrid1.Cells[10,i]:=List^.Metod;
    StringGrid1.Cells[11,i]:=List^.URL;
    StringGrid1.Cells[12,i]:=List^.Client;
    StringGrid1.Cells[13,i]:=List^.IerarcheCode;
    StringGrid1.Cells[14,i]:=List^.TypeInfo;
    i:=i+1;
    List:=List^.Prev;
  end;
end;

Ответить