Sortowanie rozszerzone wzgl. 2 kolumny

0

Cześć!
Mam problem, jak to posortować aby z tego:
120 220
730 1030
600 730
730 1230
Powstało to:
120 220
600 730
730 1030
730 1230
(Było posortowane wzgl. 2 kolumny ale żeby pierwsza kolumna pasowała, do 2 kolumny tak jak bylo to na poczatku.

0

std::sort przyjmuje funkcję porównującą jako jeden z argumentów, to mu ją odpowiednio napisz… Tam w zależności od tego, jak dokładnie u Ciebie wygląda ta struktura danych, to może być coś na modłę:

std::sort(t.begin(), t.end(),
          [](const std::pair<int, int> &a, const std::pair<int, int> &b) {return a.second < b.second;}
    );

(nie mam kompilatora pod ręką, pisane z palca)

1

Ułóż to w jakąś strukturę danych, np. ```vector``| par, napisz funkcję porównująca pary względem pierwszego elementu i przekaż ja do procedury sortującej.

0

@lion137: Mógłbyś trochę bardziej rozwinąć? Nie do końca się oswoiłem z vector i pair

0

@Kondzio33: To mój kod, wyjście to tak jak mówiłem ma być posortowane wzgl 2 kolumny.

#include <iostream>
using namespace std;
int main (){
int n,pierwsza[1024],druga[1024];
cin >> n;
for(int i=1; i<=n; ++i)
    cin >> pierwsza[i] >> druga[i];


return 0;}


0

@Althorion:
Tak to wygląda

#include <iostream>
using namespace std;
int main (){
int n,pierwsza[1024],druga[1024];
cin >> n;
for(int i=1; i<=n; ++i)
    cin >> pierwsza[i] >> druga[i];

return 0;}
3

U Ciebie na razie obie te tablice (pierwsza, druga) są kompletnie niepowiązane. Żeby rozwiązać Twój problem, musisz im zadać jakąś relację.

Sensowniej: na etapie wczytywania. Zrobić sobie std::vector std::pair<int> i wrzucać tam — a potem sortowanie jak wyżej u mnie (z dokładnością do jakichś drobnych poprawek składniowych). Masz doskonałą okazję, żeby się oswoić z tymi kontenerami, bo będziesz z nich korzystać co chwila.

Jest też opcja „przebijania głową muru” — czyli nadłożenia roboty, żeby przesunąć w czasie nauczenia się czegoś nowego. Jeśli wybierasz tę opcję, to zaprogramuj sobie samodzielnie taki algorytm sortujący jaki lubisz, przeleć nim druga tablicę, ale gdy przychodzi do zamiany wartości, zamień nie tylko te z druga, ale i te z pierwsza.

0

@Althorion:
Wielkie, dzięki naprawdę!
Zrobiłem to tak, dla przykładowych danych wyszło dobrze wiec chyba jest okay :D

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main ()
{
    int n;
    cin >> n;
    vector <pair <int,int> > P(n);
    for(int i=0; i<n; ++i)
        cin >> P[i].first >> P[i].second;
    cout << "\n";
    sort(P.begin(),P.end());

     for(int i=0; i<n; ++i)
        cout << P[i].first << " " << P[i].second << endl;
    return 0;
}
0

Twój obecny kod sortuje po pierwszej współrzędnej (lewej kolumnie). Ale jesteś już b. blisko, zobacz wyżej jak zmienić funkcję porównującą na taką, która patrzy na drugą wartość. Możesz też użyć std::tie, jeśli nie chcesz ignorować pierwszej wartości, tylko użyć jej jako drugorzędnej wartości sortowanej (tzn. „jeśli wartości w prawej kolumnie są takie same, porównaj wartości z lewej kolumny”).

0

@Althorion:
Okay? Jeśli tak mógłbyś dokładniej wytłumaczyć to po przecinku w sort po P.end()? Nie rozumiem po co tam jest " [] ". Jeszcze raz wielkie dzięki.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main ()
{
    int n;
    cin >> n;
    vector <pair <int,int> > P(n);
    for(int i=0; i<n; ++i)
        cin >> P[i].first >> P[i].second;
    cout << "\n";
    sort(P.begin(), P.end(),[](pair<int, int> a, pair<int, int> b) {return a.second<b.second;});

     for(int i=0; i<n; ++i)
        cout << P[i].first << " " << P[i].second << endl;
    return 0;
}
1

To jest składnia do tworzenia funkcji anonimowych (tzw. „lambd”, od rachunku lambda). Czasem zachodzi potrzeba formalna zrobienia jakiejś funkcji — jak na przykład tutaj, gdzie chcemy ją dostarczyć funkcji std::sort do wykonywania porównań — ale nie zachodzi taka potrzeba praktyczna. Tzn. język od nas tego wymaga składniowo, ale nam, programistom, to raczej niepotrzebne, bo chcemy tej funkcji użyć dokładnie raz i nie ma sensu celebrować całego rytuału z tym związanego. Zatem, zamiast pisać tak:

bool compare(const std::pair<int, int> &a, const std::pair<int, int> &b) {
    return a.second < b.second;
}

gdzieś w programie, a potem odwoływania się do tej funkcji po jej nazwie compare, możemy sobie szybko zrobić funkcję, nie nazywać jej, i zapisać to samo krócej i od razu w miejscu, w którym nam jest potrzebna — co poprawia czytelność.

Pełna dokumentacja: https://en.cppreference.com/w/cpp/language/lambda

0

@Althorion: A tak z czystej, ciekawości, bo zadanie już zrobiłem. Jak mógłbym zrobić to zadanie (najlepiej na moich danych) używając tie?

0

Ja bym coś takiego pyknął:

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
#include <tuple>

int main() {
	std::vector<std::pair<int, int>> data(42);
	int x, y;

	for (auto &i: data) {
		std::cin >> x >> y;
		i = std::make_pair(x, y);
	}

	std::sort(data.begin(), data.end(),
	          [](const std::pair<int, int> &a, const std::pair<int, int> &b)
	            {return std::tie(a.second, a.first) < std::tie(b.second, b.first);}
	         );

	for (const auto &i: data) {
		std::cout << i.first << '\t' << i.second << '\n';
	}

	return 0;
}

Pewnie się da jakoś ładniej (te int x, y mnie szczególnie drażnią…), ale za rzadko używam C++ żeby wiedzieć jak.

2

@Althorion, czy nie prościej tak:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() 
{
	size_t count;
	cin>>count;
	vector<pair<int,int>> data(count);
	for(auto &i:data) cin>>i.second>>i.first;
	sort(begin(data),end(data));
	for(const auto &i:data) cout<<i.second<<'\t'<<i.first<<endl;
	return 0;
}
0

cin faktycznie lepszy, a z sortowaniem… To już zależy jak bardzo chcemy zrobić zadanie jak jest zapisane, a jak bardzo as if. Jak to część czegoś większego, to może być z tym różnie.

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