まず、同様の質問を検索しようとしましたが、私の問題が何であるかを説明する回答が見つかりませんでした.
問題は次のとおりです。座標 (x、y、z) を持つ N 個のノードのセットが与えられた場合、それらを 4 番目の値 F を使用してできるだけ速く並べ替えます。
std::set
O(log(N)) の複雑さがあるため、この目的のためにカスタム コンパレータを使用したいと考えています。a とonstd::vector
の呼び出しを試すこともできますが、理論的には操作が遅くなります。std::sort
std::vector
なぜこれ?私は常にセットに要素を挿入し、F値を変更しているため(値を変更し、コンテナ内の要素を並べ替えて消去して再挿入することを意味します)、F値が小さい要素を取得したい(コンテナの前にある要素です)。
std::set
しかし、問題に行きましょう。
座標は一意性プロパティを定義し、厳密な弱い順序付けルールに従います。つまり、a
とb
は同じオブジェクトと見なされます。
!comp(a,b) && !comp(b,a)
この問題は、座標に基づく一意性基準と F 値に基づく並べ替え基準の定義に関連しています。セットに同じ座標を持つ 2 つの要素を格納したくないが、座標は異なるが同じ F 値を持つ 2 つの要素を格納できるようにしたい
コンパレータは、次の 3 つのプロパティも満たす必要があります。
- 無反射
x < x false
- 非対称
x < y true
性が意味することy < x false
- 推移
x < y && y < z
性が意味することx < z true
したがって、これらすべてのプロパティを知っているので、次の実装例を使用して取り組んできました。
いくつかの定義
class Node;
struct NodeComparator;
using NodePair = std::pair<Node *, int>;
using NodeSet = std::set<NodePair, NodeComparator>;
ここでは便宜上ポインタを使用しています
クラス ノード
class Node
{
public:
Node()
{
}
Node(int _x, int _y, int _z, int _val) : x(_x), y(_y), z(_z), value(_val)
{
}
int x, y, z;
int value;
friend inline std::ostream &operator<<(std::ostream &os, const Node &dt)
{
os << "[" << dt.x << ", " << dt.y << ", " << dt.z << "], [" << dt.value << "]";
return os;
}
friend bool operator==(const Node &_lhs, const Node &_rhs){
if( _lhs.x == _rhs.x &&
_lhs.y == _rhs.y &&
_lhs.z == _rhs.z ){
return true;
}
return false;
}
};
ここで、オペレーター<<
はデバッグ目的でのみオーバーロードされます
コンパレータ
struct NodeComparator
{
bool operator()(const NodePair &_lhs, const NodePair &_rhs) const
{
if( _lhs.first == nullptr || _rhs.first == nullptr )
return false;
/*
This first check implements uniqueness.
If _lhs == _rhs --> comp(_lhs,_rhs) == false && comp(_rhs, _lhs) == false
So ( !comp(l,r) && !comp(r,l) ) == true
*/
if( *_lhs.first == *_rhs.first)
return false;
int ret = _lhs.second - _rhs.second;
return ret < 0;
}
};
1つの問題は、座標は異なるがF値が同じ2つのノードの場合である可能性があると思います
具体的なケースを含む完全な例
この例では、上記のクラスを使用していくつかの要素を挿入/検索/消去していますが、出力に表示されているため、期待どおりに動作していません:
#include <iostream>
#include <set>
#include <vector>
#include <algorithm>
#include <tuple>
class Node;
struct NodeComparator;
using NodePair = std::pair<Node *, int>;
using NodeSet = std::set<NodePair, NodeComparator>;
class Node
{
public:
Node()
{
}
Node(int _x, int _y, int _z, int _val) : x(_x), y(_y), z(_z), value(_val)
{
}
int x, y, z;
int value;
friend inline std::ostream &operator<<(std::ostream &os, const Node &dt)
{
os << "[" << dt.x << ", " << dt.y << ", " << dt.z << "], [" << dt.value << "]";
return os;
}
};
struct NodeComparator
{
bool operator()(const NodePair &_lhs, const NodePair &_rhs) const
{
/*
This first check implements uniqueness.
If _lhs == _rhs --> comp(_lhs,_rhs) == false && comp(_rhs, _lhs) == false
So ( !comp(l,r) && !comp(r,l) ) == true
*/
if(_lhs == _rhs)
return false;
int ret = _lhs.second - _rhs.second;
return ret < 0;
}
};
int main(int argc, char **argv)
{
Node n1(0, 2, 4, 12),
n2(2, 4, 5, 25),
n3(0, 1, 4, 34),
n4(0, 1, 4, 20),
n5(0, 1, 5, 20),
n6(0, 2, 4, 112);
NodeSet set;
set.insert({&n1, n1.value});
set.insert({&n2, n2.value});
set.insert({&n3, n3.value});
set.insert({&n4, n4.value}); //Should not be inserted because it already exists n3 with same coords
set.insert({&n5, n5.value});
//Try to insert multiple times a previously inserted node (n1 coords is == n6 coords)
//It should not be inserted because it already exists one node with the same coords (n1)
set.insert({&n6, n6.value});
set.insert({&n6, n6.value});
set.insert({&n6, n6.value});
set.insert({&n6, n6.value});
set.insert({&n6, 0});
set.insert({&n6, 1});
if (set.find({&n4, n4.value}) != set.end())
std::cout << "Found n4" << std::endl;
auto it = set.erase({&n4, 20});
std::cout << "It value (elements erased): " << it << std::endl;
if (set.find({&n4, n4.value}) != set.end())
std::cout << "Found n4 after removal" << std::endl;
std::cout << "Final Set content: " << std::endl;
for (auto &it : set)
std::cout << *it.first << std::endl;
return 0;
}
C++11 以降でコンパイルするには:g++ -o main main.cpp
出力:
Found n4
It value (elements erased): 1
Final Set content:
[0, 2, 4], [12]
[2, 4, 5], [25]
[0, 1, 4], [34]
[0, 2, 4], [112]
**期待される出力: ** F が小さいもの (n1) から F が大きいもの (n3) に並べられた要素 n1、n5、n2、n3 に対応します。
Final Set content:
[0, 2, 4], [12]
[0, 1, 5], [20]
[2, 4, 5], [25]
[0, 1, 4], [34]
実装の助けやアイデア、代替案をいただければ幸いです。ありがとう