Вставка элемента в связанный список


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

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

program InserElement(input, output);
{Has the user type in integers and forms a linked list out of them,
then inserts an element at the end of that linked list and prints the
linked list with the added new element}

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes;

type
  tRefList = ^tList;
  tList = record
             info : integer;
             next : tRefList
            end;
var
 RefBeginning: tRefList;
 RefEnd : tRefList;
 Number : integer;



   procedure CreateList(var outRefBeginning: tRefList; var OutRefEnd: tRefList);
   { Creates a linear list through user input }
  var
   RefNew : tRefList;

  begin
   writeln('Please key in natural numbers. Key in 0 once you are done. ');
   readln(Number);
   while Number <> 0 do
   begin
     new (RefNew);
     RefNew^.info := Number;
     RefNew^.next := nil;
     if outRefBeginning = nil then
      begin
      outRefBeginning := RefNew;
      OutRefEnd := RefNew;
      end
     else
     begin
       outRefEnd^.next := RefNew;
       outRefEnd := RefNew
     end;
     readln (Number)
   end; { while-loop }
  end; {CreateList}

procedure InsertElement(inNumber : integer; var outRefBeginning : tRefList; var outRefEnd : tRefList);
  { Inserts a new element at the end of the list. outRefBeginning points to the first
  element of that list, outRefEnd points to the last element of it. The Value of inNumber is
  assigned to the record component info of the new element}

  var
   RefNew : tRefList;

  begin
  { Create and initialise new element }
  new(RefNew);
  RefNew^.info := inNumber;
  RefNew^.next := nil;
  { Insert element at the end of the linear list }
  if outRefBeginning = nil then
     begin
     outRefBeginning := RefNew;
     outRefEnd := RefNew
     end
     else
         begin
           outRefEnd^.next := RefNew;
           outRefEnd := RefNew;
         end;
  end;{ InsertElement }

  procedure PrintList;
  { Prints all elements of the linked list }

  var
   RefNew : tRefList;

  begin
   RefNew := RefBeginning;
   while RefNew <>  nil do
   begin
     writeln (RefNew^.info);
     RefNew := RefNew^.next
   end;
  end;

begin
  RefBeginning := nil;
  RefEnd := nil;
  CreateList(RefBeginning, RefEnd);
  InsertElement(5,RefBeginning,RefEnd);
  PrintList;
  readln;
end.


207
3
задан 26 января 2018 в 03:01 Источник Поделиться
Комментарии
1 ответ

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

Именования

Я нашел названия немного сбивают с толку. Почему это "Реф" список? К чему оно относится? (Или что значит ref значит, в данном контексте, если не "ссылка"?) Я думаю, что я бы назвал список узлов типа tNode вместо tListи я бы назвал, что указывает на его tList.

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

Типы

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

type
tNodePtr = ^tNode;
tNode = record
info : integer;
next : tNodePtr;
end;

tList = record
head : tNodePtr;
tail : tNodePtr;
end;

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

Проверьте Свои Отчисления

Есть 2 места, где вы называете new(). Вы никогда не проверить результат, чтобы увидеть, если выделение получилось. Вы должны убедиться, что память действительно была выделена, прежде чем начать писать его. В противном случае, вы в конечном итоге писать за некоторые другие сведения вызывая трудно найти ошибку, или запись данных вы не имеете доступа к и привело к аварии.

Удалить вещи, когда вы закончите с ним

Другое дело, что вам нужно сделать с памятью, выделяемой из кучи удалить его, когда вы больше не используете. В этом случае, что бы в конце программы. Я бы написал процедуру для удаления узлов из списка. Что-то вроде этого (и я предполагаю, что вы используете типы, которые я рекомендовал выше):

procedure DeleteList(var list : tList)
var
nextNode : tNodePtr;
currNode : tNodePtr;
begin
nextNode = list.head;
currNode = list.head;
while nextNode <> nil do
begin
nextNode = currNode^.next;
delete(currNode);
currNode = nextNode;
end;
list.head = nil;
list.tail = nil;
end;

(Примечание: прошло уже несколько лет, как я уже писал Паскаль, так что простите меня, если я сделал здесь все очевидные ошибки!)

Форматирование

При этом не влияют на работу программы, форматирование кода может повлиять на то, как легко читать и понимать. Я предлагаю принять согласованное количество символов. Я вижу, что вы иногда использовать 1 места, иногда 2. Я бы порекомендовал вам всегда использовать 2 или больше (мое предпочтение 4, лично), как единое пространство не так легко отличить как 2 или больше.

Также, похоже, в CreateList() в if класс имеет один тип отступов, и else пункт другой. Я хотел быть последовательными о том, что уровень отступа можно использовать для begin и end ключевые слова.

2
ответ дан 26 января 2018 в 06:01 Источник Поделиться