🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

3646閲覧

vectorによるx-y座標のソート

k.s.t

総合スコア4

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/12/05 18:18

前提・実現したいこと

メンバ変数cx,cy,px,pyをもつ構造体C2Pをvectorコンテナc2pListに格納しています。構造体C2Pをメンバ変数pxとpyの大きさに応じてソートしたいと考えています。
表1のようにランダムに並んだC2Pを、表2のようにpyが昇順になるようにC2Pをソートしてからpyが同じ場合はpxが昇順になるようにC2Pをソートするといったイメージです。
下記のソースコードではC2Pの数が増えると動作が重くなってしまいます。for文を使わない単純な方法でソートしたいと考えています。アドバイスをお願いいたします。

<表1>
|cx|cy|px|py|
|:--|:--:|--:|
111|169|6|2
34|90|7|2
61|122|0|0
139|40|3|1
257|169|3|2
|8|113|0|0
252|47|2|2
55|8|5|2
148|190|1|0
113|194|0|1
190|60|7|2
1|97|1|1

<表2>
|cx|cy|px|py|
|:--|:--:|--:|
|8|113|0|0
61|122|0|0
148|190|1|0
113|194|0|1
1|97|1|1
139|40|3|1
252|47|2|2
257|169|3|2
55|8|5|2
111|169|6|2
34|90|7|2
190|60|7|2

発生している問題・エラーメッセージ

下記のソースコードでは無駄が多いのか座標数が多くなるとプログラムがうまく動作しません。そのため、もう少し単純な方法で実現したいと考えております。for文を使わずに実現することは可能でしょうか。

該当のソースコード

C++

1 2#include <vector> 3#include <algorithm> 4#include <random> 5using namespace std; 6 7struct C2P 8{ 9 int cx; 10 int cy; 11 int px; 12 int py; 13 14 C2P(int camera_x, int camera_y, int proj_x, int proj_y) 15 { 16 cx = camera_x; 17 cy = camera_y; 18 px = proj_x; 19 py = proj_y; 20 } 21}; 22//---最後尾から探索するfind_if------- 23template<class Iterator,class Predicate> 24Iterator find_last_if(Iterator begin, Iterator end, Predicate pred) 25{ 26 const auto rbegin = make_reverse_iterator(end); 27 const auto rend = make_reverse_iterator(begin); 28 auto found = find_if(rbegin, rend, pred); 29 30 return (found != rend) ? (++found).base() : end; 31} 32 33int main() 34{ 35 //データの用意 36 vector<C2P> c2pList; 37 38 39 for (int i = 0;i < 2000;i++) 40 { 41 for (int j = 0;j < 1000;j++) 42 { 43 c2pList.push_back(C2P(j, i, rand() % 100, rand() % 100) 44 } 45 } 46 47 //C2Pの最大値と最小値を調べる 48 auto max_px = max_element(c2pList.begin(), c2pList.end(), [](C2P& a, C2P& b) {return a.px < b.px;}); 49 auto min_px = min_element(c2pList.begin(), c2pList.end(), [](C2P& a, C2P& b) {return a.px < b.px;}); 50 auto max_py = max_element(c2pList.begin(), c2pList.end(), [](C2P& a, C2P& b) {return a.py < b.py;}); 51 auto min_py = min_element(c2pList.begin(), c2pList.end(), [](C2P& a, C2P& b) {return a.py < b.py;}); 52 53 int max_px_num = max_px->px; 54 int min_px_num = min_px->px; 55 int max_py_num = max_py->py; 56 int min_py_num = min_py->py; 57 58 //今回の質問の本題(ソートを行う) 59 sort(c2pList.begin(), c2pList.end(), [](C2P& a, C2P& b) { return a.py < b.py; });//pyを使いC2Pをソート 60 for (int i = min_py_num;i <= max_py_num;i++)//pxをソート 61 { 62 auto first_itr = find_if(c2pList.begin(), c2pList.end(), [&i](C2P& a) {return a.py == i;});//先頭のイテレータを取得 63 auto last_itr = find_last_if(c2pList.begin(), c2pList.end(), [&i](C2P& a) { return a.py == i; });//最後尾のイテレーターを取得 64 65 if (first_itr != c2pList.end() && last_itr != c2pList.end()&&first_itr!=last_itr) 66 { 67 sort(first_itr, last_itr + 1, [](C2P& a, C2P& b) { return a.px < b.px; }); 68 } 69 70 } 71 72 return 0; 73 74 75 76}

試したこと

補足情報(FW/ツールのバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

C++

1#include <vector> 2#include <algorithm> 3#include <random> 4#include <utility> 5#include <iostream> 6#include <iomanip> 7 8struct C2P { 9 int cx; 10 int cy; 11 int px; 12 int py; 13 14 C2P(int camera_x, int camera_y, int proj_x, int proj_y) { 15 cx = camera_x; 16 cy = camera_y; 17 px = proj_x; 18 py = proj_y; 19 } 20}; 21 22int main() { 23 //データの用意 24 std::vector<C2P> c2pList; 25 26 std::mt19937 gen{std::random_device{}()}; 27 std::uniform_int_distribution<int> dist(0,99); 28 29 for ( int i = 0;i < 2000; i++) { 30 for ( int j = 0;j < 1000; j++) { 31 c2pList.push_back(C2P(j, i, dist(gen), dist(gen))); 32 } 33 } 34 35 //今回の質問の本題(ソートを行う) 36 std::sort(c2pList.begin(), c2pList.end(), 37 [](C2P& a, C2P& b) { 38 return std::make_pair(a.py, a.px) < std::make_pair(b.py, b.px); 39 }); 40 41 for ( const auto& item : c2pList ) { 42 std::cout << std::setw(5) << item.cx 43 << std::setw(5) << item.cy 44 << std::setw(5) << item.px 45 << std::setw(5) << item.py 46 << std::endl; 47 } 48 49}

投稿2020/12/05 22:32

episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k.s.t

2020/12/06 09:43

回答いただきありがとうございました。 無事解決しました。
episteme

2020/12/06 10:04

僕のがbest-answer? なんで?
k.s.t

2020/12/06 10:54

初心者なものでつける回答を間違てしまいました。 申し訳ありません。 epistemeさんの回答も大変参考になりました。 回答いただきありがとうございました。
guest

0

ベストアンサー

for文を使わない単純な方法でソートしたいと考えています。アドバイスをお願いいたします。

下記ソースコードのmain関数内で使用しているstd::sortの
第三引数のラムダ式内のようにpyの比較なのかpxの比較なのか
if文や三項演算子で分岐してやればコードを簡略化できます。

C2Pの数が増えると動作が重くなってしまいます

vectorのreserveメソッドを使わずpush_backで
何度もメモリの確保を行うと遅くなってしまうので
サイズがあらかじめ決まっているのなら
最初にreserveでメモリを全て確保してから
push_backで要素を追加していく方が好ましいかと思われます。

c++

1#include <vector> 2#include <algorithm> 3#include <iostream> 4#include <cstddef> 5 6// 7// C2P構造体 8// 9struct C2P 10{ 11 int cx; 12 int cy; 13 int px; 14 int py; 15 16 C2P(int camera_x, int camera_y, int proj_x, int proj_y) 17 { 18 cx = camera_x; 19 cy = camera_y; 20 px = proj_x; 21 py = proj_y; 22 } 23 24}; 25 26// 27// C2Pオブジェクトの標準出力用演算子のオーバーライド 28// 29std::ostream& operator<<(std::ostream& os, const C2P& c2p) 30{ 31 os << "---------------------------------" << std::endl; 32 os << "cy:" << c2p.cy << std::endl; 33 os << "cx:" << c2p.cx << std::endl; 34 os << "py:" << c2p.py << std::endl; 35 os << "px:" << c2p.px; 36 return os; 37} 38 39// 40// C2Pの初期値生成関数 41// 42std::vector<C2P> c2pList_factry(const std::size_t size_x, const std::size_t size_y) 43{ 44 auto result = std::vector<C2P>(); 45 result.reserve(size_x * size_y); 46 47 for(std::size_t x = 0; x < size_x; x++) for(std::size_t y = 0; y < size_y; y++) 48 result.push_back(C2P(x, y, rand() % 100, rand() % 100)); 49 50 return result; 51} 52 53// 54// main関数 55// 56int main() 57{ 58 auto c2p_list = c2pList_factry(100, 200); 59 60 std::sort(c2p_list.begin(), c2p_list.end(), [](const C2P& c2p_1, const C2P& c2p_2) 61 { 62 return c2p_1.py != c2p_2.py ? c2p_1.py < c2p_2.py : c2p_1.px < c2p_2.px; 63 }); 64 65 for(auto&& i:c2p_list) std::cout << i << std::endl; 66 67 return 0; 68}

wandboxで実行

投稿2020/12/05 20:02

編集2020/12/05 23:34
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

actorbug

2020/12/05 21:34

元のソースからC2Pの定義を変えてしまっているのは良いのでしょうか。 定義を変えなくても、reserveでメモリを事前確保するだけで十分だと思いますが。
退会済みユーザー

退会済みユーザー

2020/12/05 21:57 編集

> 元のソースからC2Pの定義を変えてしまっているのは良いのでしょうか。 私の記載したサンプルコードに必要ない引数付きコンストラクタだったので省略しましたが C2Pの定義を変えたくないのなら下記のように記載すれば良いかと思われます。 struct C2P { int cx; int cy; int px; int py; C2P() = default; C2P(int camera_x, int camera_y, int proj_x, int proj_y) { cx = camera_x; cy = camera_y; px = proj_x; py = proj_y; } }; > reserveでメモリを事前確保するだけで十分だと思いますが。 std::vectorのreserveを使うのも引数付きコンストラクタで事前にメモリを確保 することもやっている事は同じかと。
actorbug

2020/12/05 22:08

> 私の記載したサンプルコードに必要ない引数付きコンストラクタだったので省略しましたが > C2Pの定義を変えたくないのなら下記のように記載すれば良いかと思われます。 それって結局C2Pを改変しているのは変わらないのではないでしょうか。 元のソースだと引数ありのコンストラクタのみ定義しているので、 デフォルトコンストラクタが存在しません。 回答のソースだと、コンストラクタ定義がないのでデフォルトコンストラクタが存在します。 コメントのソースだと、C2P() = default;としているのでデフォルトコンストラクタが存在します。 デフォルトコンストラクタが存在するかどうかが、元ソースとの差になります。 > std::vectorのreserveを使うのも引数付きコンストラクタで事前にメモリを確保 > することもやっている事は同じかと。 元のソースだとC2Pのデフォルトコンストラクタがないので、 vectorの初期サイズを指定するとエラーになるはずです。 その場合でもreserveなら使用可能なので、C2Pを改変しないのなら、こちらしか選択肢はありません。 reserveとresizeを勘違いしてはいませんか。
退会済みユーザー

退会済みユーザー

2020/12/05 22:51 編集

確かにreserve+push_backを使えばデフォルトコンストラクタを呼ばなくて良いので消せますね。 回答があまり適切ではなかったので修正しておきました。 教えてくださりありがとうございます。
k.s.t

2020/12/06 09:44

回答いただきありがとうございました。 無事に解決することができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問