background image

1

Wykład 3

Metoda „dziel i 

zwyciężaj”

background image

2

Wprowadzenie

 Technika konstrukcji algorytmów

 dziel i zwyciężaj.

  przykładowe problemy:

– Wypełnianie planszy
– Poszukiwanie (binarne)
– Sortowanie (sortowanie przez łączenie - merge sort).

background image

3

Wypełnianie planszy

Zadanie: dysponując klockami

oraz planszą 
2

n

x2

n

 z 

brakującym 
polem:

Wypełnić plansze 
w całości:

background image

4

Wypełnianie planszy: przypadki trywialne (n = 1)

 Przypadek trywialny (n = 1): wypełniamy plansze jednym 

klockiem:

Idea dla rozwiązania problemu – doprowadzić 
rozmiar zadania do przypadku trywialnego, 
który umiemy rozwiązać

background image

5

Wypełnianie planszy : podział zadania

 Oryginalną planszę dzielimy na 4 części

Dostajemy problemy o rozmiarze 2

n-1

x2

n-

1

Ale: trzy z nich nie są podobne do 
oryginalnego (plansze nie mają 
brakującego pola)! 

background image

6

Wypełnianie planszy : podział zadania

 pomysł: umieszczamy jeden klocek w środku planszy i 

dokonujemy podziału na 4 części

Teraz otrzymujemy 4 plansze o rozmiarach 2

n-1

x2

n-1

.

Każda z planszy ma brakujące pole

background image

7

Wypełnianie planszy : algorytm

INPUTn  – plansza 2

n

x2

n

L – pozycja brakującego pola. 

OUTPUT: wypełniona plansza

Tile(n, L)
   if n = 1 then
      przypadek trywialny
      wypełnij jednym klockiem
      
return
   umieść jeden klocek w środku planszy 

podziel planszę na 4 równe części
Niech L1, L2, L3, L4 oznaczają pozycje 4 brakujących pól

   Tile(n-1, L1)
   Tile(n-1, L2) 
   
Tile(n-1, L3) 
   
Tile(n-1, L4) 

INPUTn  – plansza 2

n

x2

n

L – pozycja brakującego pola. 

OUTPUT: wypełniona plansza

Tile(n, L)
   if n = 1 then
      

przypadek trywialny

      wypełnij jednym klockiem
      
return
   umieść jeden klocek w środku planszy 

podziel planszę na 4 równe części
Niech L1, L2, L3, L4 oznaczają pozycje 4 brakujących pól

   Tile(n-1, L1)
   Tile(n-1, L2) 
   
Tile(n-1, L3) 
   
Tile(n-1, L4) 

background image

8

Dziel i zwyciężaj

 Metoda konstrukcji algorytmów „Dziel i zwyciężaj” :

– Jeśli problem jest na tyle mały, że umiesz go rozwiązać  - zrób to. 

Jeśli nie to:

• Podział: Podziel problem na dwa lub więcej rozdzielnych 

podproblemów

• Rozwiązanie: Wykorzystaj metodę rekurencyjnie dla 

rozwiązania tych podproblemów

• Łączenie: połącz rozwiązania podproblemów tak, aby 

rozwiązać oryginalny problem

background image

9

Wypełnianie planszy : Dziel i zwyciężaj

 Wypełnianie jest przykładem algorytmu „dziel i zwyciężaj” :

– w wypadku trywialnym (2x2) – po prostu wypełniamy planszę, lub:
– Dzielimy planszę na 4 mniejsze części (wprowadzając wypełnione 

miejsce w rogu, przez umieszczenie centralnie jednego klocka)

– Rozwiązujemy problem rekursywnie stosując tą samą metodę
– Łączymy części umieszczając klocek w środku planszy

background image

10

 Odnaleźć 

liczbę w posortowanej tablicy:

– Przypadek trywialny – tablica jest jednoelementowa
– Albo dzielimy tablice na dwie równe części i rozwiązujemy 

zadanie osobno dla każdej z

 nich

Poszukiwanie binarne

INPUT: A[1..n] – posortowana niemalejąco tablica liczb, s – liczba. 
OUTPUT
: indeks taki, że A[j] = s. NIL, jeśli (1jn): A[j] s 
Binary-search(A, p, r, s):
   if p = r then 
      if 
A[p] = s then return p
      else return NIL 
   q(p+r)/2
   ret  Binary-search(A, p, q, s)
   if ret = NIL then 
      return Binary-search
(A, q+1, r, s)
   else return ret      

INPUT: A[1..n] – posortowana niemalejąco tablica liczb, s – liczba. 
OUTPUT
: indeks taki, że A[j] = s. NIL, jeśli (1jn): A[j] s 
Binary-search(A, p, r, s):
   if p = r then 
      if 
A[p] = s then return p
      else return NIL 
   q(p+r)/2
   ret  Binary-search(A, p, q, s)
   if ret = NIL then 
      return Binary-search
(A, q+1, r, s)
   else return ret      

background image

11

Rekurencja

 Czas działania algorytmu z odwołaniami rekursywnymi można opisać 

poprzez rekurencję

 Równanie/nierówność opisująca funkcję poprzez jej wartości dla 

mniejszego argumentu

Przykład: poszukiwanie binarne

(1)

  if 

1

( )

2 ( / 2)

(1)  if 

1

n

T n

T n

n



 

background image

12

Poszukiwanie binarne (poprawione)

INPUT: A[1..n] – posortowana niemalejąco tablica liczb, s – liczba. 
OUTPUT
: indeks taki, że A[j] = s. NIL, jeśli (1≤jn): A[j] ≠s 

Binary-search(A, p, r, s):
   if p = r then 
      if A[p] = s then return p
      
else return NIL 
   q
(p+r)/2
   if A[q]  s then return Binary-search(A, p, q, s)
   else return Binary-search(A, q+1, r, s)

INPUT: A[1..n] – posortowana niemalejąco tablica liczb, s – liczba. 
OUTPUT
: indeks taki, że A[j] = s. NIL, jeśli (1≤jn): A[j] ≠s 

Binary-search(A, p, r, s):
   if p = r then 
      if A[p] = s then return p
      
else return NIL 
   q
(p+r)/2
   if A[q]  s then return Binary-search(A, p, q, s)
   else return Binary-search(A, q+1, r, s)

 T(n) = (n) – nie lepiej niż dla metody siłowej!
 Poprawa: rozwiązywać zadanie tylko dla jednej połowy tablicy

background image

13

Czas działania metody

T(n) = (lg n) !

(1)

  if 

1

( )

( / 2)

(1)  if 

1

n

T n

T n

n



 

background image

14

Sortowanie przez łączenie (merge sort)

 Podziel: Jeśli posiada przynajmniej dwa elementy (1 lub 0 

elementów – przypadek trywialny), podziel na dwie równe (z 
dokładnością do 1 elementu) części S

1

 i S

2

. (tj. S

1

 zawiera 

pierwsze n/2elementów, a S

2

 kolejne n/2).

 Zwyciężaj: posortuj sekwencje S

1

 i S

2

 stosując Merge Sort.

 Połącz: Połącz elementy z dwóch posortowanych sekwencji S

1

 i 

S

2

 w sekwencję zachowaniem porządku

background image

15

Algorytm – Merge Sort

Merge-Sort(A, p, r)
   if p < r then
      q(p+r)/2

      Merge-Sort(A, p, q)
      Merge-Sort(A, q+1, r)
      Merge(A, p, q, r)

Merge-Sort(A, p, r)
   if p < r then
      q(p+r)/2

      Merge-Sort(A, p, q)
      Merge-Sort(A, q+1, r)
      Merge(A, p, q, r)

Merge(A, p, q, r)
   wybieramy mniejszy z dwóch elementów na początku 
sekwencji
 A[p..q] oraz A[q+1..r] i wkładamy go do 
sekwencji wynikowej, przestawiamy odpowiedni znacznik. 
Powtarzamy to aż do wyczerpania się elementów. 
Rezultat kopiujemy do A[p..r]. 

Merge(A, p, q, r)
   wybieramy mniejszy z dwóch elementów na początku 
sekwencji
 A[p..q] oraz A[q+1..r] i wkładamy go do 
sekwencji wynikowej, przestawiamy odpowiedni znacznik. 
Powtarzamy to aż do wyczerpania się elementów. 
Rezultat kopiujemy do A[p..r]. 

background image

16

Sortowanie przez łączenie - 1

background image

17

Sortowanie przez łączenie - 2

background image

18

Sortowanie przez łączenie - 3

background image

19

Sortowanie przez łączenie - 4

background image

20

Sortowanie przez łączenie - 5

background image

21

Sortowanie przez łączenie - 6

background image

22

Sortowanie przez łączenie - 7

background image

23

Sortowanie przez łączenie - 8

background image

24

Sortowanie przez łączenie - 9

background image

25

Sortowanie przez łączenie - 10

background image

26

Sortowanie przez łączenie - 11

background image

27

Sortowanie przez łączenie - 12

background image

28

Sortowanie przez łączenie - 13

background image

29

Sortowanie przez łączenie - 14

background image

30

Sortowanie przez łączenie - 15

background image

31

Sortowanie przez łączenie - 16

background image

32

Sortowanie przez łączenie - 17

background image

33

Sortowanie przez łączenie - 18

background image

34

Sortowanie przez łączenie - 19

background image

35

Sortowanie przez łączenie - 20

background image

36

Sortowanie przez łączenie - 21

background image

37

Sortowanie przez łączenie - 22

background image

38

Sortowanie przez łączenie – podsumowanie 

 Sortowanie liczb

– jeśli n=1 – trywialne 
– rekursywnie sortujemy 2 ciągi 

n/2 i n/2 liczb

– łączymy dwa ciągi w czasie (n)

 Strategia 

– Podział problemu na mniejsze, ale 

analogiczne podproblemy

– Rekursywne rozwiązywanie 

podproblemów

– Łączenie otrzymanych rozwiązań

background image

39

Sortowanie przez łączenie – czas działania

 Czas działania algorytmu może 

być reprezentowany przez 
następującą zależność 
rekurencyjną:

 Po rozwiązaniu dostajemy:

(1)

  if 

1

( )

2 ( /2)

( )  if 

1

n

T n

T n

n

n



 

)

lg

(

)

(

n

n

n

T

background image

40

Wieże Hanoi

 Mamy 3 wieże oraz stos 64 dysków o zmniejszających się 

średnicach umieszczonych na pierwszej wieży

 Potrzebujemy przenieść wszystkie dyski na inną wieżę
 Zabronione jest położenie dysku  większego na mniejszym
 W każdym kroku wolno mam przenieść tylko jeden dysk

background image

41

Wieże Hanoi

background image

42

Rozwiązanie rekursywne

background image

43

Algorytm rekursywny

INPUTn  – ilość dysków , a, b, c – wieże, wieża a zawiera wszystkie 

dyski. 

OUTPUT: a, b, c – wieże, wieża b zawiera wszystkie dyski

Hanoi(n, a, b, c)
      
if  n = 1 then
          Move(a,b);
      
else
          Hanoi(n-1,a,c,b);
          
Move(a,b);
          
Hanoi(n-1,c,b,a);

INPUTn  – ilość dysków , a, b, c – wieże, wieża a zawiera wszystkie 

dyski. 

OUTPUT: a, b, c – wieże, wieża b zawiera wszystkie dyski

Hanoi(n, a, b, c)
      
if  n = 1 then
          Move(a,b);
      
else
          Hanoi(n-1,a,c,b);
          
Move(a,b);
          
Hanoi(n-1,c,b,a);

Poprawność algorytmu łatwo pokazać przez indukcję względem n.

background image

44

Ilość kroków

 Ilość kroków M(n) potrzebnych 

do rozwiązania problemu dla  
dysków spełnia zależność 
rekurencyjną

M(1) = 1

M(n) = 2M(n-1) + 1

n

M(n)

1

1

2

3

3

7

4

15

5

31

background image

45

Ilość kroków

 Rozwijając tę zależność dostajemy

    M(n) 

= 2M(n-1) + 1

     

= 2*[2*M(n-2)+1] + 1 = 2

*

 

M(n-2) + 1+2

     

= 2

* [2*M(n-3)+1]  + 1 + 2

     

= 2

*

 

M(n-3) + 1+2 + 2

=…

 Po k krokach

M(n) = 2

*

 

M(n-k) + 1+2 + 2

+ … + 2

n-k-1

 Dla k = n-1

M(n) 

= 2

n-1 

*

 

M(1) + 1+2 + 2

+ … + 2

n-2

= 1 + 2 + … + 2

n-1 

= 2

n

-1

background image

46

Projekt 

 Uogólnić zadanie o wieżach Hanoi dla k wież


Document Outline