[C] Problem z sortowaniem listy dwukierunkowej w C

Awatar użytkownika
Basia89
Użytkownik
Użytkownik
Posty: 17
Rejestracja: 15 lis 2008, o 17:23
Płeć: Kobieta
Lokalizacja: Warszawa

[C] Problem z sortowaniem listy dwukierunkowej w C

Post autor: Basia89 »

Mam problem z samym posortowaniem listy dwukierunkowej, program miał wczytać elementy(f.dodaj) następnie je wypisać oraz przesortować (f.sortowanie) oraz wypisać posortowana liste. czy ktos moglby mi wytlumaczyc co jest zle i jak to poprawic?
Z gory dziekuje:)

Kod: Zaznacz cały

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

struct lista { 
    int key; 
    struct lista *next; 
} *head=NULL;    

void dodaj(int ile){ 
    struct lista *part=NULL, *ppart=head; 
    int liczba; 
    
    printf("Podaj 1 liczbe: "); 
    scanf("%d",&liczba); 
    head->key=liczba; 
    
    for(int i=1;i<ile;i++){ 
        printf("Podaj %d liczbe: ",i+1); 
        scanf("%d",&liczba); 
        
        part=(lista*)malloc(sizeof(lista)); 
        
        ppart->next=part; 
        part->next=NULL; 
        part->key=liczba; 
        ppart=part; 
    } 
} 
void wypisz(struct lista *head){ 

    if(head) { 

        printf("%d
",head->key); 
        wypisz(head->next);} 
    } 
  
void sortowanie(struct lista *head){ 
    lista *pom, *pom_pop; 
    lista * pop=NULL; 
    lista * nast; 
    bool ctrl=1; 
    while (ctrl=1) 
    { 
              printf("element do wfeiwubgr:"); 
          pom_pop=NULL; 
          pom=head; 
          ctrl=0; 
          while(pom->next != NULL) 
          { 

                          if (pom->key > pom->next->key) 
                          { 
                                       ctrl=1; 
                                       if (pom_pop) 
                                       { 
                                                   pom_pop->next = pom->next; 
                                                   pom->next = pom->next->next; 
                                                   pom_pop->next->next = pom; 
                                                   } 
                                       else 
                                       { 
                                           head = head->next; 
                                           pom->next = pom->next->next; 
                                           head->next = pom; 
                                           } 

                          } 
                          pom_pop=pom; 
                          pom=pom->next; 
          } 
    } 
                                        
} 

int main(void){ 
    head=(lista*)malloc(sizeof(lista)); 
    head->next=NULL; 
    int il; 
    printf("Ile elementow? "); 
    scanf("%d",&il); 
    dodaj(il); 
    wypisz(head); 
sortowanie(head); 
wypisz(head); 
    getchar(); 

    return 0; 
}
Ostatnio zmieniony 1 sty 2017, o 10:04 przez Afish, łącznie zmieniany 1 raz.
Powód: Poprawa wiadomości.
soku11
Użytkownik
Użytkownik
Posty: 6607
Rejestracja: 16 sty 2007, o 19:42
Płeć: Mężczyzna
Podziękował: 119 razy
Pomógł: 1823 razy

[C] Problem z sortowaniem listy dwukierunkowej w C

Post autor: soku11 »

Nie wiem, czy jest sens ten kod komentowac, gdyz w tresci jest wyraznie napisane, ze lista ma byc dwukierunkowa, a w deklaracji struktury wezla jest tylko wskaznik na nastepny element...
Moge tylko napisac takie ogolne odczycia co do kodu, bez sprawdzania poprawnosci:
1. Funkcja dodaj na moje oko powinna TYLKO dodawac jeden element do listy. Nie powinna sama z siebie pytac uzytkownika o liczby, tylko dodawac do listy zadana jako argument liczbe.
2. Funkcja dodaj bedzie dzialac tylko dla jednokrotnego wywolania. Tzn. przy jej dwukrotnym z rzedu wywolaniu dostaniesz wyciek pamieci (ustalisz od nowa liste z podanych elementow, a stara lista sie gdzies zapodzieje w pamieci).
3. Podaj moze jaki chcesz zrealizowac algorytm sortowania, gdyz nie chce mi sie przebijac przez gaszcz kodu i sie domyslac

Pozdrawiam.
Awatar użytkownika
Basia89
Użytkownik
Użytkownik
Posty: 17
Rejestracja: 15 lis 2008, o 17:23
Płeć: Kobieta
Lokalizacja: Warszawa

[C] Problem z sortowaniem listy dwukierunkowej w C

Post autor: Basia89 »

Z f. dodaj jest wszystko ok (chodzi o to ze ma wczytac to co jej podamy), chodzi o samo sortowanie, klasyczny bubble sort... porownujemy elementy ze soba przesuwajac wiekszy na dalsza pozycje, f. skonczy sie, gdy nie przesunie zadnego elementu-- 24 maja 2009, 22:50 --
soku11 pisze:Nie wiem, czy jest sens ten kod komentowac, gdyz w tresci jest wyraznie napisane, ze lista ma byc dwukierunkowa, a w deklaracji struktury wezla jest tylko wskaznik na nastepny element...
Bo najpierw pisałam ja dla jednokierunkowej;) ale to i tak nie zmienia faktu ze sie wykrzacza...
soku11
Użytkownik
Użytkownik
Posty: 6607
Rejestracja: 16 sty 2007, o 19:42
Płeć: Mężczyzna
Podziękował: 119 razy
Pomógł: 1823 razy

[C] Problem z sortowaniem listy dwukierunkowej w C

Post autor: soku11 »

Wiem, ze funkcja dodaj dziala. Napisalem poprostu moje odczucia co do tego kodu
Apropo sortowania, to pierwsze co mi sie rzuca w oczy, to zabawa na wskaznikach oraz warunek nieskonczony w petli while. Sprobuj zamiast tych kombinacji z przelaczaniem elementow zastapic ich wartosci, tzn:

Kod: Zaznacz cały

void sortowanie(struct lista *head)
{
  struct lista* pom=NULL;
  int tmp=0;
  int ctrl=1;

  while(ctrl==1)
  {
    pom=head;
    ctrl=0;
    while(pom->next != NULL)
    {
      if (pom->key > pom->next->key)
      {
         ctrl=1;
         tmp=pom->key;
         pom->key=pom->next->key;
         pom->next->key=tmp;
      }
      pom=pom->next;
    }
  }                                     
} 
Kod niesprawdzany, ale powinien dzialac
BTW. Warto sprawdzic tez, czy do funkcji nie podano nulla.

Pozdrawiam.
Awatar użytkownika
Basia89
Użytkownik
Użytkownik
Posty: 17
Rejestracja: 15 lis 2008, o 17:23
Płeć: Kobieta
Lokalizacja: Warszawa

[C] Problem z sortowaniem listy dwukierunkowej w C

Post autor: Basia89 »

Gdzie nieskonczona petla? jesli zamieni sie na ctrl=0; to petla sie skonczy...

Właśnie o to chodzi, ze niestety ma być to zabawa na wskaźnikach a nie zamiana wartości.....;(
soku11
Użytkownik
Użytkownik
Posty: 6607
Rejestracja: 16 sty 2007, o 19:42
Płeć: Mężczyzna
Podziękował: 119 razy
Pomógł: 1823 razy

[C] Problem z sortowaniem listy dwukierunkowej w C

Post autor: soku11 »

Przypomnij sobie dzial w ksiazce (bo zapewne jakas czytalas) o instrukcjach warunkowych. Kod, ktory mialas:

Kod: Zaznacz cały

while(ctrl=1)
Robi nic innego jak PRZYPISANIE do zmiennej ctrl wartosci 1. Nastepnie sprawdza warunek. Jako, ze zmienna bedzie tutaj ZAWSZE miala wartosc 1, to warunek rowniez bedzie mial wartosc 1, czyli petla bedzie nieskonczona. Dla ctrl=0 bedzie podobnie, tylko ze wartosc logiczna bedzie 0 (taka jak wartosc zmiennej), czyli nie wykona sie znow ani razu. Popatrz na moj kod, tam jest poprawny warunek, tj:

Kod: Zaznacz cały

while(ctrl==1)
Wtedy poprostu porownujesz wartosc ctrl z 1, a nie przypisujesz do niej zadnej wartosci


Co do samego sortowanie, to zakladajac, ze jest to lista dwukierunkowa (dla jednokierunkowej potrzeba znalezc poprzednika dla dla zmiany wskaznikow), to wydaje mi sie, ze taka zamiana da poprawny rezultat:

Kod: Zaznacz cały

if(pom->key > pom->next->key)
{
  ctrl=1;
  if(pom!=head)         /* zmiana gdzies w srodku */
  {
    pom->prev->next=pom->next;
    pom->next->prev=pom->prev;
    pom_pop=pom->next;
    pom->next=pom_pop->next;
    pom->prev=pom_pop;
    pom_pop->next=pom;
  }
  else                     /* zamiana pierwszy z drugim */
  {
    head=head->next;
    head->prev=NULL;
    pom->next=head->next;
    head->next=pom;
    pom->next->prev=pom;
    pom->prev=head;
  }
} 
Pozdrawiam.
Awatar użytkownika
Basia89
Użytkownik
Użytkownik
Posty: 17
Rejestracja: 15 lis 2008, o 17:23
Płeć: Kobieta
Lokalizacja: Warszawa

[C] Problem z sortowaniem listy dwukierunkowej w C

Post autor: Basia89 »

No i niestety nadal nie dziala poprawnie...Nie wiem co tu jest zle...
soku11
Użytkownik
Użytkownik
Posty: 6607
Rejestracja: 16 sty 2007, o 19:42
Płeć: Mężczyzna
Podziękował: 119 razy
Pomógł: 1823 razy

[C] Problem z sortowaniem listy dwukierunkowej w C

Post autor: soku11 »

Napisz konkretnie co jest zle. Wywala sie program, czy co? Bo ja wrozka nie jestem

BTW. Przekazujac argument do funkcji sortuj nie spowoduje zmiany adresu head zmiennej globalnej. Tak wiec mozesz albo przekazac wskaznik na ten wskaznik, albo manipulowac bezposrednio na wskazniku glowy bez przekazywania argumentu. Jesli po sortowaniu wyswietlasz liste wlasnie z wskaznika head to mozesz uzyskac rozne dziwne informacje.

Pozdrawiam.
Awatar użytkownika
Basia89
Użytkownik
Użytkownik
Posty: 17
Rejestracja: 15 lis 2008, o 17:23
Płeć: Kobieta
Lokalizacja: Warszawa

[C] Problem z sortowaniem listy dwukierunkowej w C

Post autor: Basia89 »

Dziekuje bardzo za pomoc:D

Juz sobie poradziłam i działa prawie dobrze:):)
Awatar użytkownika
Mariusz M
Użytkownik
Użytkownik
Posty: 6909
Rejestracja: 25 wrz 2007, o 01:03
Płeć: Mężczyzna
Lokalizacja: 53°02'N 18°35'E
Podziękował: 2 razy
Pomógł: 1246 razy

[C] Problem z sortowaniem listy dwukierunkowej w C

Post autor: Mariusz M »

soku11 pisze:Napisz konkretnie co jest zle. Wywala sie program, czy co? Bo ja wrozka nie jestem
No jak nie umiesz czytać kodu to jak chcesz pomóc

Co do sortowania to proponuję przez scalanie bo działa dość szybko,
zachowa poprawną kolejność kluczy i nie zwolni tak jak tzw szybkie

Aby pobawić się listą trzeba napisać funkcję dodającą element do listy oraz usuwającą element z listy

Jeśli chcemy znaleźć element po którym należy dokonać podziału listy to możemy wykorzystać pomysł
znany z listy jednokierunkowej w którym obydwa wskaźniki ustawiamy na głowę i jeden iterujemy o jedno pole a drugi iterujemy o dwa pola
Możemy też jeden wskaźnik ustawić na głowę a drugi na ogon i iterować na przemian
od ogona do głowy oraz od głowy do ogona

Jeżeli chcemy scalić dwie posortowane listy a nie chcemy używać rekurencji ani wartowników to
sprawdzamy czy któraś z list nie jest pusta jeśli tak zwracamy drugą
Jeśli obydwie nie są puste porównujemy głowy i głowę o mniejszym kluczu zachowujemy
Porównujemy pozostałe elementy w pętli dopóki obydwie listy nie są puste
Jeśli opróżnimy elementy z jednej z list to ustawiamy wskaźniki na pozostałe elementy niepustej listy

Co do sortowania to rekurencyjne podejście wygląda tak
Dzielimy listę na dwie części
(jeżeli lista ma nieparzystą liczbę węzłów to jedna podlista będzie zawierała o jeden element więcej)
sortujemy rekurencyjnie obydwie części listy
łączymy posortowane części listy

Warto też rozważyć to jak często potrzebujemy sortować tę listę
i czy nie lepiej byłoby napisać procedurę która by od razu wstawiała element w odpowiednie miejsce
ODPOWIEDZ