การจัดเรียงช่วง a vector
หรืออื่น ๆ ที่ใช้งานได้ (ตัวทำอินพุตอินพุตที่ไม่แน่นอน) ของชนิดของวัตถุที่กำหนดเองX
สามารถทำได้โดยใช้วิธีการต่าง ๆ โดยเฉพาะอย่างยิ่งรวมถึงการใช้อัลกอริทึมไลบรารีมาตรฐานเช่น
เนื่องจากเทคนิคส่วนใหญ่เพื่อให้ได้การเรียงลำดับของX
องค์ประกอบที่สัมพันธ์กันได้ถูกโพสต์แล้วฉันจะเริ่มต้นด้วยหมายเหตุบางประการเกี่ยวกับ "ทำไม" และ "เมื่อ" เพื่อใช้วิธีการต่างๆ
วิธี "ดีที่สุด" จะขึ้นอยู่กับปัจจัยต่าง ๆ :
- การเรียงลำดับช่วงของ
X
วัตถุเป็นงานทั่วไปหรืองานที่หายาก (ช่วงดังกล่าวจะถูกจัดเรียงสถานที่ต่าง ๆ ในโปรแกรมหรือโดยผู้ใช้ห้องสมุด) หรือไม่?
- การเรียงลำดับที่ต้องการเป็น "ธรรมชาติ" (คาดว่า) หรือมีหลายวิธีที่ชนิดสามารถเปรียบเทียบกับตัวเองได้หรือไม่
- ประสิทธิภาพเป็นปัญหาหรือควรจัดเรียงช่วงของ
X
วัตถุที่จะเข้าใจผิดได้หรือไม่
ถ้าช่วงการเรียงลำดับของX
เป็นงานทั่วไปและคาดว่าจะประสบความสำเร็จในการเรียงลำดับ (เช่นX
เพียงแค่ตัดค่าพื้นฐานเพียงค่าเดียว) จากนั้นอาจจะทำงานหนักเกินไปoperator<
เนื่องจากจะช่วยให้การเรียงลำดับโดยไม่มีฝอย (เช่นผ่านการเปรียบเทียบที่เหมาะสมอย่างถูกต้อง) ผล.
หากการเรียงลำดับเป็นงานทั่วไปหรือมีแนวโน้มที่จะต้องใช้ในบริบทที่แตกต่างกัน แต่มีหลายเกณฑ์ที่สามารถใช้ในการจัดเรียงX
วัตถุฉันจะไป Functors ( operator()
ฟังก์ชันที่มากเกินไปของคลาสที่กำหนดเอง) หรือตัวชี้ฟังก์ชั่น สำหรับการจัดเรียงคำและอีกอันสำหรับการเรียงตามธรรมชาติ)
หากช่วงการเรียงลำดับของประเภทX
เป็นเรื่องแปลกหรือไม่น่าเป็นไปได้ในบริบทอื่น ๆ ฉันมักจะใช้ lambdas แทนที่จะยุ่งเหยิงในเนมสเปซที่มีฟังก์ชันหรือชนิดมากกว่า
โดยเฉพาะอย่างยิ่งหากการเรียงลำดับนั้นไม่ "ชัดเจน" หรือ "เป็นธรรมชาติ" ในบางวิธี คุณสามารถรับตรรกะที่อยู่เบื้องหลังการสั่งซื้อได้อย่างง่ายดายเมื่อดูแลมบ์ดาที่นำมาใช้ในสถานที่ในขณะที่operator<
เป็นสิ่งที่คลุมเครือตั้งแต่แรกเห็นและคุณจะต้องค้นหาคำจำกัดความเพื่อทราบว่า
อย่างไรก็ตามโปรดทราบว่าoperator<
คำจำกัดความเดียวเป็นจุดหนึ่งของความล้มเหลวในขณะที่หลาย lambas เป็นหลายจุดของความล้มเหลวและต้องใช้ความระมัดระวังมากขึ้น
หากคำจำกัดความของoperator<
ไม่สามารถใช้งานได้เมื่อการเรียงลำดับเสร็จสิ้น / แม่แบบการเรียงลำดับถูกรวบรวมคอมไพเลอร์อาจถูกบังคับให้ทำการเรียกใช้ฟังก์ชันเมื่อเปรียบเทียบวัตถุแทนการฝังตรรกะการสั่งซื้อซึ่งอาจเป็นข้อเสียเปรียบอย่างรุนแรง ไม่ใช้การเพิ่มประสิทธิภาพเวลาลิงค์ / การสร้างรหัส)
วิธีในการบรรลุการเปรียบเทียบclass X
เพื่อใช้อัลกอริทึมการเรียงลำดับไลบรารีมาตรฐาน
อนุญาตstd::vector<X> vec_X;
และstd::vector<Y> vec_Y;
1. โอเวอร์โหลดT::operator<(T)
หรือoperator<(T, T)
ใช้เทมเพลตไลบรารีมาตรฐานที่ไม่คาดว่าจะมีฟังก์ชั่นการเปรียบเทียบ
เกินสมาชิกoperator<
:
struct X {
int i{};
bool operator<(X const &r) const { return i < r.i; }
};
// ...
std::sort(vec_X.begin(), vec_X.end());
หรือฟรีoperator<
:
struct Y {
int j{};
};
bool operator<(Y const &l, Y const &r) { return l.j < r.j; }
// ...
std::sort(vec_Y.begin(), vec_Y.end());
2. ใช้ตัวชี้ฟังก์ชันพร้อมฟังก์ชันเปรียบเทียบแบบกำหนดเองเพื่อจัดเรียงพารามิเตอร์ฟังก์ชัน
struct X {
int i{};
};
bool X_less(X const &l, X const &r) { return l.i < r.i; }
// ...
std::sort(vec_X.begin(), vec_X.end(), &X_less);
3. สร้างbool operator()(T, T)
โอเวอร์โหลดสำหรับประเภทที่กำหนดเองซึ่งสามารถส่งเป็น functor การเปรียบเทียบ
struct X {
int i{};
int j{};
};
struct less_X_i
{
bool operator()(X const &l, X const &r) const { return l.i < r.i; }
};
struct less_X_j
{
bool operator()(X const &l, X const &r) const { return l.j < r.j; }
};
// sort by i
std::sort(vec_X.begin(), vec_X.end(), less_X_i{});
// or sort by j
std::sort(vec_X.begin(), vec_X.end(), less_X_j{});
นิยามฟังก์ชันวัตถุเหล่านั้นสามารถเขียนทั่วไปได้มากกว่าโดยใช้ C ++ 11 และเท็มเพลต:
struct less_i
{
template<class T, class U>
bool operator()(T&& l, U&& r) const { return std::forward<T>(l).i < std::forward<U>(r).i; }
};
ซึ่งสามารถนำมาใช้ในการจัดเรียงชนิดที่มีสมาชิกสนับสนุนi
<
4. ผ่านการปิดแบบไม่ระบุชื่อ (แลมบ์ดา) เป็นพารามิเตอร์การเปรียบเทียบไปยังฟังก์ชันการเรียงลำดับ
struct X {
int i{}, j{};
};
std::sort(vec_X.begin(), vec_X.end(), [](X const &l, X const &r) { return l.i < r.i; });
ที่ C ++ 14 เปิดใช้งานการแสดงออกแลมบ์ดาทั่วไปยิ่งขึ้น:
std::sort(a.begin(), a.end(), [](auto && l, auto && r) { return l.i < r.i; });
ซึ่งสามารถห่อในแมโคร
#define COMPARATOR(code) [](auto && l, auto && r) -> bool { return code ; }
ทำให้การสร้างตัวเปรียบเทียบแบบธรรมดาค่อนข้างราบรื่น:
// sort by i
std::sort(v.begin(), v.end(), COMPARATOR(l.i < r.i));
// sort by j
std::sort(v.begin(), v.end(), COMPARATOR(l.j < r.j));