私は以下のような2D配列を持っています。 (array[5][2]
)
20 11
10 20
39 14
29 15
22 23
ソート後は以下のようになります。
10 20
20 11
22 23
29 15
39 14
つまり、配列は最初の列の値のみを比較して並べ替える必要があります。
Javaには、それを行うための組み込み関数機能があります。以下のように。
Arrays.sort(a, new Comparator<Long[]>() {
@Override
public int compare(Long[] o1, Long[] o2) {
Long t1 = o1[1];
Long p1 = o1[0];
Long t2 = o2[1];
Long p2 = o2[0];
if (t1 == t2) {
return (p1 > p2 ? 1 : (p1 == p2 ? 0 : -1));
} else {
return (t1 < t2 ? -1 : 1);
}
}
});
それで、これらの種類のことを行うためのC++組み込み関数機能はありますか、またはC++(最速の実装)でこれを行うにはどうすればよいですか?
前もって感謝します :)
数少ないものの1つだったという理由だけでこれを提供していますstd::qsort
はwellそのstd::sort
単純に、つまり複数列の固定配列をソートしません。コンパレータは3値ステートメントの文字列ですが、十分に長く見つめれば十分に明確である必要があります。
#include <iostream>
#include <random>
#include <algorithm>
int main()
{
int ar[10][2];
// populate with random data
std::random_device rd;
std::default_random_engine rng(rd());
std::uniform_int_distribution<> dist(1,20);
std::for_each(std::begin(ar), std::end(ar),
[&](int (&ar)[2]){ ar[0] = dist(rng); ar[1] = dist(rng); });
std::cout << "Before Sort..." << '\n';
std::for_each(std::begin(ar), std::end(ar),
[](const int(&ar)[2]) { std::cout << ar[0] << ',' << ar[1] << '\n';});
std::qsort(ar, 10, sizeof(*ar),
[](const void *arg1, const void *arg2)->int
{
int const *lhs = static_cast<int const*>(arg1);
int const *rhs = static_cast<int const*>(arg2);
return (lhs[0] < rhs[0]) ? -1
: ((rhs[0] < lhs[0]) ? 1
: (lhs[1] < rhs[1] ? -1
: ((rhs[1] < lhs[1] ? 1 : 0))));
});
std::cout << "After Sort..." << '\n';
std::for_each(std::begin(ar), std::end(ar),
[](const int(&ar)[2]) { std::cout << ar[0] << ',' << ar[1] << '\n';});
return 0;
}
サンプル実行(あなたは明らかに異なります)
Before Sort...
2,11
18,4
20,20
14,6
8,10
17,8
14,14
3,10
20,14
19,19
After Sort...
2,11
3,10
8,10
14,6
14,14
17,8
18,4
19,19
20,14
20,20
注:これは、潜在的なアンダーフローの問題を回避するために、コンパレータで減算ショートカットではなく厳密な値の比較を具体的に使用します。制限されたデータスペースでそれが問題にならない場合は、そのコンパレータを非常に簡単にすることができます。
CおよびC++の組み込み配列は非常に柔軟性がなく、特に割り当てることができません。
最良のオプションは、少なくとも内部次元では、C++標準ライブラリの「配列」クラスです。
_array<int, 2> a[5] = { { 20, 11 },
{ 10, 20 },
{ 39, 14 },
{ 29, 15 },
{ 22, 23 } };
sort( a, a + 5 );
_
ここでは、std :: arrayのプロパティを使用します。このプロパティは、デフォルトで「<」が辞書式に比較します。つまり、最初の要素から始まります。物事を異なる方法でソートするには、コンパレータオブジェクトを考え出す必要があるため、2番目の列をソートキーとして使用する場合は、次のようにする必要があります。
_auto comp = []( const array<int, 2>& u, const array<int, 2>& v )
{ return u[1] < v[1]; };
sort( a, a + 5, comp );
_
そして最初のコメントで述べたように、_sort(a, a+5 ...
_はクリーナーsort(std::begin(a), std::end(a) ...
の醜い短い形式です
可能であれば、Vector
をいくつかの構造体とともに使用して2つのint
を保持します。
typedef std::pair<int, int> pairType;
std::vector<pairType> vec;
// Initialize vector
std::sort(std::begin(vec), std::end(vec), [](pairType& first, pairType& second)->bool { return first.first < second.first });
正直なところ、2番目の次元にはints
が2つしかないため、代わりに、独自の比較関数が組み込まれたペアの配列を使用します。 _pair<int,int> arr[200]
_のようなものを使用すると、組み込みの並べ替え関数sort(arr, arr + 200)
を呼び出すことができます。これにより、配列が最初の要素で並べ替えられ、次に2番目の要素で並べ替えられます。
_#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
// pair of integers
pair<int, int> arr[1000];
// fill array with random numbers
random_device rd;
mt19937 rng(rd());
uniform_int_distribution<int> uni(0,1000);
for(int i = 0; i < 10; i++) {
// make_pair(x, y) creates a pair with two integers x and y
arr[i] = make_pair(uni(rng), uni(rng));
}
// prints out initial array
cout << "BEFORE ARRAY..." << endl;
for(int i = 0; i < 10; i++) {
// .first and .second call the first and second ints in the pair respectively
cout << arr[i].first << " " << arr[i].second << endl;
}
cout << endl;
// sort the array by calling built in sort function
sort(arr, arr + 10);
// prints out array
cout << "FINAL ARRAY..." << endl;
for(int i = 0; i < 10; i++) {
cout << arr[i].first << " " << arr[i].second << endl;
}
cout<<endl;
}
_
このプログラムを実行すると、配列がソートされていることがわかります。
_BEFORE ARRAY...
726 562
916 348
594 6
515 872
976 960
662 169
529 317
789 702
74 255
330 574
FINAL ARRAY...
74 255
330 574
515 872
529 317
594 6
662 169
726 562
789 702
916 348
976 960
_
2番目の要素もどのようにソートされているかに注意してください。ただし、
まず、_vector<vector<int>> array
_を指定した場合、これはsort(begin(array), end(array))
を使用するだけで並べ替えることができます。これは、vector
が辞書式比較関数を定義しているためです: http://en.cppreference .com/w/cpp/container/vector/operator_cmp
とはいえ、vector
- of -vector
sを使用することには欠点があります: vector-of-vectorsの問題は何ですか? そしてそれは明らかに何ではありませんあなたが意図した。 _int array[5][2]
_を使用しようとすると sort
は次のようになります。
エラーC3863:配列タイプ 'int [2]'は割り当てできません
swap
を使用して2 _int[2]
_ sを交換する代わりに、sizeof(*array)
のバイトを交換する必要があります。これは、 qsort
WhozCraigの回答 で示唆されているように、しかし、コンパレータを任意のサイズのサブ配列を処理できるようにすることで改善できます。 _int array[5][2]
_または必要な寸法が与えられた場合、次のように記述できます。
_static const auto SIZE = size(*array);
qsort(array, size(array), sizeof(*array), [](const auto lhs, const auto rhs) {
const auto first = reinterpret_cast<const int*>(lhs);
const auto last = next(first, SIZE);
const auto its = mismatch(first, last, reinterpret_cast<const int*>(rhs));
if (its.first == last) {
return 0;
} else if (*its.first < *its.second) {
return -1;
} else {
return 1;
}});
_
クイックノートarray
は、標準タイプを定義するため、変数名として使用しないでください。この変更により、ここに例があります: http://ideone.com/87AoIr
エンドコンテナが問題にならない場合は、マップを使用してみませんか?
#include<map>
std::map<int, int> m;
for(std::size_t i = 0; i < 5; ++i )
m[array[i][0]] = array[i][1] ;
これで、m
をarray
にコピーして戻すことができます
std::size_t i=0;
for(const auto& x:m)
{
array[i][0] = x.first ;
array[i++][1] = x.second ;
}
2D配列を時間内に並べ替える最速の方法(列のみを使用)。 。 。参照の局所性にコストがかかります...それ以外の場合、他のすべての方法では行のコピーが大量に発生します。 。ただし(C++の移動操作はこれを緩和する可能性があります)
2D配列へのポインタの新しい配列を作成します...次に、ポインタを並べ替えます...
そうでなければ、私の前の他のすべての答えは良いようです。ただし、std :: arrayを使用することをお勧めします。