• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Problem ze zrozumieniem przykładu algorytmu w książce Cormena

Object Storage Arubacloud
+1 głos
365 wizyt
pytanie zadane 22 lipca 2019 w Matematyka, fizyka, logika przez Sonit Nowicjusz (180 p.)

Fragment książki "Wprowadzenie do algorytmów" - Thomas H. Cormen:

Mamy dany projekt układu mechanicznego w postaci listy rodzajów części składowych, z których każda może zawierać inne części. Chcemy wypisać elementy tej listy w takiej kolejności, żeby każda część występowała wcześniej niż dowolna część, która ją wykorzystuje. Jeśli układ składa się z n rodzajów części, to jest n! możliwych uporządkowań. Ponieważ silnia rośnie jeszcze szybciej niż funkcja wykładnicza, nie jesteśmy w stanie wygenerować każdego możliwego uporządkowania, a potem sprawdzać, czy przy tym uporządkowaniu każda część występuje przed częściami, które ją wykorzystują (chyba że części jest bardzo mało).

Rozumiem to, że silnia rośnie szybciej niż funkcja wykładnicza, ale nie mogę zrozumieć tego, że nie jesteśmy w stanie wygenerować każdego możliwego uporządkowania, a potem sprawdzać, czy przy tym uporządkowaniu każda część występuje przed częściami, które ją wykorzystują. 

Rozumiem, że byłoby to mało efektywne ale czemu niemożliwe?

1 odpowiedź

+2 głosów
odpowiedź 22 lipca 2019 przez Chess Szeryf (76,710 p.)
wybrane 24 lipca 2019 przez Sonit
 
Najlepsza

Pamięć komputerów osobistych jest dość ograniczona jak i szybkość przeprowadzanych operacji. Z powodu braku wystarczającej wielkości pamięci przy bardzo dużych liczbach dostałbyś chyba overflow (przepełnienie).

 Chcemy wypisać elementy tej listy w takiej kolejności, żeby każda część występowała wcześniej niż dowolna część, która ją wykorzystuje.

Przyjmijmy, że sokowirówka (będzie ich kilka typów oznaczone numerami) to część, która występuje wcześniej (ponieważ wykorzystuje jakiś owoc), a elementy listy to owoce.

(list :juicer1 'apple :juicer3 'pear :juicer2 'orange :juicer4 'cherry :juicer5 'lemon)

Dla pięciu różnych rodzajów sokowirówek i owoców mamy 5! możliwości, czyli 120. Dla 6!=720, 7!=5040; itd..

Dla 7! możliwości mamy np. wprawić w ruch pętlę, która wykona aż 5040 obrotów, przecież to nie optymalne. Korzystając chociażby ze struktury danych - listy pozbywamy się tego problemu.

gigamonkeys.com/.../Common_Lisp

Poniższa lista może być uporządkowana na 3! możliwości.

[1][]->[2][]->[3][NIL]

1 2 3
1 3 2
2 3 1
2 1 3
3 2 1
3 1 2

Kolejność obojętna, ważne żeby juicer+ był przed (owoc)*.

juicer - sokowirówka

Jeśli się nie mylę, to ten problem to jest po prostu sortowanie. Poniżej przedstawię sortowanie listy jednokierunkowej przez scalanie.

(1 3 2) ; input
(1 3 2 nil) ; input, but with append element nil, that was even number of elements 
((1 2) (3 nil))
((1) (2) (3) (nil))
((1 2) (3 nil))
(1 2 3 nil) ; output

Złożoność algorytmu merge sort.

Czasowa: O(n * log (n))

Pamięciowa: O(n)

wikipedia.org

;;; Helper function to tell us if a given sequence has just one element.
(defun single (sequence)
  (if (consp sequence)
      (not (cdr sequence))
      (= (length sequence) 1)))

;;; Sequence can be a vector or a list. Note that this means that this
;;; code isn't optimized for any of those.
(defun merge-sort (sequence)
  (if (or (null sequence) (single sequence))
      sequence
      (let ((half (truncate (/ (length sequence) 2))))
        ;; MERGE is a standard common-lisp function, which does just
        ;; what we want.
        (merge (type-of sequence)
               (merge-sort (subseq sequence 0 half))
               (merge-sort (subseq sequence half))
               #'<))))

Implementacja algorytmu merge sort - licencja GFDL

Cechy Algorytmu Sortowania Przez Scalanie

klasa złożoności obliczeniowej optymistyczna O(n log n)
klasa złożoności obliczeniowej typowa O(n log n)
klasa złożoności obliczeniowej pesymistyczna O(n log n)
Sortowanie w miejscu NIE
Stabilność TAK

źródło

Jeśliby założono, że pojedyncza instrukcja wykonuje się jedną nanosekundę (czyli na komputerze działającym z częstotliwością 1 GHz) wtedy czasy wykonania względem rozmiaru danych wyglądałyby następująco:

Złożoność obliczeniowa względem rozmiaru danych wejściowych

Rozmiar danych 10 20 50 100
n 10 ns 20 ns 50 ns 100 ns
n! 3.6 ms 77 lat 9.6 * 10^44 lat 3 * 10^141 lat

W tabeli n - O(n); n! O(n!).

Jeśli więc jesteśmy w stanie rozwiązać postawione zadanie algorytmem o złożoności nie większej niż wielomianowej, wtedy mamy szansę na rozwiązanie zadania w realnym/rozsądnym czasie. Jeśli zaś algorytm posiada złożoność ponadwielomianową, wtedy w praktyce wykonywanie algorytmu dla większej ilości danych, nigdy się ne zakończy,gdyż często rozwiązanie trwałoby dłużej niż szacowany wiek Wszechświata (ok. 1010 lat)! Warto więc rozważać złożoność obliczeniową algorytmów, gdyż bez niej nawet dokładny i poprawny algorytm może się dla nas realnie nigdy nie zakończyć!

źródło

Widać już chyba dlaczego przy złożoności O(n!) niemozliwe jest doczekanie się na sensowny rezultat w sensownym czasie. Zgodnie z przykładem, już przy rozmiarze danych wejściowych 10 widać, że przy tej złożoności czas wykonania to 3.6 milisekundy, czyli 0.0036 sekundy, gdzie przy złożoności O(n) jest to zaledwie 10 nanosekund - 0.000000010 sekundy.

sortowanie przez scalanie złożoność obliczeniowa złożoność obliczeniowa

Podobne pytania

0 głosów
0 odpowiedzi 172 wizyt
pytanie zadane 21 kwietnia 2021 w Algorytmy przez wojtek_suchy Mądrala (6,880 p.)
+1 głos
4 odpowiedzi 496 wizyt
pytanie zadane 6 stycznia 2016 w C i C++ przez kacperoo7 Nowicjusz (200 p.)
0 głosów
5 odpowiedzi 2,326 wizyt
pytanie zadane 20 października 2015 w Algorytmy przez starzec Początkujący (410 p.)

92,556 zapytań

141,403 odpowiedzi

319,559 komentarzy

61,942 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...