Podobne pytanie zostało tam zadane wcześniej , ale tutaj jest odwrotnie, używając dwóch kolejek jako stosu. Pytanie...
Biorąc pod uwagę dwie kolejki z ich standardowych operacji ( enqueue
, dequeue
, isempty
, size
), zaimplementować stos z jego standardowych operacji ( pop
, push
, isempty
, size
).
Powinny istnieć dwie wersje rozwiązania.
- Wersja A : Stos powinien być wydajny podczas wypychania elementu; i
- Wersja B : Stos powinien być wydajny podczas wyskakiwania elementu.
Interesuje mnie algorytm bardziej niż jakiekolwiek konkretne implementacje językowe. Z zadowoleniem przyjmuję jednak rozwiązania wyrażone w językach, które znam (Jawa,do#,pyton,czas,javascript,php).
algorithm
data-structures
stack
TechTravelThink
źródło
źródło
Pop
działa w $ O (1) $ iPush
działa w $ O (\ sqrt {n}) $ amortyzowanym czasie.Odpowiedzi:
Wersja A (wydajne wypychanie):
Wersja B (wydajny pop):
źródło
Najłatwiejszym (i być może jedynym) sposobem na zrobienie tego jest wpychanie nowych elementów do pustej kolejki, a następnie dekolejowanie pozostałych i wpisywanie do poprzednio pustej kolejki. W ten sposób najnowszy jest zawsze na początku kolejki. Byłaby to wersja B, w przypadku wersji A wystarczy odwrócić proces, usuwając elementy z kolejki do drugiej kolejki, z wyjątkiem ostatniej.
Krok 0:
Krok 1:
Krok 2:
Krok 3:
źródło
Możemy to zrobić jedną kolejką:
Pchać:
n
jest liczbą elementów w kolejce, usuń i wstawn-1
razy elementy .Muzyka pop:
.
Przykładowa realizacja:
źródło
źródło
Czy możemy użyć jednej kolejki do zaimplementowania stosu? Mogę używać dwóch kolejek, ale rozważenie pojedynczej kolejki byłoby bardziej wydajne. Oto kod:
źródło
źródło
Oto moja odpowiedź - gdzie „pop” jest nieefektywny. Wydaje się, że wszystkie algorytmy, które przychodzą do głowy od razu, mają złożoność N, gdzie N jest rozmiarem listy: niezależnie od tego, czy zdecydujesz się pracować na „pop”, czy na „push”
Algorytm, w którym listy są wymieniane z powrotem i czwarte, może być lepszy, ponieważ obliczanie rozmiaru nie jest potrzebne, chociaż nadal musisz zapętlić i porównać z pustymi.
możesz udowodnić, że ten algorytm nie może być zapisany szybciej niż N, zauważając, że informacja o ostatnim elemencie w kolejce jest dostępna tylko poprzez znajomość rozmiaru kolejki i że musisz zniszczyć dane, aby dostać się do tego elementu, stąd druga kolejka .
Jedynym sposobem, aby to przyspieszyć, jest przede wszystkim nie używanie kolejek.
źródło
Oto moje rozwiązanie, które działa w przeciętnym przypadku dla O (1). Istnieją dwie kolejki:
in
iout
. Zobacz pseudokod poniżej:źródło
Jak już wspomniano, czy pojedyncza kolejka nie załatwi sprawy? Prawdopodobnie jest mniej praktyczny, ale jest nieco bardziej przejrzysty.
źródło
Oto prosty pseudokod, push to O (n), pop / peek to O (1):
źródło
Niech S1 i S2 będą dwoma stosami używanymi w implementacji kolejek.
Dbamy o to, aby jedna kolejka była zawsze pusta.
Operacja wypychania: niezależnie od tego, która kolejka nie jest pusta, wstaw do niej element.
Push (struct Stack *S, int data) { if(isEmptyQueue(S->Q1) EnQueue(S->Q2, data); else EnQueue(S->Q1, data); }
Złożoność czasowa: O (1)
Operacja pop: Przenieś n-1 elementów do innej kolejki i usuń ostatni z kolejki w celu wykonania operacji pop.
`
Złożoność czasowa: czas działania pop Operacja wynosi O (n), ponieważ za każdym razem, gdy wywoływany jest pop, przenosimy wszystkie elementy z jednej kolejki do drugiej.
źródło
źródło
źródło
Oto jeszcze jedno rozwiązanie:
dla PUSH: -Dodaj pierwszy element do kolejki 1. -Podczas dodawania drugiego elementu i tak dalej, należy najpierw umieścić element w kolejce 2, a następnie skopiować cały element z kolejki 1 do kolejki2. -W przypadku POP po prostu usuń z kolejki element z kolejki od wstawionego ostatniego elementu.
Więc,
}}
Jest jeden problem, nie wiem jak zmienić nazwy kolejek ???
źródło
źródło
Kod Pythona wykorzystujący tylko jedną kolejkę
źródło
oto kompletny działający kod w C #:
Został zaimplementowany z pojedynczą kolejką,
Pchać:
Muzyka pop:
źródło
Oto bardzo proste rozwiązanie, które wykorzystuje jedną kolejkę i zapewnia funkcjonalność taką jak Stack.
Więc w powyższej klasie o nazwie „CustomStack” to, co robię, to po prostu sprawdzanie, czy kolejka jest pusta, jeśli jest pusta, to wstaw jedną i od tej pory wstawiaj i usuwaj wstawki. Zgodnie z tą logiką pierwszy będzie ostatni. Przykład: W kolejce wstawiłem 1 i teraz próbuję wstawić 2. Drugi raz usuń 1 i ponownie włóż, aby stało się w odwrotnej kolejności.
Dziękuję Ci.
źródło
Poniżej znajduje się bardzo proste rozwiązanie Java, które obsługuje wydajną operację wypychania.
Algorytm -
Zadeklaruj dwie kolejki q1 i q2.
Operacja wypychania - wstaw element do kolejki q1.
Operacja pop - upewnij się, że kolejka q2 nie jest pusta. Jeśli jest pusty, usuń z kolejki wszystkie elementy z q1 z wyjątkiem ostatniego i umieść go w kolejce do q2 jeden po drugim. Usuń z kolejki ostatni element z q1 i zapisz go jako wyskakujący element. Zamień kolejki q1 i q2. Zwróć przechowywany popped element.
Peek operation - upewnij się, że kolejka q2 nie jest pusta. Jeśli jest pusty, usuń z kolejki wszystkie elementy z q1 z wyjątkiem ostatniego i umieść go w kolejce do q2 jeden po drugim. Usuń z kolejki ostatni element z q1 i zapisz go jako podglądany element. Umieść go z powrotem w kolejce q2 i zamień kolejki q1 i q2. Zwróć przechowywany wgląd w element.
Poniżej znajduje się kod powyższego algorytmu -
źródło
Oto moje rozwiązanie…
Concept_Behind ::
push(struct Stack* S,int data)
:: Ta funkcja umieszcza w kolejce pierwszy element w Q1 i odpoczywa w Q2pop(struct Stack* S)
:: jeśli Q2 nie jest puste, przenosi wszystkie elementy do Q1 i zwraca ostatni element w Q2 else (co oznacza, że Q2 jest puste) przenosi wszystkie elementy do Q2 i zwraca ostatni element w Q1Efficiency_Behind ::
push(struct Stack*S,int data)
:: O (1) // od pojedynczej kolejki na danepop(struct Stack* S)
:: O (n) // ponieważ przenosi najgorsze n-1 danych na pop.źródło
źródło
źródło