priority_queue, wyrzucany wyjątek invalid comparator

0
#include <iostream>
#include <queue>

struct Point
{
	Point(int p_x,int p_y):x(p_x),y(p_y){}
	int x;
	int y;
};

class ComparePoints
{
public:
	bool operator()(Point *p1,Point *p2) const
	{
		if ((p1->x*p1->x + p1->y*p1->y) > (p2->x*p2->x + p2->y*p2->y))
			return true;
		else if ((p1->x*p1->x + p1->y*p1->y) == (p2->x*p2->x + p2->y*p2->y))
			return rand() % 2;
		return false;
	}
};

int main()
{
	std::priority_queue < Point*, std::vector<Point*>, ComparePoints> q;
	for (int i = 0; i < 10; ++i)
		q.push(new Point(rand() % 10, rand() % 10));
	for (int i = 0; i < 10; ++i)
	{
		std::cout << q.top()->x << " " << q.top()->y << std::endl;
		q.pop();
	}
	system("pause");
	return 0;
} 

Jak uruchamiam program to wyrzuca mi wyjątek "invalid comparator". Jak debugowałem program to dzieje się tak przy którejś operacji push. O co tu może chodzić?

2

return rand() % 2;

Łamiesz strict weak ordering, które jest wymagane od komparatora. Jeśli a > b to b > a nigdy nie może być prawdziwe. (jeśli (a > b) == false i (b > a) == false to a == b).

0

Czy mógłbyś dokładniej wytłumaczyć co to jest w C++ "strict weak ordering"? Co należałoby zrobić aby kod działał? Chciałbym aby dla punktów o równej odległości od początku układu współrzędnych przy porównywaniu jako większy wybierany był losowo jeden z nich.

1

Dla tych samych punktów wynik porównania nie ma prawa być różny pomiędzy porównaniami.

0

Czyli rozumiem, że za pomocą priority_queue nie można wykonać tego co napisałem powyżej?

0

Można, tylko nie wiem czy to zasadne, biorąc pod uwagę ilość dodatkowej implementacji. Mając punkty a, b, i c nie możesz doprowadzić do sytuacji, gdzie a<b, b<c i c<a.

Jak chcesz słabą pseudolosowość to porównuj adres obiektów, dla których wykonujesz porównanie.

return std::greater<>{}(p1,p2);
2

strict partial order to pewien rodzaj porządku częściowego. To matematyka, pewna relacja na danym zbiorze. Poczytaj.

0

No właśnie czytam. Są gdzieś po polsku omówione te pojęcia, czy jak to wszędzie w infie tylko na angielskich stronach?

0
#include <iostream>
#include <queue>
#include <random>

struct Point
{
	Point(int p_x,int p_y):x(p_x),y(p_y){}
	int x;
	int y;
};

class ComparePoints
{
public:
	bool operator()(Point *p1,Point *p2) const
	{
		if ((p1->x*p1->x + p1->y*p1->y) > (p2->x*p2->x + p2->y*p2->y))
			return true;
		else if ((p1->x*p1->x + p1->y*p1->y) == (p2->x*p2->x + p2->y*p2->y))
			return p1>p2;
		return false;
	}
};

int main()
{
	std::priority_queue < Point*, std::vector<Point*>, ComparePoints> q;
	for (int i = 0; i < 10; ++i)
		q.push(new Point(rand() % 10, rand() % 10));
	for (int i = 0; i < 10; ++i)
	{
		std::cout << q.top()->x << " " << q.top()->y << std::endl;
		q.pop();
	}
	system("pause");
	return 0;
} 

No dobra. Napisałem program ze słabą pseudolosowością, gdzie w przypadku punktów o równej odległości od początku układu współrzędnych jako większy wybieramy ten o większym adresie. Czy nie ma lepszego rozwiązania? Przecież tu z tego co widzę to nie ma żadnej losowości, bo adresy są nadawane od najmniejszego do największego.

1

Ech. Dasz gotowy działający kod, to weźmie UB z komentarza...

Porównywanie wskaźników jest wyłącznie zdefiniowane dla:

Comparing pointers to objects is defined as follows:

  1. If two pointers point to different elements of the same array, or to subobjects thereof, the pointer to the element with the higher subscript compares greater.
  2. If one pointer points to an element of an array, or to a subobject thereof, and another pointer points one past the last element of the array, the latter pointer compares greater.
  3. If two pointers point to different non-static data members of the same object, or to subobjects of such members, recursively, the pointer to the later declared member compares greater provided the two members have the same access control (Clause 11) and provided their class is not a union.

Żadne tutaj nie pasuje. Dlatego w przykładzie dostałeś std::greater.

0

A da się tu wymyślić coś, żeby była tu jednak porządna losowość? Najlepiej żeby w przypadku elementów równych wybierało jeden z nich jako większy z rozkładem jednostajnym.

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