niedziela, 20 listopada 2011

Algorytm poszukiwanie przez połowienie


Specyfikacja:

Dane: Zbiór elementów w postaci ciągu n uporządkowanych liczb x1<= x2<= …<=xn. Wyróżniony element y. Wynik: Jeśli y należy do tego zbioru, podaj miejsce (index) w ciągu, w przeciwnym razie sygnalizuj brak takiego elementu w zbiorze.

Algorytm:

Powtarzaj kroki 1-3, dopóki nie natrafisz na poszukiwany element.

Krok 1: Sprawdź element środkowy ciągu (gdy ciąg ma nieparzystą liczbę elementów) lub jeden z dwóch elementów środkowych (gdy ciąg ma parzystą liczbę elementów).

Krok 2: Jeśli jest on elementem poszukiwanym y, to zakończ algorytm.

Krok 3: Jeśli środkowy element jest większy od y, to pozostaw podciąg na lewo od elementu środkowego, a w przeciwnym wypadku (gdy element środkowy jest mniejszy od y), pozostaw podciąg na prawo od elementu środkowego.

Zadanie: Zapisz program „Zgadnij jaka to liczba?” odpowiadający na podane pytanie.
Wybierz partnera z grupy. Następnie partner wymyśli dowolną liczbę n z przedziały [1, 50], a Ty masz ją znaleźć, zadając mu pytania typu: „Czy to jest liczba …?” Na co Twój partner może jedynie odpowiedzieć : „Tak”- gdy trafiłeś, lub „Za mała”, „Za duża”- w zależności od położenia wybranej przez Ciebie liczby względem ukrytej liczby.

Wytłumaczenie do tego algorytmu z forum elektroda:
Jak się szuka? Mamy przykładowo 32 liczby, od zera do 31
1.
zakresDolny = 0
zakresGorny = 31

2.
pozycja = w połowie = (zakresDolny+zakresGorny)/2

3.
Jeżeli tablica[pozycja] == szukana to znaleziono, exit.

Jeżeli liczba w tablicy na pozycji `pozycja` jest mniejsza od szukanej, to przesuwamy dolny zakres nad aktualną pozycję, bo szukanej liczby na pewno nie będzie niżej (zakresDolny=pozycja+1).

Jeżeli liczba w tablicy na pozycji `pozycja` jest większa od szukanej, to znaczy że jesteśmy za wysoko, więc górna granica spada poniżej aktualnej pozycji: zakresGorny=pozycja-1.

Jeżeli górny zakres nie jest większy od dolnego, powtórz od kroku 2.


Jeżeli nie znaleziono liczby, to automatycznie mamy pozycję na którą można wstawić nową liczbę (przesuwając wszystkie elementy po `prawej` w `prawo` o jedną pozycję). Jest nią pozycja+x, gdzie x jest jedynką tylko wtedy, gdy ostatnie porównanie podniosło dolną granicę.

Kod:
On: Pomyślałem sobie liczbą od zera do 31, zgadnij jaką? (pomyślał sobie 9)
Ja: (liczę...)
zakresDolny = 0
zakresGorny = 31
połowa = (zakresDolny+zakresGorny)/2 = 15

Ja: pytam czy to 15
On: mniej

Ja: (liczę... zostały liczby 0-14)
zakresDolny = 0
zakresGorny = 15-1 = 14
połowa = (0+14)/2 = 7

Ja: pytam czy to 7
On: więcej

Ja: (liczę... zostały liczby 8-14)
zakresDolny = 7+1 = 8
zakresGorny = 14
połowa = (8+14)/2 = 11

Ja: pytam czy to 11
On: mniej

Ja: (liczę... zostały liczby 8,9,10)
zakresDolny = 8
zakresGorny = 11-1 = 10
połowa = (8+10)/2 = 9

Ja: pytam czy to 9
On: Tak

Implementacja w C++

#include <iostream>

using namespace std;

const int n = 50;
const int y = 10;

int wyszukaj (int p, int k, int tab[])
{
int l_zbioru = k - p;
int polowa_liczb = l_zbioru/2;
int srodek_zbioru = p + polowa_liczb;



    if ( y == tab[srodek_zbioru]) return tab[y];
    if (l_zbioru < 0) return 0;

    if ( y < tab[srodek_zbioru]  )
        {
           return wyszukaj(p,srodek_zbioru-1,tab);

        }

    if ( y > tab[srodek_zbioru] )  return  wyszukaj (srodek_zbioru+1,k,tab);



}
int main()
{
    int tab[n];
    for (int i = 1; i<=n; i++)
    {
        tab[i] = i;

    }

    cout << wyszukaj(1,n,tab);
    return 0;
}

1 komentarz:

  1. Trafiłem tu, poszukując tego algorytmu w c++. Również przygotowuje się do maturki z infy. Jeszcze po przeglądam resztę algorytmów na twoim blogu, są na pewno takie które i tak będę musiał ogarnąć.

    OdpowiedzUsuń