Listy jednokierunkowe - wstawianie nowego elementu przed zadany

Listy jednokierunkowe - wstawianie nowego elementu przed zadany

Wątek przeniesiony 2014-10-26 18:19 z C/C++ przez ŁF.

zeed94
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

Witam!
Na uczelni uczymy się właśnie tworzyć i używać list jednokierunkowych. I mieliśmy za zadanie napisać funkcje, które dodają nowy element za i przed wskazany przez q element w liście. Z dodawanie za nie miałem problemu, jednakże z przed już mam.

Kopiuj
#include<stdio.h>
#include<stdlib.h>

typedef struct el{
	int dane;
	struct el *nast;
} element;

element *p, *q, *r;
int x, y, z;

element *DNPL(int a, element *l){
	element *q;
	q = malloc(sizeof(element));
	q->dane = a;
	q->nast = l;
	return q;
}

element *DNKL(int a, element *l){
	element *q, *r;
	q = malloc(sizeof(element));
	while (q != NULL){
		printf("%i\n", q->dane);
		q = q->nast;
	}
	if (l == NULL) return q;
	r = l;
	while (r->nast != NULL) r = r->nast;
	r->nast = q;
	return l;
}

void druk_normalny(element *p){
	if (p != NULL){
		printf("%d, ", p->dane);
		druk_normalny(p->nast);
	}
}

void druk_odwrocony(element *p){
	if (p != NULL){
		druk_odwrocony(p->nast);
		printf("%d, ", p->dane);
	}
}

element *znajdz(int x, element *p){
	element *q = p;
	while ((q != NULL) && (q->dane != x)) q = q->nast;
	return q;
}

void dodaj_za(int x, element *q){
	element *r = malloc(sizeof(element));
	r->dane = x;
	r->nast = q->nast;
	q->nast = r;
}

void dodaj_przed(int x, element *q, element *p){
	element *r = NULL;
	if (r->nast == q) DNPL(x, p);
	else{
		while (r->nast != q) r = r->nast;
		element *t = malloc(sizeof(element));
		r->nast = t;
		t->dane = x;
		t->nast = q;
	}
}

int main(){
	p = NULL;
	printf("Podaj elementy list:\n");
	scanf("%i", &x);
	while(x != 0){
		p = DNPL(x, p);
		scanf("%i", &x);
	}

	printf("\nTwoja lista: ");
	q=p;
	druk_normalny(p);

	printf("\nJaki element chcesz znalesc w liscie: "); scanf("%d", &x);
	while (x){
		q = znajdz(x, p);
		if (q != NULL) {
			printf("Znaleziono %i\n", x);
		}
		else{
			printf("Nie ma %i na liscie\n", x);
		}
		scanf("%i", &x);
	}
	
	printf("\nPodaj element, ktory chcesz dodac do listy: ");
	scanf("%d", &x);
	dodaj_przed(x, q, p);

	printf("\nTwoja lista: ");
	druk_normalny(p);

	getchar();
	getchar();
	return 0;
}

Po skompilowaniu wyskakuje błąd "Unhandled exception at 0x00313CF8 in ASD.exe: 0xC0000005: Access violation reading location 0x00000004." przy warunku if w funkcji dodaj_przed.
Byłbym wdzięczny za pomoc.
Pozdrawiam

_13th_Dragon
  • Rejestracja: dni
  • Ostatnio: dni
0

Z dodaj_za też masz problemy, bo wystarczy:

Kopiuj
void dodaj_za(int x, element *q) {
    q->nast = DNPL(x,q->nast);
}

Padłeś ofiarą bezsensownego nazywania zmiennych.

Kopiuj
void dodaj_przed(int x, element *q, element *p){
    element *r = NULL;
    if (r->nast == q) DNPL(x, p);
    else{
        while (r->nast != q) r = r->nast; // co my tu iterujemy skoro r=NULL w pierwszym wierszu funkcji.
        element *t = malloc(sizeof(element));
        r->nast = t;
        t->dane = x;
        t->nast = q;
    }
}
zeed94
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

Faktycznie z dodaj_za nie pomyślałem żeby użyć funkcji DNPL.
Co do pętli while, to widzę to tak, że dopóki r->nast nie będzie wskazywała na q mam przechodzić przez kolejne, elementy listy. Nie widzę w sumie innego sposobu by dostać element listy przed q, który swoją drogą jest mi potrzebny.
Zaś co do nazywania zmiennych, to tak zmienne nazywa mój wykładowca i kod który tu wstawiłem jest bezpośrednio z zajęć. Ja tylko dopisałem funkcje dodaj_za i dodaj_przed, z czego jedna nie działa...

_13th_Dragon
  • Rejestracja: dni
  • Ostatnio: dni
0

Jakie r ? r - to zmienna lokalna:

Kopiuj
element *r = NULL;
zeed94
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

Aaa, dobra już wiem. Dzięki.
Zamiast

Kopiuj
element *r = NULL; 

powinno być

Kopiuj
element *r;
r = NULL; 

Nie kurde, to też nic nie zmienia...:(

_13th_Dragon
  • Rejestracja: dni
  • Ostatnio: dni
1

Czy rozumiesz cokolwiek z tego kodu co przedstawiłeś ?
No chyba że coś dobrego palisz i jesteś obecnie na głębokim haju.

zeed94
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

Większość, ale nie wszystko.

_13th_Dragon
  • Rejestracja: dni
  • Ostatnio: dni
0

Weź się za naukę, bo jak nie zrobisz tego sam to dalej będzie gorzej.
Nie sądzę aby rozumiałeś większość bo widzę że nie rozumiesz nawet parametrów funkcji którą masz zrobić.

zeed94
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

Udało mi się częściowo naprawić tą funkcje i rozumiem czemu głupota było ustawianie r na NULL. Jednakże nie rozumiem teraz dlaczego funkcja ma problem z użyciem DNPL w przypadku gdy wskazany element jest na samym początku listy. Więc byłbym wdzięczy za "niestresującą" pomoc.

Kopiuj
void dodaj_przed(int x, element *q, element * p){
	element *r = p;
	if (r == q) p = DNPL(x, p);
	else{
		while (r->nast != q) r = r->nast;
		element *t = malloc(sizeof(element));
		r->nast = t;
		t->nast = q;
		t->dane = x;		
	}
}

dodanie znacznika <code class="c"> - @furious programming

_13th_Dragon
  • Rejestracja: dni
  • Ostatnio: dni
0

Ta funkcja nie jest przeznaczona do dodania na początek listy, ponieważ przy dodaniu na początek musisz zmienić początek listy zaś ten początek jest przekazany przez wartość.
Podsumowując, nie zmieniając nagłówka funkcji - nie da się.
Poza tym:

Kopiuj
element *dodaj_przed(int x,element *q,element * p){
    element *r=p;
    if (p==q) p=DNPL(x,p);
    else {
        while(r->nast!=q) r=r->nast;
        r->nast=DNPL(x,q);
    }
    return p;
}

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.