dydaktyka

Algorytmy i struktury danych

Grzegorz Bancerek
Politechnika Białostocka, I rok, I semestr, informatyka, magisterskie uzupełniające, 2007


Slajdy do wykładu, zjazd: I(06.10.2007), II(13.10.2007), III(27.10.2007), IV(17.11.2007), V(24.11.2007), VI(01.12.2007), VII(15.12.2007), VIII(12.01.2008), IX(19.01.2008). X(26.01.2008).
Rozkłady: wszystkie, ta specjalność (kopia).

Zasady zaliczenia laboratorium: Na każdych zajęciach podawany jest problem do sprogramowania. Za poprawne sprogramowanie problemu w czasie zajęć można uzyskać 2 punkty. Za oddanie i obronienie (należy odpowiedzieć na prę pytań) programu na następnych zajęciach otrzymuje się 1 punkt. Na ostatnich zajęciach punkty są przeliczane na oceny według tabeli:
punktyocena
0-3.9992
4-6.9993
7-9.9993+
10-12.9994
13-16.9994+
17-5

  1. 06.10.2007
    Wykład: Trzy algorytmy potęgowania, poprawność i złożoność algorytmu
    Pracownia specjalistyczna: Porównanie trzechch metod obliczania potęgi (patrz slady z wykładu). Należy dla każdej metody obliczyć ilość wykonanych mnożeń oraz podać czas działania (przykład oblicznia czasu działania: czas.pas). Żeby czas był miarodajny należy obliczenia wykonać odpowiednio dużą ilość razy (np. 30000). W drugim algorytmie należy wypisać tabelę potęg w postaci:
     P[0] = x^1 = 1.100
     P[1] = x^2 = 1.210
     P[2] = x^4 = 1.464
     ....
    
    oraz dokonać optymalizacji, tzn. wyeliminować niepotrzebne liczenia w pierwszej i drugiej pętli. W trzecim algorytmie należy wypisać wyrażenia odpowiadające niezmiennikowi pętli z konkretnymi danymi.
  2. 13.10.2007
    Wykład: Rzędy wielkości funkcji. Algorytmy obliczania symbolu Newtona - metoda dynamiczna
    Pracownia specjalistyczna: Porównanie metod obliczania symbolu Newtona (patrz slady z wykładu): Należy dla każdej metody obliczyć ilość wykonanych mnożeń (metody 1-4) lub dodawań (metody 5-7) oraz podać czas działania (przykład oblicznia czasu działania: czas.pas). Żeby czas był miarodajny należy obliczenia wykonać odpowiednio dużą ilość razy (np. 30000).
  3. 27.10.2007
    Wykład: Metody sortowania: wybieranie, wstawianie, bąbelkowe, Shella
    Pracownia specjalistyczna: Porównanie 3 sortowań: przez zliczanie, Shella i jednego z pozostałych.
    Należy wczytać liczby z pliku liczby.txt do trzech tablic. Każdą tablicę należy posortować inną metodą licząc porównania i przypisania w oddzielnych licznikach. Wynikowe tablice należy porównać i podać wartości liczników.
  4. 17.11.2007
    Wykład: Listy, kolejki, stosy. Sortowanie przez scalenie, metoda "dziel i zwyciężaj", wyszukiwanie w posortowanej tablicy.
    Pracownia specjalistyczna: Implementacja kolejki jako dwóch stosów:
    Stos należy zaimplementować jako listę liniową jednokierunkową a kolejkę jako rekord zawierający dwa stosy: jeden do wkładania elementów a drugi do pobierania. Jesli pobieramy pierwszy element z kolejki a stos do pobierania jest pusty, to wszystkie elementy ze stosu do wkładania są przerzucane na stos do pobierania i wtedy pobieramy element. Podobnie w przypadku operacji POP.
    type
      Lista = ^Element;
      Element = record
        liczba: integer;
        nast: Lista;
      end;
      Stos = Lista;
    
      function Pusty(S: Stos): boolean;
      function NaGorze(S: Stos): integer;
      procedure Push(var S: Stos; a: integer);
        { należy utworzyć nowy Element
          new(e)
          i przypisać
          e^.liczba := a
          i potem wstawić Element e na górze stosu (na początku listy)
        }
      procedure PopS(var S: Stos);
    
      procedure Przerzuc(var Sin, Sout: Stos); {przerzucanie elementów ze stosu Sin do Sout}
    
    type
      Kolejka = record
        stos_in, stos_out: Stos;
      end;
    
      function Pusta(K: Kolejka): boolean; {czy oba stosy są puste}
      function Pierwszy(K: Kolejka): integer;
        {podaje liczbę w pierwszym elemencie stos_out przerzucając wcześniej
         elementy ze stos_in jeśli trzeba}
      procedure Dodaj(var K: Kolejka; a: integer); {robi Push do stos_in}
      procedure PopK(var K: Kolejka);
        {usuwa pierwszy element ze stos_out przerzucając wcześniej
         elementy ze stos_in jeśli trzeba}
      
    

  5. 24.11.2007
    Wykład: Sortowanie przez kopcowanie, sortowanie przez wstawianie połówkowe, sortowanie leksykograficzne (pozycyjne). Drzewa binarnego wyszukiwania (BST)
    Wizualizacje: sortowanie przez kopcowanie, sortowanie leksykograficzne, operacje na drzewach BST.

    Pracownia specjalistyczna: Implementacja przy użyciu kolejek dwóch sortowań z trzech: sortowanie szybkie, leksykograficzne i przez scalanie.

    Aby zaimplementować sortowanie przez scalanie przy użyciu kolejek należy zaimplementować kolejki oraz funkcje

    void Dziel(kolejka *K, kolejka* K1, kolejka* K2) {
    // Dzieli kolejkę K na dwie części, które zapisuje do K1 i K2
    }
    
    void Scal(kolejka *K1, kolejka *K2, kolejka *K) {
    // scala posortowane kolejki K1 i K2 w pustą kolejkę K
    }
    
    void SortowaniePrzezScalanie(kolejka *K) {
      kolejka K1; Init(K1);
      kolejka K2; Init(K2);
      if (K.Count > 1) {
        Dziel(&K,&K1,&K2);
        SortowaniePrzezScalanie(&K1);
        SortowaniePrzezScalanie(&K2);
        Scal(&K1,&K2,&K);
      }
    }
    
    int main(){
    kolejka K;
    // Wczytanie z pliku 'dane.txt' liczb do sortowanie do kolejki K 
      SortowaniePrzezScalanie(&K);
    // Wypisanie kolejki K
    }
    

  6. 01.12.2007
    Wykład: Drzewa AVL i 2-3
    Pracownia specjalistyczna: Implementacja operacji na drzewach AVL.
  7. 15.12.2007
    Wykład: Algorytm Kruskala z UNION-FIND
    i algorytm Prima z kopcem Pracownia specjalistyczna: Porównanie implementacji algorytmu UNION-FIND. Zastosowanie w algorytmie Kruskala.
    {listowa}
      var Zbior: array[1..n] of 1..n;
      var Pierwszy: array[1..n] of 0..n; (* 0 - brak elementow we zbiorze *)
      var Nastepny: array[1..n] of 0..n; (* 0 - brak nastepnego elementu *)
    
      procedure Init1;
           (* Zbior[i]:=i, Pierwszy[i]:=i, Nastepny[i]:=0 *)
      function FIND1(i: integer): integer;
           (* zbior, do ktorego nalezy element i *)
           (* tzn. Zbior[i] *)
      procedure UNION1(i,j: integer);
           (* zakladamy, ze i <> j; dolaczamy zbior j do i *)
    
    {drzewiasta}
      var Ojciec: array[1..n] of 0..n;  (* 0 - brak ojca *)
      var Ilosc: array[1..n] of 1..n; (* ilosc reprezentowanych elementow *)
    
      procedure Init2; (* wpisuje zera do Ojciec i jedynki do Ilosc *)
      function FIND2(i: integer): integer;
           (* rekurencyjnie znajduje reprezentanta elementu i *)
           (* uzywajac tablicy Ojciec *)
      procedure UNION2(i,j: integer);  (* zakladamy, ze i <> j oraz i i j nie maja ojcow *)
                                      (* laczymy zbiory reprezentowane przez i i j *)
    {KRUSKAL}
      var Wedges: array[1..m] of record
            start, koniec, waga: integer;
          end;
      ReadGraph; { wczytuje z pliku m krawedzi (trojek liczb) }
      SortWedges; { sortuje krawedzie wg wag }
      Init_UNION_FIND;
      for i:=1 to m do
      begin
        p:=FIND(Wedges[i].start);
        k:=FIND(Wedges[i].koniec);
        if p <> k then
        begin
          { wypisz krawedz }
          UNION(p,k);
        end;
      end;
    

  8. 12.01.2008 Wykład: Algorytmy wyszukiwania najkrótszych dróg w grafie
    Pracownia specjalistyczna: Implementacja Algorytmu Dijkstry wyszukiwania najkrótszych dróg w grafie z wagami nieujemnymi.
  9. 19.01.2008 Wykład: Algorytmy wyszukiwania wzorca w tekście: KMP
    Pracownia specjalistyczna: Implementacja wybranego algorytmu wyszukiwania wzorca w tekście (oprócz naiwnego)
  10. 26.01.2008 Wykład: Szybka transformata Fouriera
    Pracownia specjalistyczna: Operacja dzielania wielomianów

Grzegorz Bancerek