materiał do pobrania
Transkrypt
materiał do pobrania
Klasyczne algorytmy działające na tablicach Poznałeś już tablicę i podstawową obsługę zmiennych tego typu, pora więc przejść do realizacji algorytmów, które działają na tablicach. 1. Przeszukiwanie liniowe tablicy jednowymiarowej Przykład Zajmijmy się problemem poszukiwania wyróżnionego elementu w jednowymiarowej tablicy. Zakładamy przy tym, że element, którego szukamy, może się w tablicy znajdować lub nie. W tym celu kolejno, począwszy od pierwszego elementu, będziemy sprawdzać, czy napotkana wartość jest elementem szukanym. Nazwijmy go szuk. Jeśli już pierwszy element tablicy (oczywiście pierwszym elementem jest element indeksowany zerem!) okaże się poszukiwanym elementem, przeszukiwanie zakończymy, a na wyjściu pojawi się informacja, że element szukany znajduje się w tablicy. W przeciwnym wypadku sprawdzamy, czy drugi element jest równy elementowi szukanemu, i tak postępujemy aż do ostatniego elementu tablicy. Przeszukiwanie tablicy metodą element po elemencie nazywamy przeszukiwaniem liniowym. Po każdym przebiegu pętli musimy oczywiście skontrolować, czy nie sprawdzamy ostatniego elementu tablicy, aby nie wyjść poza zakres tablicy. Specyfikacja problemu algorytmicznego i opis użytych zmiennych Problem algorytmiczny: Znalezienie wyróżnionego elementu w tablicy Dane wejściowe: Tablica tab [ n ], gdzie n to rozmiar tablicy, szuk ∈ R - szukany element w tablicy tab Dane wyjściowe: Informacja o znalezieniu (bądź nie) elementu szuk Zmienne pomocnicze: i ∈ N ; i ∈{0,..., n − 1} Zapiszmy algorytm w postaci listy kroków: 1. Wczytaj tablicę n-elementową, pobierz wartość elementu szukanego szuk. 2. Zmiennej pomocniczej i przypisz wartość 0. 3. Jeśli i jest mniejsze od n, przejdź do kroku 4, w przeciwnym wypadku wypisz „Element nie został znaleziony" i zakończ. 4. Jeśli tab[i] jest różne od szuk, zwiększ o 1 wartość zmiennej i i przejdź do kroku 3. 5. Wypisz „Element został znaleziony" i zakończ. Ryc. 5.7. Schemat blokowy wyszukiwania w tablicy wyróżnionego elementu Porównaj schemat blokowy algorytmu (ryc. 5.7) z zapisem w postaci listy kroków, a następnie przeanalizuj program: Analiza złożoności obliczeniowej algorytmu przeszukiwania liniowego Policzmy, ile w tym algorytmie wykonuje się operacji dominujących, czyli mających wpływ na szybkość działania algorytmu. Załóżmy, że w tablicy nie ma szukanego elementu. Wówczas dla każdego elementu tablicy wykonujemy dwa porównania: czy jego indeks świadczy o tym, że element mieści się w zakresie tablicy, oraz czy element jest elementem szukanym. Przeanalizuj kod funkcji, która przeszukuje tablicę w celu znalezienia elementu: while { i++; } (i<10 && tablica[i]!=szukany) A zatem dla n elementów wykonujemy w najgorszym wypadku 2n porównań. Złożoność obliczeniowa tego algorytmu jest więc złożonością liniową. Liczbę porównań da się zmniejszyć dzięki zastosowaniu algorytmu przeszukiwania liniowego z wartownikiem. 2. Przeszukiwanie liniowe tablicy jednowymiarowej z wartownikiem Podczas przeszukiwania tablicy w poprzednim przykładzie musieliśmy za każdym obiegiem pętli wykonywać dwie czynności: porównywać kolejne elementy tablicy z wartością poszukiwaną i sprawdzać, czy wartość indeksu tablicy nie przekracza dozwolonego zakresu. Poznasz teraz metodę przeszukiwania liniowego tablicy z tak zwanym wartownikiem pozwalającą nam zrezygnować z „pilnowania" wyjścia poza zakres tablicy. Dodajmy do tablicy dodatkowy element o poszukiwanej wartości i ustawmy go na końcu. Ten właśnie element nazywamy wartownikiem. W tak zmodyfikowanej tablicy zawsze znajdziemy element szukany (przecież sami wpisaliśmy go na końcu tablicy), mamy więc pewność, że algorytm skończy swoje działanie, zanim wyjdzie poza zakres tablicy. Aby móc wykorzystać metodę z wartownikiem, musisz użyć tablicy o liczbie elementów o jeden większej niż liczba elementów do sprawdzenia. Dodatkowy element na końcu tablicy jest przeznaczony na umieszczenie w nim wartownika. Jeśli w przeszukiwanej tablicy nie ma szukanego elementu, to algorytm znajdzie ten ostatni, dodatkowy. Dzięki takiemu rozwiązaniu algorytm nie musi za każdym razem sprawdzać, czy dotarł do końca tablicy. Wystarczy, że po znalezieniu szukanego elementu sprawdza, czy jest on elementem dodatkowym (to znaczy: czy ma indeks n). Jeśli tak, to wyprowadzony zostanie napis mówiący, że w tablicy nie ma szukanej wartości (pamiętasz, że wartownik nie jest elementem badanej tablicy). W sytuacji pesymistycznej, gdy elementu szukanego nie było w wejściowej tablicy, algorytm wykona n operacji porównań oraz jedno dodatkowe - sprawdzi, czy znaleziony element jest wartownikiem. Mimo że zmniejszyliśmy dwukrotnie liczbę operacji, to klasa złożoności tego algorytmu się nie zmieniła i wynosi O(n), czyli jest liniowa - podobnie, jak w przeszukiwaniu liniowym. Na schemacie blokowym z ryciny 5.8 wyraźnie zauważalna jest mniejsza liczba dokonywanych porównań niż w zapisie algorytmu w postaci listy kroków (specyfikacja jak w przykładzie wcześniejszym). Ryc. 5.8. Schemat blokowy wyszukiwania z wartownikiem wyróżnionego elementu w tablicy Lista kroków algorytmu: 1. Utwórz tablicę o rozmiarze o 1 większym niż wielkość badanej tablicy i wypełnij ją elementami przeszukiwanej tablicy. 2. Wczytaj wartość elementu szukanego szuk. 3. Na końcu (po ostatnim elemencie) przeszukiwanej tablicy dopisz element o wartości szuk. 4. Zmiennej pomocniczej i (indeks tablicy) przypisz wartość 0. 5. 5. Jeśli tab[i] = szuk, przejdź do kroku 7. 6. Zwiększ zmienną i o 1 i przejdź do kroku 5. 7. Jeśli i < n, wypisz „Element został znaleziony" i zakończ. 8. Wypisz „Element nie został znaleziony" i zakończ. Poniżej przedstawiamy samą funkcję przeszukującą tablicę z wartownikiem (reszta programu wyglądałaby analogicznie jak w metodzie przeszukiwania liniowego, bez użycia wartownika): void szukaj_z_wartownikiem(int tablica[11], int szukany) { int i; tablica[10] = szukany; i = 0; while (tablica[i]!=szukany) i++; if (i<10) cout << "Element zostal znaleziony"; else cout << "Element nie zostal znaleziony"; } Chociaż szukamy elementu w tablicy dziesięcioelementowej, w programie tworzymy tablicę jedenastoelementową, gdyż pamiętamy, że ostatnim elementem jest wartownik niebędący elementem badanej tablicy.