• 0
مصطفى 36a2

أهمية العملية >operator وأمثلة على استخدامها

سؤال

السلام عليكم ورحمة الله وبركاته

يتكرر استخدام العملية >operator كونها العمود الفقري في أي مقارنة ضمن حاويات STL أو توابع المقارنة ;

فعلى سبيل المثال لا الحصر : أي بنى شجرية تستخدم balanced tree مثل std::map أو std::set تستخدم العملية >operator لمقارنة العناصر أثناء الترتيب أو أثناء البحث والوصول لعناصر الشجرة , وكمثال آخر فإن توابع max_element أو min_element تستخدم هذه العملية لمقارنة العناصر والعثور على العنصر الأكبر/أو الأصغر كما تعرّفه هذه العملية , فالعنصر الأكبر هو العنصر الذي تمت مقارنته مع باقي العناصر جميعاً ولم يوجد أي عنصر أكبر منه ,وهكذا ..

وكمثال أخير فإن المقارنة أثناء الترتيب تستخدم أيضاً العملية >operator لتحديد أي العناصر يجب أن يكون أولاً , وأيها يجب أن يكون في نهاية الحاوية أو القائمة انظر للتابع sort.

 

تظهر أهمية هذه العملية عند إعادة تعريفها , والقالب العام لذلك هو الشكل التالي :

bool operator<(const type&first,const type&second){    //some comparison operators return 'true' if first<second}

حيث type هو نوع العناصر في القائمة.

 

أينما وجدت عملية المقارنة >  فهي تعيد true إذا كان العنصر الأيسر أصغر تماماً من الأيمن , ولها قواعد صارمة لا يمكن تجاوزها وهي :

إذا كان a<b تعطي true فيجب أن يكون b<a يعطي  false

إذا كان a<b و b<a يعطيان false فيجب أن يكون a==b تماماً

 

مثلاً لو كان التابع كما يلي :

bool operator<(const type&first,const type&second){    return true;}

فلن يعمل أي شيء يستخدمه بشكل صحيح , وسيسبب مشاكل لا تحصى ,

يجب أن يكون دائماً :

(a<b) + (b<a) + (a==b) == 1

لنبدأ بإعادة تعريف بعض المعاملات :

نريد أن نعرف المقارنة للبنية التالية :

struct student{    string name;    int rank;};

النوع student له اسم وتقييم (في اختبار ما )

ونريد أن يكون الطالب الذي تقييمه أعلى ((أكبر)) من الطالب ذو التقييم الأخفض , وإن كان لطالبين نفس التقييم فيجب أن يكون الطالب الذي اسمه يأتي في المعجم قبلاً , هو الطالب الـ((أصغر))

(لاحظ كيف نقول أكبر وأصغر )

حل هذا المثال هو كما يلي :

bool operator<(const student&first,const student&second){    if(first.rank<second.rank)        return true;    else if(first.rank==second.rank){        if(first.name<second.name)            return true;        else            return false;    }    else        return false;}

مثال 2 : لو كان لدينا البية التالية :

struct Elephant{    int size;};

ويكون القيل أكبر من فيل آخر إذا كان حجمه أكبر !! ببساطة :

bool operator<(const Elephant&first,const Elephant&second){    return first.size<second.size;}

ماذا لو أردنا ان يكون الفيل أكبر من فيل آخر إذا كان حجمه أصغر ؟

bool operator<(const Elephant&first,const Elephant&second){    return first.size>second.size;}

يمكنك تجربة كتابة الكود التالي داخل الـmain :

Elephant x={4};    Elephant y={5};    cout << x.size<<"<"<<y.size<<endl;    cout << "x"   <<"<"<<"y="<<(x<y);

ما رأيك لو نقارن حجم فيلين ونقول أن الفيل الأكبر بين فيلين زوجيين هو الفيل ذو الحجم الأكبر ولو كانا فرديين فهو الأصغر ولو كان أحدهما فقط زوجي فهو أكبر من الآخر :p

bool operator<(const student&first,const student&second){    if(first.rank<second.rank)        return true;    else if(first.rank==second.rank){        if(first.name<second.name)            return true;        else            return false;    }    else        return false;}

جرب الكود التالي ولاحظ كيف أصبحت المقارنة مختلفة عن المقارنة البسيطة المعتادة :

Elephant a={4},b={5},c={6},d={7};    cout<<(a<b)<<(b<c)<<(a<c)<<(b<d)<<endl;

 

غالباً ما توجد نسختان من توابع STL التي تستخدم العملية > , النسخة الأولى تكون افتراضية تستخدم هذه العملية , والنسخة الثانية تستخدم تابعاً يتم تمريره كوسيط , له نفس قواعد العملية >
يكون شكل التابع تماماً كشكل إعادة تعريف العملية > , أي كما يلي :

bool compare(const type&first,const type&second){    //some comparison operators return 'true' if first<second}

والمحتوى هو ذاته .

 

أرجو أن يكون المقال مفيداً في اعتياد استخدام العملية > بعد إعادة تعريفها . يفترض بهذا المقال أن يكون مساعداً لمقالات أخرى تستخدم هذه العملية في محتواها .

 

والله ولي التوفيق

تم تعديل بواسطه مصطفى 36a2
2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

1 إجابات على هذا السؤال .

  • 0

المصائب التي تجلبها العملية > لا يمكن حصرها , فتعريفها بشكل خاطئ سيؤدي إلى تشويش جميع التوابع التي تعتمد عليها ..

إليكم هذا المثال (من تجربة قاسية) :

لدينا فيل :)

الفيل له  معدل ذكاء IQ و له وزن W

نريد ترتيب قائمة من الأفيال بحيث يكون الـ IQ متزايداً والـ W متناقصاً ..

 

بداية قمت بما يلي :

struct E{    int w,iq;    bool operator<(const E&x)const{        if(iq>x.iq and w<x.w)            return true;        return false;    }};

تعريف الـ struct , وتعريف العملية >بداخله .

 

اعلم أخي الكريم أن أي شرط مثل الذي قمتُ بوضعه (يحوي and ) سيعطي نتائج خاطئة دوماً في المقارنة ,

وذلك للسبب التالي :

القاعدتان الرئيسيتان لصحة المقارنة هما :

1- ما ليس أكبر ولا أصغر فهو يساوي

2- ما هو أصغر لا يمكن أن يكون أكبر

ولكن القاعدة الأولى يكسرها التعريف الذي وضعتُه وذلك لأن ما ليس أكبر بالـ iq و أصغر بالـوزن , كما أنه ليس أكبر بالوزن وأصغر بالـ iq (مثلاً كلا المتحولين أكبر أو كلاهما أصغر) --حسب القاعدة يجب أن يكون يساوي , إلا أنه يمكن ألا يكون كذلك !

 

هناك عدة تغييرات , قمت بعملها منها :

struct E{    int w,iq;    bool operator<(const E&x)const{        if(iq>x.iq and w<x.w)            return true;        else if(iq==x.iq and w<x.w)            return true;        else if(iq>x.iq and w==x.w)            return true;        return false;    }};

 

الخلاصة :

طالما قمت بوضع and داخل الشرط , فحلك خاطئ ..

 

السبب :

الترتيب عملية تتم بشكل متسلسل وليس متوازي . يمكن ترتيب قائمة ما حسب صفة معينة (ثم حسب صفة أخرى ) وليس الصفتين معاً في نفس الوقت .. أي أن القائمة يمكن أن تكون مرتبة تماماً بالنسبة للصفة الأولى , وعند تساوي الصفة الأولى يمكننا النظر للصفة الثانية

 

نتيجة :

يستحيل ترتيب قائمة بالنسبة لصفتين معاً في نفس الوقت , ولكن يمكن العثور على أطول متتالية جزئية من العناصر التي تحقق الترتيب المطلوب

 

الحل الصحيح أخيراً كان :

struct E{    int w,iq,id;    bool operator<(const E&x)const{        if(iq>x.iq)            return true;        else if(iq==x.iq and w<x.w)            return true;        return false;    }};

الترتيب حسب العملية >السابقة ثم تطبيق خوارزمية معينة لإيجاد أطول متتالية جزئية تحقق الترتيب المطلوب حسب IQ متناقص و W متزايد

 

والله ولي التوفيق

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



سجل دخولك الان

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .