Zastanawiam się, czy istnieje jakaś logika odwracania pojedynczo połączonej listy przy użyciu tylko dwóch wskaźników.
Dodaje stosuje się odwrócić jedną listę łączy się stosując trzy wskaźniki mianowicie p
, q
, r
:
struct node {
int data;
struct node *link;
};
void reverse() {
struct node *p = first,
*q = NULL,
*r;
while (p != NULL) {
r = q;
q = p;
p = p->link;
q->link = r;
}
first = q;
}
Czy istnieje inna alternatywa do odwrócenia połączonej listy? Jaka byłaby najlepsza logika do odwrócenia pojedynczo połączonej listy pod względem złożoności czasowej?
Odpowiedzi:
Jakaś alternatywa? Nie, to jest tak proste, jak to tylko możliwe, i nie ma zasadniczo innego sposobu, aby to zrobić. Ten algorytm ma już czas O (n) i nie możesz uzyskać nic szybszego, ponieważ musisz zmodyfikować każdy węzeł.
Wygląda na to, że Twój kod jest na dobrej drodze, ale nie działa w powyższym formularzu. Oto działająca wersja:
źródło
reverse()
funkcji powinna być ustawiana jako pierwsza, jak sądzę. W przeciwnym razie oryginalny kod działał poprawnie po podłączeniu do zgrabnej wiązki testowej. Mimo to otrzymujesz ode mnie +1 - ale wyjaśnienie, co uważasz za „oczywiste błędy”, poprawiłoby Twoją odpowiedź.Nienawidzę być zwiastunem złych wiadomości, ale nie sądzę, aby twoje rozwiązanie za trzy wskazówki faktycznie działało. Kiedy użyłem go w poniższej wiązce testowej, lista została zredukowana do jednego węzła, zgodnie z następującym wyjściem:
Nie uzyskasz lepszej złożoności czasowej niż twoje rozwiązanie, ponieważ jest to O (n) i musisz odwiedzić każdy węzeł, aby zmienić wskaźniki, ale możesz łatwo zrobić rozwiązanie z tylko dwoma dodatkowymi wskaźnikami, jak pokazano w poniższym kodzie:
Ten kod wyprowadza:
co myślę, że to jest to, czego szukałeś. W rzeczywistości może to zrobić, ponieważ po załadowaniu
first
wskaźnika do wskaźnika przechodzącego przez listę możesz ponownie użyćfirst
do woli.źródło
first
wskaźnik na samej liście połączonej rozwiązanie pozwala używać tylko 2 dodatkowe wskaźniki, ale 3 łączne wskaźniki są nadal niezbędne do tego.first
. W ten sam sposób rozwiązanie trzech wskaźnik PO miałafirst
,p
,q
ir
.źródło
Oto kod, aby odwrócić pojedynczo połączonej listy w C .
I tutaj jest wklejony poniżej:
źródło
Tak. Jestem pewien, że możesz to zrobić w ten sam sposób , w jaki możesz zamienić dwie liczby bez używania trzeciej . Po prostu rzuć wskaźniki na int / long i wykonaj operację XOR kilka razy. To jedna z tych sztuczek C, która jest zabawnym pytaniem, ale nie ma żadnej praktycznej wartości.
Czy możesz zmniejszyć złożoność O (n)? Nie, nie bardzo. Po prostu użyj podwójnie połączonej listy, jeśli myślisz, że będziesz potrzebować odwrotnej kolejności.
źródło
Robert Sedgewick, „ Algorithms in C ”, Addison-Wesley, 3. wydanie, 1997, [sekcja 3.4]
W przypadku, gdy nie jest to lista cykliczna, dlatego NULL jest ostatnim łączem.
źródło
Dla zabawy (chociaż optymalizacja rekurencji ogona powinna powstrzymać ją przed zjadaniem całego stosu):
źródło
Aby zamienić dwie zmienne bez użycia zmiennej tymczasowej,
najszybszym sposobem jest zapisanie go w jednej linii
Podobnie,
za pomocą dwóch zamian
rozwiązanie przy użyciu xor
rozwiązanie w jednej linii
Ta sama logika służy do odwracania połączonej listy.
źródło
intptr_t
). Chociaż interesujące - zamiana w ten sposób jest nieoptymalna w nowoczesnych systemach.Potrzebujesz wskaźnika ścieżki, który będzie śledził listę.
Potrzebujesz dwóch wskazówek:
pierwszy wskaźnik, aby wybrać pierwszy węzeł. drugi wskaźnik, aby wybrać drugi węzeł.
Przetwarzanie:
Przesuń wskaźnik ścieżki
Skieruj drugi węzeł na pierwszy węzeł
Przesuń pierwszy wskaźnik o jeden krok, przypisując drugi wskaźnik do jednego
Przesuń drugi wskaźnik o jeden krok, przypisując wskaźnik ścieżki do drugiego
}
źródło
A co z bardziej czytelnymi:
źródło
Oto prostsza wersja w Javie. Używa tylko dwóch wskaźników
curr
&prev
źródło
Sprawdź złożoność czasową algorytmu, którego używasz teraz i powinno być oczywiste, że nie można go poprawić.
źródło
Nie rozumiem, dlaczego istnieje potrzeba powrotu głowy, skoro przekazujemy to jako argument. Przechodzimy obok listy linków, a następnie możemy zaktualizować. Poniżej proste rozwiązanie.
źródło
źródło
Nie, nie da się zrobić nic szybciej niż obecne O (n). Musisz zmienić każdy węzeł, więc czas i tak będzie proporcjonalny do liczby elementów i to jest O (n), które już masz.
źródło
Używanie dwóch wskaźników przy jednoczesnym zachowaniu złożoności czasowej O (n), najszybszego możliwego do osiągnięcia, może być możliwe tylko poprzez rzucanie liczb wskaźników i zamianę ich wartości. Oto realizacja:
źródło
Mam trochę inne podejście. Chciałem skorzystać z istniejących funkcji (takich jak insert_at (indeks), delete_from (indeks)), aby odwrócić listę (coś w rodzaju operacji przesunięcia w prawo). Złożoność jest nadal O (n), ale zaletą jest więcej ponownie wykorzystanego kodu. Rzuć okiem na metodę another_reverse () i daj mi znać, co myślicie.
źródło
źródło
źródło
Tak, jest sposób wykorzystujący tylko dwa wskaźniki. To znaczy, tworząc nową połączoną listę, w której pierwszy węzeł jest pierwszym węzłem z danej listy, a drugi węzeł pierwszej listy jest dodawany na początku nowej listy i tak dalej.
źródło
Oto moja wersja:
gdzie
źródło
Używam javy do implementacji tego, a podejście jest oparte na testach, dlatego dołączone są również przypadki testowe.
Klasa Node, która reprezentuje pojedynczy węzeł -
Klasa usługi, która przyjmuje węzeł początkowy jako dane wejściowe i rezerwuje go bez używania dodatkowego miejsca.
I przypadek testowy, który obejmuje powyższy scenariusz. Pamiętaj, że potrzebujesz słoików junit. Używam testng.jar; możesz użyć wszystkiego, co ci się podoba.
źródło
Prosty algorytm, jeśli używasz połączonej listy jako struktury stosu:
Wydajność może ulec pogorszeniu, ponieważ dodatkowe wywołanie funkcji do add i malloc, więc algorytmy zamiany adresów są lepsze, ale faktycznie tworzy nową listę, więc możesz użyć dodatkowych opcji, takich jak sortowanie lub usuwanie elementów, jeśli dodasz funkcję zwrotną jako parametr do odwrócić.
źródło
Oto nieco inne, ale proste podejście w C ++ 11:
Wyjście tutaj
źródło
Poniżej znajduje się jedna implementacja wykorzystująca 2 wskaźniki (nagłówek i r)
źródło
sizeof(size_t) < sizeof(ListNode*)
... powinieneś użyćstd::uintptr_t
.oto małe proste rozwiązanie ...
źródło
Możesz rozwiązać ten problem za pomocą tylko jednego dodatkowego wskaźnika, który musi być statyczny dla funkcji odwrotnej. Jest w złożoności O (n).
źródło
Alternatywnie możesz użyć rekurencji -
źródło
źródło
źródło