.c - lista dwukierunkowa - zamiana elementów

0

Czesc, napisalem taki program. Sa trzy funkncje, ktore zamieniaja ze soba elementy.
Niestety nie dzialaja one zawsze (np gdy elementow listy jest 0, 1 lub 2) i program sie "wysypuje".
Chcialbym aby program dzialal zawsze. Wiem, ze trzba dodac takie warunki

if ( (pocz!=NULL) && (pocz->nast==kon) )
{
...
}

if ( (pocz!=NULL) && (pocz->nast!=NULL) && (pocz->nast!=kon)

ale niestety nie daje rady. Prosze o pomoc.

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

typedef struct el_listy lista; 
typedef lista *ptr_lista; 
struct el_listy 

{ 
  	int dana; 
 	lista *nast; 
 	lista *pop; 
}; 

void dodaj_poczatek(ptr_lista *pocz, ptr_lista *kon) 
{ 
  lista *nowy; 
  nowy = (lista *)malloc(sizeof(lista)); 
  if(nowy == NULL)
  { printf("\n Brak miejsca"); 
  exit(-1); 
  } 
  nowy->dana=rand()%50; 
  nowy->nast=NULL;
  if(*pocz == NULL) 
  {
    nowy->pop=NULL; 
    *pocz=nowy; 
    *kon=nowy; 
  } else 
  { 
    nowy->pop=*kon; 
    (*kon)->nast=nowy; 
    *kon=nowy; 
  } 
} 

void wyswietl(lista *pocz) 
{ 
  lista *pomoc; 
  pomoc=pocz; 
  while (pomoc != NULL) 
  { 
    printf("Liczba to: %d\n",pomoc->dana);
    pomoc=pomoc->nast; 
  } 
} 

void zamien(ptr_lista *pocz, ptr_lista *kon) //napisz funkcje zamieniającą między sobą element pierwszy z ostatnim w liście.
{ 

  lista *nowy1; 
  lista *nowy2; 
  lista *nowy3;
  lista *nowy4;
  nowy1=*pocz;     
  nowy2=*kon;     
  nowy3=(*kon)->pop;
  nowy4=(*pocz)->nast;
  *pocz=nowy2;
  *kon=nowy1;
  (*kon)->pop=nowy3;
  (*pocz)->pop=NULL;
  (*pocz)->nast=nowy1->nast;
  (*kon)->nast=NULL;
  nowy3->nast=*kon;
  nowy4->pop=*pocz;
} 

void zamien2(ptr_lista *pocz)//napisz funkcje zamieniającą między sobą element pierwszy z drugim w liście.
{
  printf("Funkcja zamieniajaca miedzy soba element pierwszy z drugim w liscie\n");
  lista *nowy1;
  lista *nowy2;
  lista *nowy3;
  nowy1=*pocz;
  nowy2=(*pocz)->nast;
  nowy3=(*pocz)->nast->nast;
  nowy1->nast=nowy2->nast;
  *pocz=nowy2;
  nowy1->pop=*pocz;
  (*pocz)->nast=nowy1;
  (*pocz)->pop=NULL;
  nowy3->pop=nowy1;
}

void zamien3(ptr_lista *kon)//napisz funkcje zamieniającą między sobą element ostatni z przedostatnim w liście
{
  printf("Funkcja zamieniajaca miedzy soba element ostatni z przedostatnim w liscie\n");
  lista *nowy1;
  lista *nowy2;
  lista *nowy3;
  nowy1=*kon;
  nowy2=(*kon)->pop;
  nowy3=(*kon)->pop->pop;
  nowy1->pop=nowy2->pop;
  *kon=nowy2;
  nowy1->nast=*kon;
  (*kon)->pop=nowy1;
  (*kon)->nast=NULL;
  nowy3->nast=nowy1;
   
}

void kasuj(ptr_lista *pocz, ptr_lista *kon) 
{ printf("Funkcja usuwajaca z listy wszystkie elementy\n");
  lista *pomoc; 
  while(*pocz != NULL) 
  { 
    pomoc=*pocz; 
    *pocz=(*pocz)->nast;
    free(pomoc); 
  } 
  *pocz=NULL; 
  *kon=NULL; 
  printf("Lista skasowana\n\n"); 
} 

int main(int argc, char *argv[]) 
{ 
  lista *pocz, *kon; 
  int i; 
  time_t t; 
  pocz=NULL; 
  kon=NULL; 
  srand((unsigned) time(&t)); 
  for(i=0;i<10;i++) 
  { 
    dodaj_poczatek(&pocz, &kon);
  } 
  printf("Funkcja zamieniajaca miedzy soba element pierwszy z ostatnim w liscie\n");
  zamien(&pocz, &kon);
  wyswietl(pocz); printf("\n");
  zamien2(&pocz);
  wyswietl(pocz);printf("\n");
  zamien3(&kon);
  wyswietl(pocz);printf("\n");
  kasuj(&pocz, &kon);
  system("PAUSE"); 
  return 0; 
}
1

Nie wklejaj calego programu tylko funkcje ktore nie dzialaja, te 2 rodzaje wyswietlania,srednia,ile,dodawanie tylko zasmiecaja.

Jak masz pusta listę, albo ma tylko 1 element to chyba logiczne, że nie mozesz zamienic. Dodaj prosty warunek i zrob return false,0 czy cokolwiek.
Dla 2 elementow powinno dzialac, jak nie dziala to cos namieszales.

0

(ok usunąłem już zbędne funkcje u góry)

teraz tak: zmodyfikowałem już jedną z funkcji, tak że działa od 2 (włącznie) w górę. Ale nie mogę coś wymyślić jak napisać, żeby nie próbowała zamieniać, jak jest 0 lub 1 wartość.

void zamien(ptr_lista *pocz, ptr_lista *kon)
{

    lista *nowy1, *nowy2, *nowy3, *nowy4;
    nowy2=*kon;
    nowy1=*pocz;

    if(nowy1!=NULL && nowy1->nast==nowy2)
        {
            nowy1=*pocz;
            nowy2=*kon;
            nowy1->pop=nowy2;
            nowy1->nast=NULL;
            nowy2->pop=NULL;
            nowy2->nast=nowy1;
            *pocz=nowy2;
            *kon=nowy1;

        }
    else
        {

            nowy1=*pocz;
            nowy2=*kon;
            nowy3=(*kon)->pop;  /*zapamietanie przedostatniego elementu */
            nowy4=(*pocz)->nast;    /*zapamietnie 2 elementu */
            *pocz=nowy2;
            *kon=nowy1;
            nowy2->pop=*kon;
            (*kon)->pop=nowy3;
            (*pocz)->pop=NULL;
            (*pocz)->nast=nowy1->nast;
            (*kon)->nast=NULL;
            nowy3->nast=*kon;
            nowy4->pop=*pocz;
        }
}
1

sprawdź czy 'pocz' nie jest NULL'em lub pocz==kon bo wtedy mamy jeden element :)

0

dla jedynki mi działa, ale proszę o sprawdzenie, czy dobrze. Jeśli dobrze to zostało jeszcze te nieszczęsne 0.

P.S. Sorry, że taki upierdliwy jestem, ale trochę się już namęczyłem nad programem i nie mam pomysłów :).

Edit: Aha dodam, że rozumiem, że jak jest 0 to nie ma co zamieniać, tylko pragram ma być "idiotoodporny" i jak ktoś poda zero to nie zamknie się program, tylko wyświetli informację, że "nie mozna zamienic". :)

void zamien(ptr_lista *pocz, ptr_lista *kon)
{

    lista *nowy1, *nowy2, *nowy3, *nowy4;
    nowy2=*kon;
    nowy1=*pocz;

  if(nowy1 != NULL && nowy1==nowy2)
  { printf("\n Nie ma co zamieniac"); 
  exit(-1); }

    if(nowy1!=NULL && nowy1->nast==nowy2)
        {
            nowy1=*pocz;
            nowy2=*kon;
            nowy1->pop=nowy2;
            nowy1->nast=NULL;
            nowy2->pop=NULL;
            nowy2->nast=nowy1;
            *pocz=nowy2;
            *kon=nowy1;

        }
    else
        {

            nowy1=*pocz;
            nowy2=*kon;
            nowy3=(*kon)->pop;  /*zapamietanie przedostatniego elementu */
            nowy4=(*pocz)->nast;    /*zapamietnie 2 elementu */
            *pocz=nowy2;
            *kon=nowy1;
            nowy2->pop=*kon;
            (*kon)->pop=nowy3;
            (*pocz)->pop=NULL;
            (*pocz)->nast=nowy1->nast;
            (*kon)->nast=NULL;
            nowy3->nast=*kon;
            nowy4->pop=*pocz;
        }

}
1

wystarczy taki warunek zamiast tego co zrobiłeś :

 
if( pocz == NULL || pocz == kon)
{ 
...
}

Sprawdza dwa warunki a tylko jeden musi być spełniony aby zaprzestał dalszej pracy.

  1. sprawdza czy pocz == NULL co jest rownoznaczne z tym ze lista jest pusta
  2. sprawdza czy pocz == kon co oznacza ze lista ma jeden element

EDIT:
btw. jeśli to Twój kod to poćwicz trochę formatowanie kodu bo źle się czyta, i Tobie będzie źle i innym kiedyś, wbrew pozorom to jest dość ważne :)

0

Ok. Dzięki wielkie! Wszystko działa. Jak skończę wszystko poprawiać, to wrzucę całość, może się komuś na przyszłość przyda ;)

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