matematykaszkolna.pl
Rekurencyjne dodawanie elementów do listy Mariusz: Rekurencyjne dodawanie elementów do listy typedef struct lista{ int wart; struct lista *nast; }lista; void dodaj(lista *l,int nowy) { if(l!=NULL) { dodaj(l−>nast,nowy); } else { l=(lista*) malloc((sizeof(lista))); l−>wart=nowy; l−>nast=NULL; } } void pokaz(lista *l) { if(l!=NULL) { printf("%i ",l−>wart); pokaz(l−>nast); } } Gdy wkleimy kod do naszej funkcji głównej to wprawdzie się skompiluje ale nie będzie efektów Dlaczego tak się dzieje i jaki macie pomysł aby to poprawić Problematyczna może być funkcja dodaj
1 sty 20:59
Dziadek Mróz: Sychy kod tak jak powinno działać: void dodaj(lista *elem, int nowy) { if (elem == NULL) { elem = (lista *)malloc(sizeof(lista)); elem = nowy; elem−>next = NULL; } else { dodaj(elem−>next, nowy); } } lista *first = NULL; pokaz(first); → (NULL) dodaj(NULL, 1); NULL == NULL → tak elem = (lista *)malloc(sizeof(lista)); elem = nowy; elem−>next = NULL; pokaz(first); → (1, NULL) dodaj(1, 2); 1 == NULL → nie dodaj(NULL, 2): NULL == NULL → tak elem = (lista *)malloc(sizeof(lista)); elem = nowy; elem−>next = NULL; pokaz(first); → (1, 2, NULL)
1 sty 21:43
Dziadek Mróz: void pokaz(lista *elem) { if (elem == NULL) { printf("NULL"); } else { printf("%d, ", (*elem).wart); pokaz((*elem).next); } }
1 sty 21:45
Dziadek Mróz: W rekurencji musisz pilnować warunku stopu bo inaczej będziesz krążył w nieskończonej rekurencji
1 sty 21:46
Dziadek Mróz: tam jest: elem−>next = nowy; // (*elem).wart = nowy;
1 sty 21:52
Mariusz: Ja podejrzałem kod innej funkcji rekurencyjnej i miałem pomysł aby funkcja zwracała wskaźnik na głowę zmienionej listy bo dodanie drugiego wskaźnika skompilkowałoby rekurencyjne wywołanie a referencja wchodzi dopiero w C++
1 sty 22:01
Mariusz: https://matematykaszkolna.pl/forum/340043.html Kod funkcji na podstawie którego wpadłem na pomysł aby funkcja zwracała wskaźnik na zmienioną głowę listy Czy aby na pewno po wyjściu z funkcji zmieni nam listę ? Dlaczego w podejściu iteracyjnym jest podwójny wskaźnik
1 sty 22:29
Dziadek Mróz: Taka funkcja zwraca pojedynczy węzeł. A co będzie do niego podpięte to inna sprawa. Jak napiszesz kod tak będzie wyglądała lista. Najprostszy sposób to kartka, ołówek i rozpisanie każdego kroku
1 sty 22:39
Mariusz: W iteracyjnym podejściu jest podwójny wskaźnik , po co on jest ? Gdybyśmy chcieli dać w funkcji rekurencyjnej podwójny wskaźnik to jak wyglądałoby rekurencyjne wywołanie Gdy zmieniłem tę funkcję tak aby zwracała wskaźnik na głowę zmienionej listy to działa ale napisałem to na wzór innej funkcji rekurencyjnej bez pewności że pomysł zadziała W Pascalu jest słówko var po którym procedurę można przepisać słowo w słowo i działa
1 sty 22:51
Dziadek Mróz: Pokaż mnie fragment kodu bo nie wiem jak chcesz użyć taki podwójny wskaźnik int d = 10 int *ptr1 = &d; int **pptr1 = &ptr1;
1 sty 22:54
Mariusz: lista* dodaj(lista *l,int nowy) { lista* wynik=NULL; if(l!=NULL) { wynik=l; wynik−>nast=dodaj(l−>nast,nowy); } else { wynik=(lista*)malloc(sizeof(lista)); wynik−>wart=nowy; wynik−>nast=NULL; } return wynik; } void pokaz(lista *l) { if(l!=NULL) { printf("%i ",l−>wart); pokaz(l−>nast); } } Pomysł który powinien zadziałać
1 sty 22:57
Mariusz: void dodaj(lista** l,int nowy) { lista* p; lista* e; e=(lista*)malloc(sizeof(lista)); e−>wart=nowy; e−>nast=NULL; p=(*l); if(p==NULL) (*l)=e; else { while(p−>nast!=NULL) p=p−>nast; p−>nast=e; } } Dla wersji iteracyjnej pomysł z podwójnym wskaźnikiem działa
1 sty 23:01
Dziadek Mróz: no dobrze, a gdzie jest ten podwójny wskaźnik?
1 sty 23:01
Mariusz: Wersja rekurencyjna mogłaby chyba tak wyglądać void dodaj(lista **l,int nowy) { if((*l)!=NULL) { dodaj(&((*l)−>nast),nowy); } else { (*l)=(lista*)malloc(sizeof(lista)); (*l)−>wart=nowy; (*l)−>nast=NULL; } }
1 sty 23:13
Mariusz: Funkcja pokaż ma tylko wskaźnik na głowę jako parametr natomiast funkcja dodaj albo zwraca wskaźnik na głowę albo jej parametr ma jeszcze dodatkowy wskaźnik , nie widzisz tego ? Dlaczego jest ten podwójny wskaźnik
1 sty 23:25
Mariusz: Do pary przydałaby się rekurencyjna funkcja usun
3 sty 04:16
Mariusz: Napisałem taką funkcję usuń ale nie wiem czy dobrze działa void usun1(lista **l) { if((*l)!=NULL) { if((*l)−>nast==NULL) { free((*l)); (*l)=NULL; } else { usun1(&((*l)−>nast)); } } } lista* usun2(lista *l) { lista* wynik=NULL; if(l!=NULL) { if(l−>nast==NULL) { free(l); wynik=NULL; } else { wynik=l; l−>nast=usun2(l−>nast); } } return wynik; }
3 sty 18:57