program
Benny: #include <iostream>
using namespace std;
struct ellisty
{
int klucz;
ellisty* nast;
};
class lista
{
ellisty* glowa;
public:
lista();
void sortowanie();
void zamien(ellisty*, ellisty*);
void zamien2(ellisty*, ellisty*);
void wypisz();
void wstaw(ellisty*, int);
ellisty* zwrocglowe();
};
ellisty* lista::zwrocglowe()
{
return glowa;
}
void lista::sortowanie()
{
ellisty *pomi, *pomj, *pomk;
pomi=glowa;
int min;
while (pomi−>nast!=NULL)
{
min=pomi−>nast−>klucz;
pomk=pomi;
pomj=pomi−>nast;
while(pomj−>nast!=NULL)
{
if (pomj−>nast−>klucz<min)
{
min=pomj−>nast−>klucz;
pomk=pomj;
}
pomj=pomj−>nast;
}
zamien2(pomi, pomk);
pomi=pomi−>nast;
}
}
void lista::zamien(ellisty* pomi, ellisty* pomk)
{
int y;
y=pomi−>nast−>klucz;
pomi−>nast−>klucz=pomk−>nast−>klucz;
pomk−>nast−>klucz=y;
}
void lista::zamien2(ellisty* poz1, ellisty* poz2)
{
if (poz1!=poz2)
{
if (poz2==poz1−>nast)
{
ellisty* pom3;
pom3=poz2−>nast;
poz1−>nast=pom3;
poz2−>nast=pom3−>nast;
pom3−>nast=poz2;
}
else
{
ellisty *pom3, *pom4;
pom3=poz1−>nast;
pom4=poz2−>nast−>nast;
poz1−>nast=poz2−>nast;
poz2−>nast−>nast=pom3−>nast;
poz2−>nast=pom3;
pom3−>nast=pom4;
}
}
}
void lista::wstaw(ellisty* poz, int x)
{
ellisty* pom;
pom=new ellisty;
if (pom!=NULL)
{
pom−>klucz=x;
pom−>nast=poz−>nast;
poz−>nast=pom;
}
}
lista::lista()
{
glowa=new ellisty;
if (glowa!=NULL)
glowa−>nast=NULL;
}
void lista::wypisz()
{
ellisty* pom;
pom=glowa−>nast;
while(pom!=NULL)
{
cout << pom−>klucz << " ";
pom=pom−>nast;
}
cout << endl;
}
main()
{
lista A;
A.wstaw(A.zwrocglowe(), 5);
A.wstaw(A.zwrocglowe(), 7);
A.wstaw(A.zwrocglowe(), 8);
A.wstaw(A.zwrocglowe(), 8);
A.wstaw(A.zwrocglowe(), 9);
A.wstaw(A.zwrocglowe(), 1);
A.wstaw(A.zwrocglowe(), 0);
A.wypisz();
A.sortowanie();
A.wypisz();
}
Mógłby ktoś prześledzić program i opisać jego działanie?
3 sty 23:56
Mariusz:
Co do sortowania to proponuję przez scalanie lub napisać procedurę wstawiającą
tak aby dane były posortowane zależnie od tego jak często potrzebujemy sortować
4 sty 06:09
Mariusz:
// funkcje do obsługi stosu i kolejki
Funkcja sprawdzają czy lista jest pusta
Funkcja dodająca węzeł na początek listy
Funkcja dodająca węzeł na koniec listy
Funkcja zdejmująca pierwszy węzeł listy
// funkcje dodające i usuwające węzły
Funkcja dodająca węzeł za węzłem o danym kluczu
Funkcja dodająca węzeł przed węzłem o danym kluczu
Funkcja dodająca węzeł tak aby dane były posortowane według klucza
Funkcja usuwająca węzeł o danym kluczu
Funkcja usuwająca wszystkie węzły z listy
// funkcje dodatkowe
Funkcja zwracająca liczbę węzłów
Funkcja wyszukująca węzeł o danym kluczu
Funkcja sortująca listę przez scalanie
Funkcja wypisująca dane zawarte w węzłach listy
Musisz pisać obiektowo ?
Jeśli tak użyj szablonów
Jeśli nie typem danych powinien być void*
Nie używasz referencji tam gdzie funkcja powinna zmodyfikować listę ?
4 sty 06:17
Mariusz:
Referencja czy drugi wskaźnik to do podejścia strukturalnego
Twoje sortowanie wygląda tak w jednej pętli while przechodzisz listę
W drugiej pętli szukasz minimum po znalezieniu minimum wychodzisz z najbardziej zagnieżdżonej
pętli i zamieniasz element znaleziony element z iterowanym w zewnętrznej pętli
Złożoność twojego algorytmu to O(n2) a można było uzyskać lepszy czas
Niektórzy mogą się przyczepić do tego że strukturę węzła masz na zewnątrz klasy
Poza tym brak funkcji usuń może powodować wycieki pamięci
O twoim kodzie będzie mógł trochę napisać Dziadek o ile będzie mu się chciało czytać kod
4 sty 07:07
Benny: To nie jest mój kod, dlatego pytałem o jego działanie.
4 sty 10:23
Mariusz:
Benny na razie dodałem szablony
Złym nawykiem jest pisanie konstruktorów bez destruktorów
i funkcji wstawiających bez funkcji usuwających
// to nie Java że mamy odśmiecacza tzw garbage collectora
Powyższym trzeba się teraz zająć
Pomyśl nad funkcją wstawiającą węzeł w sposób aby dane były posortowane
według klucza
Na youtube jest do tego filmik , ciebie powinna zainteresować
procedura InsertarOrdenado(var cabeza: PNodo;clave:integer);
Po polsku jest taka strona gdzie koleś podaje łatwe do przepisania pseudokody
w postaci listy kroków a nawet podaje przykładowe kody
Niestety nie uzwględnia on obsługi błędów
http://eduinf.waw.pl/inf/alg/001_search/0083.php
Jeżeli chodzi o przyspieszenie sortowania to sortowanie rozbijasz na trzy funkcje
1. Funkcje rozdzielająca listę na dwie podlisty
Dla parzystej liczby węzłów podlisty będą miały tyle samo elementów
Dla nieparzystej liczby węzłów jedna podlista będzie miała o jeden element więcej
1) zapamiętać wskaźnik na głowę listy wejściowej,
2) znaleźć węzeł, który będzie ostatnim węzłem pierwszej listy docelowej,
3) zapamiętać wskaźnik na Next węzła znalezionego w punkcie 2.,
4) wpisać do Next wartość NULL węzła znalezionego w punkcie 2.,
5) zwrócić wskaźnik na węzeł zapamiętany w punkcie 1., jako wskaźnik na głowę
pierwszej listy docelowej,
6) zwrócić wskaźnik na węzeł zapamiętany w punkcie 3., jako wskaźnik na głowę
drugiej listy docelowej;
Jak znaleźć węzeł z punktu 2
Ustawić dwa wskaźniki pomocnicze na głowę,
jeden z nich iterować o jedno pole a drugi iterować o dwa pola
Gdy ten wskaźnik iterowany o dwa pola osiągnie NULL ten iterowany o jedno pole
osiągnie węzeł po którym listę należy rozdzielić
Scalanie dwóch posortowanych list
Tutaj są różne podejścia:
rekurencyjne, iteracyjne z wartownikiem, iteracyjne bez wartownika
1. Sprawdzasz czy któraś z list jest pusta
jeśli tak to zwracasz drugą listę
2. Jeśli obydwie listy nie są puste porównujesz wartości kluczy w węzłach będących
głowami list i zachowujesz tę o mniejszym kluczu
3. Porównujesz w pętli pozostałe elementy list dopóki obydwie listy są niepuste
4. Gdy jedna z porównywanych list będzie pusta dopisujesz do wyniku elementy z tej drugiej
listy
Sortowanie
Gdy lista ma więcej niż jeden element to
(sprawdzasz to używając wskaźnika na głowę i jego następnika)
Dzielisz listę na dwie podlisty
Sortujesz rekurencyjnie obydwie podlisty
Łączysz dwie posortowane podlisty
4 sty 14:03
Mariusz:
W konstruktorze nie inicjuje głowy na węzeł tylko allokuje pamięć na węzeł
i jeżeli głowa wskazuje na jakiś węzeł przypisuje następnikowi wartość NULL
Ogólnie trochę dziwna ta klasa i nie wiem czy jest sens przyspieszać to sortowanie
Tylko napisać tę klasę od nowa a jeśli nie jesteś w tym dobry to może zacząć od
podejścia strukturalnego jak w C
#include <iostream>
using namespace std;
template <class T>
struct el listy
{
T klucz;
el listy<T>* nast;
};
template <class T>
class lista
{
el listy<T>* glowa;
public:
lista();
~lista();
void sortowanie();
void zamien(el listy<T>*, el listy<T>*);
void zamien2(el listy<T>*, el listy<T>*);
void wypisz();
ellisty<T>*znajdz(T);
// void odwroc();
void wstaw(el listy<T>*, T);
void usun pierwszy();
void usun(el listy<T>*);
el listy<T>* zwrocglowe();
};
template <class T>
el listy<T>* lista<T>::zwrocglowe()
{
return glowa;
}
template <class T>
void lista<T>::sortowanie()
{
el listy<T> *pomi, *pomj, *pomk;
pomi=glowa;
T min;
if(glowa!=NULL&&glowa−>nast!=NULL)
{
while (pomi−>nast!=NULL)
{
min=pomi−>nast−>klucz;
pomk=pomi;
pomj=pomi−>nast;
while(pomj−>nast!=NULL)
{
if (pomj−>nast−>klucz<min)
{
min=pomj−>nast−>klucz;
pomk=pomj;
}
pomj=pomj−>nast;
}
zamien2(pomi, pomk);
pomi=pomi−>nast;
}
}
}
template <class T>
void lista<T>::zamien(el listy<T>* pomi, ellisty<T>* pomk)
{
T y;
y=pomi−>nast−>klucz;
pomi−>nast−>klucz=pomk−>nast−>klucz;
pomk−>nast−>klucz=y;
}
template <class T>
void lista<T>::zamien2(el listy<T>* poz1, el listy<T>* poz2)
{
if (poz1!=poz2)
{
if (poz2==poz1−>nast)
{
el listy<T>* pom3;
pom3=poz2−>nast;
poz1−>nast=pom3;
poz2−>nast=pom3−>nast;
pom3−>nast=poz2;
}
else
{
el listy<T> *pom3, *pom4;
pom3=poz1−>nast;
pom4=poz2−>nast−>nast;
poz1−>nast=poz2−>nast;
poz2−>nast−>nast=pom3−>nast;
poz2−>nast=pom3;
pom3−>nast=pom4;
}
}
}
template <class T>
void lista<T>::wstaw(el listy<T>* poz, T x)
{
el listy<T>* pom;
pom=new el listy<T>;
if (pom!=NULL)
{
pom−>klucz=x;
pom−>nast=poz−>nast;
poz−>nast=pom;
}
}
template <class T>
lista<T>::lista()
{
glowa=new el listy<T>;
if (glowa!=NULL)
glowa−>nast=NULL;
}
template <class T>
void lista<T>::wypisz()
{
el listy<T>* pom=NULL;
if(glowa!=NULL)
pom=glowa−>nast;
while(pom!=NULL)
{
cout << pom−>klucz << " ";
pom=pom−>nast;
}
cout << "NULL"<<endl;
}
template <class T>
el listy<T>* lista<T>::znajdz(T wartosc)
{
el listy<T> *p;
p=glowa;
while((p!=NULL)&&(p−>klucz!=wartosc)) p=p−>nast;
return p;
}
/*template <class T>
void lista<T>:: odwroc()
{
el listy<T> *p=NULL;
el listy<T> *pc=NULL;
if(glowa!=NULL)
{
pc=glowa;
while(pc−>nast!=NULL)
{
p=pc−>nast;
pc−>nast=p−>nast;
p−>nast=glowa;
glowa=p;
}
}
}*/
template <class T>
void lista<T>::usun pierwszy()
{
ellisty<T> * p=glowa;
if(p!=NULL)
{
glowa = p−>nast; // nowy początek
delete p; // usuń element z pamięci
}
}
template <class T>
void lista<T>::usun(el listy<T> * e)
{
el listy<T> * p;
if(glowa == e&&e!=NULL)
{
usun pierwszy();
}
else if(e!=NULL)
{
p=glowa;
while((p!=NULL)&&(p−>nast != e)) p = p−>nast;
if(p!=NULL)
{
p−>nast = e−>nast;
delete e;
}
}
}
template <class T>
lista<T>::~lista()
{
while(glowa!=NULL)
{
usun pierwszy();
}
}
int main()
{
lista<int> A;
A.wstaw(A.zwrocglowe(), 5);
A.wstaw(A.zwrocglowe(), 7);
A.wstaw(A.zwrocglowe(), 8);
A.wstaw(A.zwrocglowe(), 8);
A.wstaw(A.zwrocglowe(), 9);
A.wstaw(A.zwrocglowe(), 1);
A.wstaw(A.zwrocglowe(), 0);
/* A.wstaw(A.zwrocglowe(),'z');
A.wstaw(A.zwrocglowe(),'s');
A.wstaw(A.zwrocglowe(),'u');
A.wstaw(A.zwrocglowe(),'i');
A.wstaw(A.zwrocglowe(),'r');
A.wstaw(A.zwrocglowe(),'a');
A.wstaw(A.zwrocglowe(),'M'); */
A.wypisz();
A.sortowanie();
A.wypisz();
//A.odwroc();
// A.wypisz();
//A.usun(A.znajdz(8));
//A.wypisz();
A.~lista();
cin.get();
return 0;
}
5 sty 10:09