Pierwszy wolny element listy

0

Witam.
Załóżmy,że implementuje w pascalu liste dwukierunkową pewnych elementów które to zawierają pole ID będące indeksem elementu.
Elementy w liście są sortowane rosnąco według ID,ale nie muszą rosnąć co jeden(sytuacja gdy kilka środkowych elementów zostało usuniętych i jeden element ma indeks np 6 a następny już ID:=12)
Wymogiem listy jest,aby następny dodawany element został umieszczony w miejscu pierwszego wolnego ID.
Jak określić warunek dla szukania następnego wolnego indeksu?
Próbowałem czegoś takiego

while((p^.next^.id)<(p^.id + 1))do
begin
  p:=p^.next;
end;

Ale nie wydaje mi się,żeby to mogło zadziałać.Czy znajdzie się ktoś kto mnie naprowadzi na rozwiązanie tego problemu?

0

Jeżeli chcesz użyć bieżącego i następnego węzła do porówniania to pętla musi zapewniać istnienie tych dwóch wymaganych węzłów, a Twoja w ogóle niczego nie sprawdza - uruchomienie tego najpewniej spowoduje wykroczenie poza listę i rzucenie wyjątku SIGSEGV;

Moja sugestia:

while (p <> nil) and (p^.next <> nil) and (p^.next^.id < p^.id + 1) do
  p := p^.next;

Przy czym jest to rozwiązanie dość nieczytelne i pasowało by skorzystać z pomocniczych zmiennych.

0

Właściwie to miałem te warunki napisane,tylko we wcześniejszej części procedury.Cała wygląda tak:

 procedure addStudent(var sVar:studentVar);
var
  temp,p:Pstudent;
begin
  p:=sVar.head;
  new(temp);
  writeln('imie studenta')
  readln(temp^.name);
  if(sVar.head=nil)then
  begin
    temp^.id:=0;
    temp^.books:=0;
    temp^.next:=nil;
    temp^.prev:=nil;
    new(temp^.BookList);
  end else
  if(p^.next=nil)then
  begin
    temp^.id:=1;
    temp^.books:=0;
    temp^.next:=nil;
    temp^.prev:=p;
  end else
  begin
    while((p^.next^.id)<(p^.id + 1))do
    begin
      p:=p^.next;
    end;

  end;

end; 

czy coś jest złego w tym kodzie?

0

czy coś jest złego w tym kodzie?

Formatowanie jest złe, pod wieloma względami; Poza tym część rzeczy należałoby skrócić, czyli wydzielić pewne instrukcje na zewnątrz; Czym jest StudentVar? Nazwa nic nie mówi o przeznaczeniu tego typu; Do czego służy temp, skoro oprócz inicjalizacji, nic z tą zmienną nie jest wykonywane?

Inicjalizację pól można wydzielić:

function FillStudent(AID, ABooks: Integer; ANext, APrev: PStudent; ACreateList: Boolean): PStudent;
begin
  New(Result);
  
  Result^.ID := AID;
  Result^.Books := ABooks;
  Result^.Next := ANext;
  Result^.Prev := APrev;
  
  if ACreateList then
    New(Result^.BooksList);
end;

Kod właściwej procedury skróci się, a jego czytelność wzrośnie:

procedure AddStudent(var AVar: StudentVar);
var
  P, Temp: PStudent;
begin
  P := AVar.Head;

  {...}

  if P = nil then
    Temp := FillStudent(0, 0, nil, nil, True)
  else
    if P^.Next = nil then
      Temp := FillStudent(1, 0, nil, P, False)
    else
      while P^.Next^.ID < P^.ID + 1 do
        P := P^.Next;

  {...}
end;

Poza tym pobieranie danych z klawiatury nalezy wywalić z procedury AddStudent; Procedura ta ma za zadanie dodać nowy węzeł do listy, na podstawie danych wejściowych; Dlatego też najpierw pobierz dane od użytkownika, a te przekaż do procedury AddStudent.

1 użytkowników online, w tym zalogowanych: 0, gości: 1