Lista jednokierunkowa i rekordy

0

Witam, mam problem z listą jednokierunkową. Mam listę z tytułami filmów w pliku .txt i chciałbym ją wczytać do listy jednokierunkowej oraz wyświetlić w Memo czy jakiejś Listbox. Umiem wczytać jakieś dane z pliku, umiem je wyświetlić. Tylko jak do tego wpleść tą listę jednokierunkową. Czytałem jakieś opisy (niestety w większości jest suchy opis lub jak tu http://4programmers.net/Delphi/Lista_jednokierunkowa przerasta to na razie moje zrozumienie problemu).

Zrobiłem to zadanie bez użycia listy jednokierunkowej (zadanie ma trochę więcej podpunktów), ale musi być z listą jednokierunkową. Czy ktoś mógłby trochę mnie naprowadzić na właściwy tor?

0

Skoro ten opis przerasta twoje zrozumienie to masz tylko trzy drogi:

  1. Poczytać jakiś kurs aby podciągnąć swoje zrozumienie
  2. Zamówić wykonanie
  3. Zmienić kierunek studiów

Ponieważ nawet nie próbowałeś sam dojść do pkt 1. obstawiam że właściwym dla ciebie będzie pkt 3.

1

@czarny Orzeł - przede wszystkim na początku zapoznaj się z tematyką list jednokierunkowych, bo bez tego ani rusz; Następnie poćwicz wykorzystanie wskaźników, bo w przypadku list to obowiązek - bez tego także ani rusz;

Kolejnym krokiem będzie napisanie sobie podstawy listy, najlepiej w postaci klasy, ale jeśli nie znasz wystarczająco obiektowości, to wystarczy zestaw procedur i funkcji do jej obsługi; A jak już kod będzie umożliwiał poprawne tworzenie i zwalnianie list, oraz co najmniej dodawanie nowego elementu i pobieranie wartości danego elementu, to wystarczy tylko dodać zapis i ładowanie danych z pliku;

W wymienionym artykule są podane dwie metody, które umożliwiają zapis i odczyt list; Tyle że zamiast używania metod WriteBuffer i ReadBuffer - Ty skorzystaj z Writeln i Readln;

Napisz coś, w razie czego pokaż kod i pytaj.

0

_13th_Dragon

  1. Czytałem opisy jakie znalazłem na temat listy jednokierunkowej, ale zrodziły więcej pytań niż odpowiedzi.
  2. Robię to dla siebie, więc jaki byłby cel?
  3. Skończyłem już studia, nie ma już czego zmieniać a szkoda bo jakbym mógł to bym zmienił.

furious programming - dzięki na coś takiego liczyłem, pojawily mi się te listy jednokierunkowe i nawet nie za bardzo wiedziałem gdzie się w to wgryźć. Tym bardziej, że często listy są porównywane do tablic, więc myślałem że są podobne i jest jakiś myk, którego nie rozumiem. Wychodzi, że różnice są większe i jest sporo do przestudiowania. Dzięki za wskazówki.

0

Tym bardziej, że często listy są porównywane do tablic, więc myślałem że są podobne i jest jakiś myk, którego nie rozumiem.

Napisz gdzie i kto porównuje listy do tablic, a furiat go odwiedzi;

Główną i ogromną różnicą pomiędzy standardowymi macierzami (potocznie tablicami) a listami jest to, że te pierwsze najczęściej (są wyjątki) zajmują jeden - ciągły blok pamięci; Natomiast węzły listy mogą zajmować randomowe adresy w pamięci - nie muszą występować zaraz po sobie;

Zaletą list jest to, że aby usunąć z niej dowolny węzeł, wystarczy przestawić jeden wskaźnik w poprzednim węźle, a ten usuwany zwolnić; W przypadku tablic jest to bardziej czasochłonne, dlatego że najpierw należy przesunąć dane z kolejnych elementów o jedno miejsce, a następnie skrócić macierz; Jak widzisz listy dają w tej materii dużą przewagę i zysk czasowy; Gorzej, jeśli chodzi o dostęp do jej węzłów; Aby odczytać dane z dowolnego węzła, najpierw trzeba przeiterować wszystkie poprzednie węzły; W przypadku macierzy jest to o wiele wygodniejsze, bo wiadomo pod jakim adresem znajduje się konkretna komórka;

Listy pozwalają też na ciekawą rzecz - można je zapętlić; Czyli sprawić, aby ostatni węzeł wskazywał na pierwszy - w ten sposób tworzy się lista zapętlona; Dzięki temu można bez końca przechodzić do kolejnego węzła, a w przypadku tablic trzeba sprawdzać czy korzysta się z ostatniego elementu i jeśli tak - ustawić indeks na początkowy (najczęściej 0); Użyteczny przykład takiej odmiany listy opisałem w swoim artykule - http://4programmers.net/Delphi/Gotowce/Bufor_cykliczny_jako_zapętlona_lista_jednokierunkowa - możesz zaglądnąć, jak temat Cię interesuje.

0

furious programming nawet w kompendium na 4 programmers lista jest porównywana do tablicy, moim błędem było założenie, że są bardziej podobne.

Poczytałem trochę więcej (jeszcze sporo przede mną), znalazłem nawet kod do aplikacji konsolowej dotyczący listy jednokierunkowej. Trochę się zacząłem nim bawić co trochę bardziej mi bardziej przybliżyło listę. Zetknąłem się jednak z problemem, który nie wiem jak ugryźć. Mam taki kod (ten, który znalazłem, ale po moich "próbach"):

type                                 // typ elementu listy jednokierunkowej
  PslistEl = ^slistEl;
  slistEl =  record
    next  : PslistEl;
    data  : integer;
    lol   : integer;
  end;

var
  L   : PslistEl;                    // wskaźnik początku listy
  e,f,p,r : PslistEl;                    // wskaźniki elementów listy
  n   : integer;                     // liczba elementów do posortowania
  v   : integer;                     // wartość elementu 1
  w   : integer;                     // wartość elementu 2
  i   : integer;                     // licznik elementów

begin
  new(L);                            // tworzymy pierwszego strażnika
  new(L^.next);                      // tworzymy drugiego strażnika
  L^.next^.next := nil;              // drugi strażnik jest ostatni na liście
  L^.next^.data := MAXINT;           // wartość drugiego strażnika

  read(n);                           // odczytujemy liczbę elementów

  for i := 1 to n do
  begin

    read(v);                         // czytamy element
    read(w);                         // czytamy element 2

    p := L;                          // p ustawiamy na pierwszego strażnika

    while v > p^.next^.data do       // szukamy miejsca wstawienia
      p := p^.next;

    new(e);                          // tworzymy nowy element
    new(f);

    e^.data := v;                    // inicjujemy element
    f^.lol := w;
    e^.next := p^.next;
    f^.next := p^.next;

    p^.next := e;                    // element wstawiamy do listy L
  end;

  p := L^.next;                      // listę przesyłamy na wyjście

  while p^.next <> nil do
  begin
    write(p^.data,' ');
    write(p^.lol,' ');
    p := p^.next;
  end;

  writeln;

  while L <> nil do                  // usuwamy listę z pamięci
  begin
    e := L;
    L := L^.next;
    dispose(e);
  end;

  ReadLn;
  end.

Teraz jeśli dobrze rozumiem record może zawierać ile danych chce (np. mógłbym wpisać całą obsadę filmu i to każde nazwisko jako osobny element)?

Idąc dalej spróbowałem dołożyć element do recordu (w).

W pierwsze części nic nie dopisywałem bo jeśli dobrze rozumiem L odnosi się do PslistEl a to do mojego rekordu, w którym już jest w.

Dalej wczytujemy v i w.

I teraz dochodzimy do pętli sortującej i tu sie pojawiają schody.

Pierwotnie było new(e) czyli stworzenie nowego elementu; e się odnosi do w dalszej części do v. Czy żeby uwzględnić w musze stworzyć nowy osobny element? (stworzyłem f)

Potem jest wstawienie elementu do listy i znowu powinienem wstawić je osobno czy jako "pakiet"?

dodanie znacznika <code class="delphi"> - @furious programming

1

Nie wiem skąd masz ten kod ale najprawdopodobnej jest on z d**y.

Weź ten artykuł http://4programmers.net/Delphi/Lista_jednokierunkowa tylko zamiast

type
  TData = Word;

Wstaw sobie to:

type
  TData = record
    Tytul_FIlmu : string[255];
    Rezyser : string[255]
    Rok_Produkcji : Word
    Premiera : Word
  end;

Albo dowolne inne dane, które są Ci potrzebne.
I przeanalizuj punkt po punkcie.

I nie mów, że artykuł przekracza twoje możliwości poznawcze, bo pisaliśmy go razem z @furious programming tak by każdy mógł zrozumieć.

0

@sf - Twój kod jest nieczytelny; Po części dlatego, że praktycznie cały kod jest "lowercase", a po drugie Twój kod jest strukturalny, liniowy, całość umieszczona jest w głównej sekcji modułu, a do tego dochodzi kupka zmiennych globalnych...

Sformatuj kod, nazwij zmienne i pola rekordu sensowniej, dorzuć trochę wielkich liter i co najmniej opakuj całość w czytelne procedury - łątwiej będzie zrozumieć kod i co za tym idzie pomóc rozwiązać problem.

0

Próbuje dalej :P

Mam taki kod jak poniżej. Na razie mam dwa problemy, po pierwsze nie wiem dlaczego ale przy pierwszej próbie dodania elementów do listy tylko w listbox2 pojawia mi sie podana wartość. Dodaje następną i tu pojawia się już w obu rubrykach. Gdzieś ta wartość ginie nie wiem dlaczego. Drugi problem jaki napotkałem to jak wpisuje jakąś wartość to wszystkie rekordy zamieniają się na tą wartość. Ktoś może ma jakieś sugestie, które wyprowadzą mnie z błędu?

type
  wskaznik = ^Lista;

  Lista = record
    lp : string;
    dane : string;
    wsk : wskaznik;
  end;

var
  Form1 : TForm1;
  First, current : wskaznik;
  tekst : string;
  liczba : string;
  i, k : integer;


implementation

{$R *.lfm}

{ TForm1 }

procedure AddToList(dane : string; lp : string; var current : wskaznik);
var
  prev, Next : wskaznik;
begin
  if current <> nil then
  begin
    prev := current;
    Next := current^.wsk;
  end
  else
  begin
    prev := nil;
    Next := nil;
  end;

  new(current);
  current^.dane := dane;
  current^.lp := lp;
  current^.wsk := Next;
  if prev <> nil then
    prev^.wsk := current;
end;


procedure GetAddr(dane : string; var First, current : wskaznik);
var
  Next : wskaznik;
begin
  if First <> nil then
  begin
    Next := First;
    repeat
      if Next^.wsk <> nil then
        Next := Next^.wsk
    until (Next^.wsk = nil) or (Next^.dane = dane);
    current := Next;
  end;
end;


procedure GetNum(n : integer; var First, current : wskaznik);
var
  Next : wskaznik;
begin
  if First <> nil then
    if n = 1 then
      current := First
    else
    if (n = 2) and (First^.wsk = nil) then
      n := 0
    else
    begin
      Next := First;
      i := 1;
      repeat
        Inc(i);
        if Next^.wsk <> nil then
          Next := Next^.wsk
      until (i = n) or (Next^.wsk = nil);
      if (Next^.wsk = nil) and (i < n) then
        n := 0
      else
        current := Next;
    end;
end;

procedure List;
var
  l : integer;
begin
  form1.listbox1.Clear;
  form1.listbox2.Clear;
  for l := 1 to i do
  begin
    Getnum(l, First, current);
    if l > 1 then
      form1.listbox1.items.add(current^.dane);
    form1.listbox2.items.add(current^.lp);
  end;
end;


procedure findLess(dane : string; lp : string; var First, current : wskaznik);
var
  tmp, Next : wskaznik;
begin
  if First <> nil then
  begin
    Next := First;
    repeat
      if (Next^.wsk <> nil) then
      begin
        tmp := Next;
        Next := Next^.wsk;
      end;
    until (Next^.wsk = nil) or (Next^.dane > dane);
    if Next^.dane > dane then
      current := tmp
    else
      current := Next;
    if Next^.lp > lp then
      current := tmp
    else
      current := Next;
  end;
end;

procedure TForm1.Button1Click(Sender : TObject);
begin
  Inc(i);
  findLess(edit1.Text, edit2.Text, First, current);
  addtolist(edit1.Text, edit2.Text, current);
  label3.Caption := 'Elementów: ' + IntToStr(i - 1);
  edit1.SetFocus;
  list;
end;




end.

dodanie znacznika <code class="delphi"> - @furious programming

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