• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

std::sort() - c++

Object Storage Arubacloud
0 głosów
537 wizyt
pytanie zadane 30 czerwca 2022 w C i C++ przez diedassel Użytkownik (570 p.)

Witam, moglby ktos wytlumaczyc po chlopsku do czego sluzy trzeci parametr w funckji std::sort() ?

Tutaj jest wytlumaczone, ale za bardzo informatycznie

3 odpowiedzi

+1 głos
odpowiedź 30 czerwca 2022 przez Kabuuz Bywalec (2,820 p.)
Służy do porównywaniu dwóch elementów. Dzięki temu wiadomo jak ma być posortowany zbiór (np. liczb -malejąco/rosnąco)
+1 głos
odpowiedź 30 czerwca 2022 przez j23 Mędrzec (194,920 p.)
Podajesz tam adres funkcji lub obiekt funkcyjny, który ma porównywać dwie wartości podane przez funkcję sortującą.
0 głosów
odpowiedź 1 lipca 2022 przez profesorek96 Szeryf (91,420 p.)
edycja 1 lipca 2022 przez profesorek96

Zacznijmy od początku, weźmy na warsztat taki oto kod:

#include <iostream>
#include <algorithm>
#define N 7
using namespace std;

int main() {
	int tab[N]={5,7,2,1,0,3,-5};
	sort(tab,tab+N);
	for(int i=0;i<N;i++)
	{
		cout<<tab[i]<<" ";
	}
	return 0;
}

Program ten nie robi nic innego jak sortuje tablice o nazwie tab za pomocą funkcji sort. Funkcja ta przyjmuje minimalnie dwa argumenty, maksymalnie trzy. Pierwszy argument to adres na początek zakresu do posortowania zaś drugi to wskaźnik na koniec zakresu. Opcjonalny, trzeci argument to wskaźnik na funkcję. Funkcja ta ma jednoznacznie określać, jak funkcja sort ma porównywać między sobą dwa elementy. W przypadku typów wbudowanych takich jak int, double itp nie jest konieczne tworzenie własnej funkcji porównującej. Standardowo funkcja sort sortuje elementy rosnąco.

Co jeśli chcieli byśmy sortować elementy w inny, przez nas określony sposób np. malejąco.

#include <iostream>
#include <algorithm>
#define N 7
using namespace std;
bool por(const int& a,const int& b)
{
	if(a>b)
	{
		return true;
	}
	else
	{
		return false;
	}
}
int main() {
	int tab[N]={5,7,2,1,0,3,-5};
	sort(tab,tab+N,por);
	for(int i=0;i<N;i++)
	{
		cout<<tab[i]<<" ";
	}
	return 0;
}

W tym przypadku nie obyło się bez stworzenia własnej funkcji porównującej. Warto sobie zapamiętać, że funkcja ta zawsze zwraca wartość typu bool oraz przyjmuje dwa argumenty. Argumenty te muszą być tego samego typu co sortowana kolekcja. W powyższym kodzie argumenty są typu int (użyłem referencji by nie dochodziło do tworzenia się niepotrzebnych kopii).

Weźmy teraz na warsztat sortowanie tablicy zawierającej obiekty jakiejś klasy. Spójrz na poniższy kod:

#include <iostream>
#include <algorithm>
#define N 3
using namespace std;
class Punkt2d
{
	public:
	int x,y;
	Punkt2d(int X,int Y):x(X),y(Y){}
	void wypisz()
	{
		cout<<x<<","<<y<<endl;
	}
};
int main() {
	Punkt2d tab[N]={Punkt2d(3,7),Punkt2d(-2,7),Punkt2d(7,7)};
	sort(tab,tab+N);//ta linia jest bledna
	for(int i=0;i<N;i++)
	{
		tab[i].wypisz();
	}
	return 0;
}

Tworzymy klasę reprezentującą punkt na płaszczyźnie 2D. Następnie tworzymy tablicę zawierającą trzy obiekty tej klasy. W kolejnej linii wywołujemy funkcję sort. Wydawać by się mogło, że wszystko jest ok, niestety program ten nie skompiluje się poprawnie. Problemem jest to, że funkcja sort nie potrafi, nie wie jak ma porównywać elementy sortowanej tablicy. Musimy ją tego nauczyć przez zdefiniowanie funkcji porównującej.

#include <iostream>
#include <algorithm>
#define N 3
using namespace std;
class Punkt2d
{
	public:
	int x,y;
	Punkt2d(int X,int Y):x(X),y(Y){}
	void wypisz()
	{
		cout<<x<<","<<y<<endl;
	}
};
bool por(const Punkt2d & a,const Punkt2d & b)
{
	if(a.x<b.x)
	{
		return true;
	}
	else
	{
		return false;
	}
}
int main() {
	Punkt2d tab[N]={Punkt2d(3,7),Punkt2d(-2,7),Punkt2d(7,7)};
	sort(tab,tab+N,por);
	for(int i=0;i<N;i++)
	{
		tab[i].wypisz();
	}
	return 0;
}

Powyższy kod kompiluje się, sortowane są obiekty klasy Punkt2d względem pola x, rosnąco.

Co ciekawe istnieje sposób na to, aby można było nauczyć funkcję sort jak ma sortować elementy kolekcji bez podawania trzeciego argumentu. Wystarczy, że wewnątrz klasy przeciążymy operator <. Kod zawierający takie przeciążenie znajduje się poniżej:

#include <iostream>
#include <algorithm>
#define N 3
using namespace std;
class Punkt2d
{
	public:
	int x,y;
	Punkt2d(int X,int Y):x(X),y(Y){}
	bool operator<(const Punkt2d other)const
	{
		if(this->x<other.x)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	void wypisz()
	{
		cout<<x<<","<<y<<endl;
	}
};
int main() {
	Punkt2d tab[N]={Punkt2d(3,7),Punkt2d(-2,7),Punkt2d(7,7)};
	sort(tab,tab+N);
	for(int i=0;i<N;i++)
	{
		tab[i].wypisz();
	}
	return 0;
}

 

komentarz 2 lipca 2022 przez j23 Mędrzec (194,920 p.)

W powyższym kodzie argumenty są typu int (użyłem referencji by nie dochodziło do tworzenia się niepotrzebnych kopii)

Przekazywanie wartości typu int przez const& jest nieco bez sensu. Koszt przekazania wartości tego typu i wskaźnika na nią jest dokładnie taki sam (wartość trzeba jeszcze później wyłuskać).

 

Podobne pytania

+3 głosów
3 odpowiedzi 1,025 wizyt
0 głosów
1 odpowiedź 181 wizyt
0 głosów
1 odpowiedź 589 wizyt
pytanie zadane 7 marca 2020 w C i C++ przez TheFandorn Nowicjusz (140 p.)

92,666 zapytań

141,564 odpowiedzi

320,022 komentarzy

62,033 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...