Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву
Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Temat 7. Kolejki priorytetowe.Содержание книги Поиск на нашем сайте Jest to najbardziej ogólny rodzaj kolejek. Spośród elementów stojących w kolejce pobierany jest element o najwyższym priorytecie, a przy równych priorytetach ten element który wcześniej stanął w kolejce. Zwykła kolejka może być traktowana jako kolejka priorytetowa, w której priorytet jest określony przez czas wejścia do kolejki. Implementacja kolejki zależy od charakteru zbioru priorytetów. a)- z nieograniczonym zbiorem wartości priorytetów - nieuporządkowane wstawianie na koniec kolejki (złożoność O(1)) usuwanie elementu o najwyższym priorytecie (pierwszego z równych) (złożoność O(N)) - uporządkowane, wykorzystujące: -- uporządkowaną listę lub tablicę usuwanie z początku kolejki (złożoność O(1)) wstawianie na właściwe miejsce (za ostatni o takim samym priorytecie) (złożoność O(N)) - stóg (złożoność wstawiania i pobierania O(log N))
b)- z priorytetami o wartościach wybranych z niewielkiego zbioru. W tym wypadku wykorzystujemy tablicę zwykłych kolejek (dla każdego priorytetu osobna).
Implementacja kolejki bazującej na liście nieuporządkowanej:
package queues; import lists.LinkedList; import lists.List; import sorting.Comparator;
public class UnsortedPriorityQueue implements Queue { private final List _list; private final Comparator _comparator; //do ustalenia priorytetu
public UnsortedPriorityQueue(Comparator comparator) { _comparator = comparator; _list = new LinkedList(); } public void enqueue(Object value) { _list.add(value); }
public Object dequeue() throws EmptyQueueException { if (isEmpty()) throw new EmptyQueueException(); return _list.delete(getIndexOfLargestElement()); }
private int getIndexOfLargestElement() { int result = 0; for (int i = 1; i < _list.size(); ++i) if (_comparator.compare(_list.get(i), _list.get(result)) > 0) result = i; return result; }
public void clear() { _list.clear(); }
public int size() { return _list.size(); }
public boolean isEmpty() { return _list.isEmpty();} }
Implementacja wykorzystująca listę uporządkowaną:
package queues; import lists.LinkedList; import lists.List; import sorting.Comparator;
public class SortedPriorityQueue implements Queue { private final List _list; private final Comparator _comparator;
public SortedPriorityQueue(Comparator comparator) { _comparator = comparator; _list = new LinkedList(); }
public void enqueue(Object value) { int pos = _list.size(); while (pos > 0 && _comparator.compare(_list.get(pos - 1), value) > 0) --pos; _list.insert(pos, value); }
public Object dequeue() throws EmptyQueueException { if (isEmpty()) throw new EmptyQueueException(); return _list.delete(_list.size() - 1); }
public void clear() { _list.clear(); }
public int size() { return _list.size();}
public boolean isEmpty() { return _list.isEmpty();} } Pojęcie stogu (Heap):
Stogiem zupełnym (stertą) nazywamy takie drzewo binarne, które ma dwie własności: - kształtu: jest pełnym drzewem, przy czym ostatni poziom jest zapełniany od lewej strony - uporządkowania: węzeł jest zawsze większy od swoich potomków.
Najprościej jest realizować stóg w tablicy. Wówczas synami węzła i są węzły 2*i+1 oraz 2*(i+1), a ojcem węzła i jest węzeł (i-1)/ 2.
Implementacja kolejki wykorzystującej stóg:
package queues; import lists.ArrayList; import lists.List; import sorting.Comparator;
public class HeapPriorityQueue implements Queue { private final List _list; private final Comparator _comparator;
public HeapPriorityQueue(Comparator comparator) { _comparator = comparator; _list = new ArrayList(); }
public void enqueue(Object value) { _list.add(value); swim(_list.size() - 1); }
//wynoszenie elementu w górę private void swim(int index) { int parent; while(index!= 0 && _comparator.compare(_list.get(index), _list.get(parent= (index - 1) / 2)) > 0) { swap(index, parent); index=parent; } }
private void swap(int index1, int index2) { Object temp = _list.get(index1); _list.set(index1, _list.get(index2)); _list.set(index2, temp); }
public Object dequeue() throws EmptyQueueException { if (isEmpty()) throw new EmptyQueueException(); Object result = _list.get(0); if (_list.size() > 1) { _list.set(0, _list.get(_list.size() - 1)); sink(0); } _list.delete(_list.size() - 1); return result; }
// opuszczanie elementu w dół stogu private void sink(int index) { boolean isDone=false; int child; while(!isDone && (child=2*index+ 1) < _list.size()) { if (child < _list.size()- 1 && _comparator.compare(_list.get(child), _list.get(child+1)) < 0) ++child; if (_comparator.compare(_list.get(index), _list.get(child)) < 0) swap(index, child); else isDone=true; } }
public void clear() { _list.clear(); }
public int size() { return _list.size(); }
public boolean isEmpty() { return _list.isEmpty();} } Zadania: 20) Stóg wykorzystywany do sortowania stogowego można zbudować bez wykorzystania metody swim (przesuwanie w górę). Jest to znacznie szybszy proces.Zaimplementuj odpowiednią metodę. 21) Flloyd zauważył, że można przyspieszyć usuwanie elementu kolejki stogowej przez modyfikację metody sink. Zaproponował żeby opuszczać element na sam dół stogu, a następnie jeśli trzeba to go podnieść na odpowiednią pozycję. Kiedy to podejście przynosi korzyść. Temat 8. Tablice symboli (słowniki). Słownik (inne nazwy to: tablica skojarzeniowa, tablica asocjacyjna, tablica indeksowana wartością klucza, odwzorowanie, mapa - bezmyślne przetłumaczenie angielskiego terminu map czyli odwzorowanie) - typ abstrakcyjny z określonymi operacjami: JestElementem - czy dany element występuje w słowniku albo wyszukaj element o danym kluczu Dodaj - dopisz element do słownika Usun - usuń element ze słownika Wybierz - k-ty co do wielkości element Sortuj - wypisz wszystkie elementy w sposób uporządkowany Połącz - połącz dwa słowniki w jeden
Należy pamiętać że podstawową operacją na typowym słowniku jest wyszukiwanie elementu; dodawanie i usuwanie albo nie występują, albo są wykonywane bardzo rzadko. Więc efektywność wyszukiwania decyduje o przydatności danej realizacji. Metody wyszukiwania elementu zależą od sposobu organizacji słownika. Klucze obiektów (elementów) występujących w słowniku nie mogą się powtarzać. Elementy występujące w słowniku mogą się składać albo z samego klucza (np. słownik słów kluczowych kompilatora, słownik do sprawdzania pisowni) lub z klucza i danych (np. słownik polsko-angielski, encyklopedia, książka telefoniczna). Od typu elementu zależy sposób działania operacji JestElementem: - tylko sprawdzenie gdy element ma tylko klucz - zwrócenie wartości pola dane dla elementów zbudowanych z klucza i danych. Operacja dodawania elementu do słownika jest wykonywana znacznie rzadziej. Tylko w specyficznych sytuacjach w czasie normalnej pracy (on-line) i wówczas jej efektywność jest istotna, zazwyczaj jednak jest wykonywana w trybie off-line i szybkość nie ma praktycznego znaczenia. Usuwanie elementu prawie zawsze jest wykonywane w trybie off-line.
Można wyróżnić trzy podstawowe klasy struktur służących do przechowywania elementów słownika: 1. ciąg nieuporządkowany (tablica, plik lub lista) 2. tablica haszowana 3. ciąg uporządkowany (tablica, plik, lista, struktury drzewiaste). Na początek zajmiemy się wyszukiwaniem na listach nieuporządkowanych i uporządkowanych. Interfejs wyszukiwania:
package searching; import lists.List;
public interface ListSearcher { //zwraca pozycję obiektu na liście - jeśli jest //jeśli nie to - (pozycja_wstawienia + 1) // plus1 umożliwia wskazanie, że element powinien się znajdować na początku listy
public int search(List list, Object value); }
Dla list nieuporządkowanych stosujemy wyłącznie proste przeszukiwanie liniowe (złożonośc O(N)). Dla list uporządkowanych możemy zastosować: - wyszukiwanie liniowe (O(N)), szybsze wykrywanie braku elementu w porównaniu do list nieuporządkowanych:
package searching; import lists.List; import sorting.Comparator;
public class LinearListSearcher implements ListSearcher { private final Comparator _comparator;
public LinearListSearcher(Comparator comparator) { _comparator = comparator; }
public int search(List list, Object value) { int cmp=0,i; for (i=0; i<list.size() && (cmp = _comparator.compare(value, list.get(i)))>0; i++); return i<list.size() && cmp ==0? i: -(i+1); //lista może być pusta } }
- wyszukiwanie binarne (złożoność O(log N)): idea:
Oznaczenia: k- klucz szukanego elementu poc - pozycja lewego końca przeszukiwanego obszaru k(poc) klucz tej pozycji kon - pozycja prawego końca k(kon) jej klucz b - wyznaczony w danym kroku punkt podziału k(b) klucz
do b= (poc+kon) div 2 if (k >k(b)) b+1 staje się lewym końcem nowego przedziału else b staje się prawym końcem nowego przedziału while (poc >=kon) sprawdź element na pozycji poc implementacja iteracyjna (nieco inna wersja - dla optymistów) package searching;
import lists.List; import sorting.Comparator;
public class IterativeBinaryListSearcher implements ListSearcher { private final Comparator _comparator;
public IterativeBinaryListSearcher(Comparator comparator) { _comparator = comparator; }
public int search(List list, Object value) { int lower = 0; int upper = list.size() - 1; int index=0,cmp=0; while (lower <= upper && (cmp = _comparator.compare(value, list.get(index=(lower + upper)/2)))!=0) if (cmp < 0) upper = index - 1; else lower = index + 1; return lower<=upper && cmp==0? index: -(lower+1); } }
Implementacja rekurencyjna
package searching; import lists.List; import sorting.Comparator;
public class RecursiveBinaryListSearcher implements ListSearcher { private final Comparator _comparator;
public RecursiveBinaryListSearcher(Comparator comparator) { _comparator = comparator; }
public int search(List list, Object value) { return search(list, value, 0, list.size() - 1); }
// wersja dla miłośników instrukcji return (moim zdaniem nienajlepsza) private int search(List list, Object value, int lower, int upper) { if (lower > upper) return -(lower + 1); int index = (lower + upper) / 2; int cmp = _comparator.compare(value, list.get(index)); if (cmp < 0) return search(list, value, lower, index - 1); if (cmp > 0) return search(list, value, index + 1, upper); return index; } }
Jeszcze szybsze jest wyszukiwanie interpolacyjne (stosowane gdy klucze mają rozkład równomierny) do b= poc+(k-k(poc))/(k(kon)-k(poc))*(kon-poc) if (k >k(b)) b+1 staje się lewym końcem nowego przedziału else b staje się prawym końcem nowego przedziału while (poc >=kon) sprawdź element na pozycji poc
Złożoność log log(N) - czyli praktycznie stała. Zadania: 22) Zaimplementuj wyszukiwanie binarne dokładnie według przedstawionej powyżej idei. Sprawdź swój algorytm dla wszystkich granicznych przypadków. 23) Zaimplementuj rekurencyjną wersję wyszukiwania liniowego. Chodzi wyłącznie o gimnastykę umysłu - staramy się unikać rekurencji o głębokości liniowej.
|
||
|
Последнее изменение этой страницы: 2016-04-23; просмотров: 223; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 216.73.217.128 (0.006 с.) |