Dlaczego w zadaniu z listą jednokierunkową konieczne jest użycie wskaźnika do wskaźnika?

0

Witam mam zadanie do rozwiązania z codewars:

https://www.codewars.com/kata/58d91d5f024c724b50000300/train/c

chciałbym wiedzieć, dlaczego listPointer1 i listPointer2 nie mogą być zwykłymi wskaźnikami a muszą być wskaźnikami do wskaźnika, dlaczego jeśli będą zwykłymi wskaźnikami nie będę mógł zamienić miejscami pierwszego węzła.
Pytanie drugie czy jeśli indeks1 lub indeks2 będą ostatnimi węzłami też nie będzie można zmienić węzłów miejscami? Nawet gdy listPonter1 i listPointer2 będą wskaźnikami do wskaźnika.

0

Coś mi tu nie pasuje, jak jest wskaźnik to możesz dowolnie adres zmienić,

A drugie można zmienić.
Ale nic nie rozumiem z tego co napisałeś strasznie dziwnie to napisane możesz przykład podać?

0

No właśnie nie bardzo kombinuję z tym zadaniem i mi nie wychodzi. Nie rozumiem wskaźnik do wskaźnika bo inaczej nie mogę zmienić adresów bez sensu, po to są wskaźniki, żeby przekazywać do funkcji przez wskaźniki i żeby pracowała na oryginalnych wartościach

0

Wskaźnik to adres, jak w losowym miejscu w pamięci dodasz nową wartość, to dodajesz ten adres do listy i potem wiesz, że to wskaźnik ten adres wtedy trzeba zaglądnąć pod ten adres i ma się wartość co się tam znajduje dlatego to jest wskaźnik, bo wiesz gdzie jest wartość, ale nie wiesz co oznacza i zaglądnięcie pod adres dany da ci jej wartość, a tam może być i wartość, ale też inny adress do czegoś innego czyli pointer do pointer, wskaźnik na wskaźnik

2

Odpowiedź z zamkniętymi oczami bez sprawdzania o co chodzi.

Bo chcesz zmodyfikować wskaźnik który masz pod wskaźnikiem.
Jak funkcja bierze int** to wiadomo, że będzie modyfikować int* oraz pewnie int

0
gonskabalbinka napisał(a):

chciałbym wiedzieć, dlaczego listPointer1 i listPointer2 nie mogą być zwykłymi wskaźnikami a muszą być wskaźnikami do wskaźnika, dlaczego jeśli będą zwykłymi wskaźnikami nie będę mógł zamienić miejscami pierwszego węzła.

Ponieważ podmieniasz elementy listy przez ich adresy. W tym zadaniu nie wolno kopiować wartości elementów listy. I musisz wiedzieć, gdzie zapisać adres zerowego elementu listy.

Pytanie drugie czy jeśli indeks1 lub indeks2 będą ostatnimi węzłami też nie będzie można zmienić węzłów miejscami? Nawet gdy listPonter1 i listPointer2 będą wskaźnikami do wskaźnika.

Wszystkie elementy oprócz zerowego mają już lokalizację next, gdzie adres elementu listy jest zapisany.

Wskaźniki do adresów kolejnych elementów:
listPointer1
&( *listPointer1 )->next
&( *listPointer1 )->next->next
itd.

0

Myślałem, że jeśli przekazuję wskaźniki funkcja pracuje na oryginałach ale doczytałem, że też dostaje tylko kopie.

2

Wyobraź sobie, że funkcja jest wywołana w takiej sytuacji:

// list1 = linked_list(1 -> 2 -> 3 -> 4)
// list2 = linked_list(5 -> 6 -> 7 -> 8)

swap_node(&list1, 0, &list2, 0);

// expected outcome
// list1 = linked_list(5 -> 2 -> 3 -> 4)
// list2 = linked_list(1 -> 6 -> 7 -> 8)

Czy dałoby się wykonać ta operację, jeśli miałbyś tylko pojedynczy wskaźnik?

BTW nie ufaj autorowi tego zadania, bo jest kilka wskazówek pokazujących, że słabo się zna na C, a robił za dużo kursów C++ i ma problem z rozróżnieniem tych języków programowania.


Ok teraz zajarzyłem, że nie łapiesz po co tu jest lista. W końcu można zwabić zamianę na value i gotowe.
Generalnie założenie jest takie, że value trzymane przez listę jest czymś dużym i ciężkim do kopiowania.
Struktura listy ma zapobiec jawnemu kopiowaniu value, a przestawianie elementów ma się odbywać przez kopiowanie wskaźników next listy.
W zadaniu dla uproszczenia zastosowano typ int dla value (bo typ trzymanych danych jest mało znaczącym detalem, dla problemu), przez co stosowanie listy traci sens i ukrywa sens zadania.

Podwójny wskaźnik, ułatwia takie rozwiązanie, że value nie jest kopiowane, a elementy listy są przestawiane, przez podmianę wartości next.

Przykład mojego rozwiązania (przeszło):

LinkedList* nodePointerAtIndex(LinkedList* l, int index)
{
    while (index && *l) {
      l = &(*l)->next;
      --index;
    }
    return l;
}

void nodeSwapPointers(LinkedList *a, LinkedList *b)
{
    LinkedList tmp = *a;
    *a = *b;
    *b = tmp;
}

int swapNodes(LinkedList *listPointer1, unsigned int index1, LinkedList *listPointer2, unsigned int index2)
{
    listPointer1 = nodePointerAtIndex(listPointer1, index1);
    listPointer2 = nodePointerAtIndex(listPointer2, index2);
    if (!*listPointer1 || !*listPointer2)
    {
        return 0;  
    }
    nodeSwapPointers(&(*listPointer1)->next, &(*listPointer2)->next);
    nodeSwapPointers(listPointer1, listPointer2);
  
    return 1;
}

https://www.codewars.com/kata/reviews/58ef7bbafbf6efcc630005df/groups/65773e9f01c98d0001b06004

1 użytkowników online, w tym zalogowanych: 0, gości: 1