Lista jednokierunkowa - usuwanie wielokrotnie pojawiającego się elementu.

0

Witam. Mam pytanie, jak usunąć element, który pojawia się wielokrotnie. To jest kod, który do tej pory mam napisany. Pozostaje mi tylko jedno - w wynikowej mam usunąć wszystkie elementy mające daną =1.

program project1;
type
  wskaznik = ^element;
  element =  record
    next  : wskaznik;
    dana  : integer;
  end;
var
  L : wskaznik;
  e : wskaznik;
  i : integer;
  tmp: wskaznik;

function ilosc(p : wskaznik) : byte;
var
  c : byte;
begin
  c := 0;
  while p <> nil do
  begin
    inc(c);
    p := p^.next;
  end;
  ilosc := c;
end;
procedure wyswietl(p : wskaznik);
begin
  writeln('Liczba elementow : ',ilosc(p));
  write('Elementy: ');
  while p <> nil do
  begin
    write(p^.dana,',');
    p := p^.next;
  end;
  writeln;
end;
procedure dodaj_przod(var head : wskaznik; v : integer);
var
  p : wskaznik;
begin
  new(p);
  p^.dana := v;
  p^.next := head;
  head := p;
end;
function dodaj_tyl(var head : wskaznik; v : integer):boolean;
var
  p,e : wskaznik;
begin
  new(e);
  e^.next := nil;
  e^.dana := v;
  p := head;
  if p = nil then
    head := e
  else
  begin
    while p^.next <> nil do p := p^.next;
    p^.next := e;
  end;
  dodaj_tyl:=true;
end;
procedure wstaw_przed(var head : wskaznik; e : wskaznik; v : integer);
var
  p : wskaznik;
begin
  p := head;
  if p = e then dodaj_przod(head,v)
  else
  begin
    while p^.next <> e do p := p^.next;
    new(p^.next);
    p^.next^.next := e;
    p^.next^.dana := v;
  end;
end;
procedure wstaw_po(e : wskaznik; v : integer);
var
  p : wskaznik;
begin
  new(p);
  p^.next := e^.next;
  p^.dana := v;
  e^.next := p;
end;
procedure usun_przod(var head : wskaznik);
var
  p : wskaznik;
begin
  p := head;
  if p <> nil then
  begin
    head := p^.next;
    dispose(p);
  end;
end;
procedure usun(var head : wskaznik; e : wskaznik);
var
  p : wskaznik;
begin
  if head = e then usun_przod(head)
  else
  begin
    p := head;
    while p^.next <> e do p := p^.next;
    p^.next := e^.next;
    dispose(e);
  end;
end;
function wyswietl_jeden(e : wskaznik):integer;
var
  p : wskaznik;
begin
 if e <> nil then wyswietl_jeden:=e^.dana else
 wyswietl_jeden:=0;
end;
begin
  L := nil;

  for i := 1 to 10 do
      begin
           dodaj_tyl(L,1);
           dodaj_tyl(L,2);
           dodaj_tyl(L,3);
      end;
  wyswietl(L);
  writeln;
  e := L;
  while e <> nil do begin
        if e^.dana = 3 then wstaw_po(e,4);
        e := e^.next;
  end;

  wyswietl(L);
  writeln;
  e := L;
  i:=1;
  write('Co 5 element: ');
  while e <> nil do begin
  if (i mod 5) = 0 then write(e^.dana,',');
  e := e^.next;
  i:=i+1;
  end;
  e:=L;
  while e <> nil do begin
  if e^.dana = 1 then write('tak ');
  e:=e^.next;
 end;
  L:=e;
  writeln;
  writeln(wyswietl_jeden(e));
  wyswietl(L);
  writeln;
  readln;
end.

Tutaj mam kod, który wyświetla elementy o wartości 1. Ale mam problem z ich usunięciem.

  e:=L;
  while e <> nil do begin
  if e^.dana = 1 then write('tak ');
  e:=e^.next;
 end;
  L:=e;
1

Do'h, chętnych nie widać...

Ja niestety odkąd poznałem programowanie obiektowe mam dość sporą niechęć do strukturalnego, więc nie analizowałem Twojego kodu; Z racji tej, że zwykle wykorzystuję gotową implementację list nie mam wprawy w tworzeniu własnej, a analiza czyjejś przyprawia mnie o ból głowy, więc mogę jedynie doradzić teoretyczne rozwiązanie; Także szkoda, że mając do dyspozycji OOP wolisz pisać strukturalnie;

Widzę, że masz zaimplementowane procedury służące np. do pobierania ilości węzłów listy czy do jej wyświetlania; W obu przypadkach masz zaimplementowany kod iterujący po każdym węźle; To samo musisz zrobić, by pousuwać każdy element o danej wartości, czyli tak samo iterując sprawdzasz czy aktualny węzeł posiada szukaną wartość; Jeśli tak - przepisujesz do poprzedniego adres na kolejny element (pomijając usuwany), a aktualny zwalniasz z pamięci; I tak aż do końca listy; Bądź ostrożny, bo łatwo pogubić referencję do kolejnych węzłów; Także uważaj przy usuwaniu pierwszego węzła jeśli pasuje do wzorca, bo należy ustawić jako głowę listy adres drugiego węzła;

Poza tym kod nie jest dobrze sformatowany, przez co jest dość nieczytelny; Popracuj też nad identyfikatorami, bo są mało intuicyjne, przez co analiza kodu jest utrudniona.

0
  e:=L;
  p:=nil;
  while e<>nil do
  begin
     if e^.dana=1 then
     begin
        n:=e^.next;
        if p<>nil then p^.next:=n;
        else L:=n;
        dispose(e);
        e:=n;
     end
     else
     begin
        p:=e;
        e:=e^.next;
     edn;
  end;

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