• الإعلانات

    • فيصل الحربي

      تسجيل عضوية جديدة في المنتدى   01/31/2016

      السلام عليكم ورحمة الله وبركاته  عزيزي العضو الجديد :  حاليا رسالة الإيميل لتأكيد صحة إيميلكم تذهب للبريد العشوائي ( جاري حل المشكلة )  فإذا لم تجد رسالة التحقق من إيميلكم في صندوق الوارد لديكم إتجه للبريد العشوائي ( JUNK)  وقم بتفعيل إشتراككم من هناك   

البحث في المنتدى

Showing results for tags 'max_element'.

  • البحث بالتاقات

    اكتب الكلمات المفتاحيه بينها علامه الفاصله
  • البحث بكاتب الموضوع

تم إيجاد 1 نتيجة

  1. السلام عليكم ورحمة الله وبركاته كثيراً ما نحتاج البحث عن أكبر عنصر أو أصغر عنصر في قائمة/مصفوفة/سلسلة/أو أي شيء يمكننا التأشير إليه (أي كل ما يملك ForwardIterator ) فالبحث عن اكبر عنصر هو عملية أساسية في Selection sort كما في Pancacke sort عدا عن كونه عملية أساسية مستقلة للكثير من الحسابات الهامة كإيجاد أفضل الطلاب في قائمة أو العثور على أقصر الطرق ضمن قائمة طرق متاحة مثلاً .. ورغم أنها عملية سهلة التكويد (كتابة الكود) بشكل كبير , إلا ان وجود حلقة البحث داخل الكود غالباً يسبب المزيد من الصعوبة في فهم الكود , كما أنه لا داع لتوضيح أهمية استخدام الأدوات الجاهزة في تسريع عملية التطوير  . لنبدأ إذا في التعرف على استخدام التابع max_element من مكتبة algorithm : تم تعريف التابع كـfunction template بنسختين   أولاً - النسخة الافتراضية للتابع : template <class ForwardIterator> ForwardIterator max_element (ForwardIterator first, ForwardIterator last);يعيد التابع مؤشراً للعنصر الأكبر في القائمة التي أول مؤشر لها هو first و مؤشر العنصر بعد الأخير  هو last وأعني بالمؤشر هنا : Iterator إن كنا في container خاص في STL أو عنوان حقيقي إن كنا داخل مصفوفة . هذا التابع الافتراضي يستخدم العملية >operator لمقارنة العناصر , والعنصر الذي لم يعثر على أي عنصر آخر أكبر منه , هو العنصر الأكبر علينا إعادة تعريف العملية >operator إذا أردنا العثور على أكبر عنصر في مجموعة من نوع جديد ( راجع هذا الموضوع للتدرب على إعادة تعريف هذا المعامل )   لنبدأ بالبحث في المصفوفات : الوسيط الأول لهذا التابع هو مؤشر بداية المجال للمصفوفة , علينا إرسال عنوان العنصر المراد البدء بالبحث منه الوسيط الثاني هو مؤشر العنصر بعد الأخير   مثال : لدينا المصفوفة التالية : int A[10]={8,5,7,1,2,4,9,3,4,7};للبحث عن أكبر عنصر في المصفوفة نكتب : max_element(&A[0],&A[10]);الاستدعاء السابق يعيد (((عنوان))) أكبر عنصر ماذا لو أردنا البحث عن أكبر عنصر في المجال من 1 إلى 3 max_element(&A[1],&A[4]);(لا تنس أن الوسيط الثاني هو عنوان العنصر بعد الأخير) يمكننا التعامل مع العناوين مباشرة مثلاً , للعثور على أكبر عنصر في المجال 0 إلى 4 max_element(A,A+5);والشكل السابق أسهل للكتابة من max_element(&A[0],&A[5]);ومفضل عليه دوماً , لأن كتابة [10]A& تعني أننا نصل إلى عنوان عنصر خارج المصفوفة وهذا ليس آمناً . إذا سنعتمد عند استخدامنا للمؤشرات في المصفوفات على ( اسم المصفوفة + الانزياح عن المبدأ ) (ملاحظة : تم استخدام المقارنة المعتادة هنا بين الأعداد لمعرفة العنصر الأكبر )   لنتابع إلى البحث في الحاويات : لدينا الـvector التالي : vector<int> A={8,5,7,1,2,4,9,3,4,7};لإيجاد أكبر عنصر في مجاله كله max_element(A.begin(),A.end());أو يمكننا البدء من begin إلى begin+offset كما يلي : max_element(A.begin(),A.begin()+10);مثلاً إذا أردنا البحث عن أكبر عنصر في المجال من 3 إلى 7 : max_element(A.begin()+3,A.begin()+8);لنقم بإعادة تعريف العملية >operator بالنسبة للنوع الجديد koko المعرف كما يلي struct koko{        int a;        koko(int x):a(x){        }};وسنعيد تعريف المعامل >operator  كما يلي : bool operator<(const koko&first,const koko&second){    if(first.a<=second.a)        return false;    else        return true;}إذا كنت قوي الملاحظة فستعرف أن عملية > الآن تتصرف كما لو كانت عملية < , وهذا يعني أن max_element ستعيد الآن العنصر الأصغر : مثلاً الاستدعاء التالي : max_element(A.begin()+3,A.begin()+8)سيعيد iterator يشير إلى العناصر الأصغر وهو 1 . ماذا تتوقع أن يعيد الاستدعاء التالي : min_element(A.begin()+3,A.begin()+8)أظن أن الفكرة أصبحت واضحةً , فالـ max_element سيعيد العنصر الذي يرجع false عند مقارنته مع جميع العناصر الباقية (أي أنه ليس أصغر من أحد حسب تعريف العملية أصغر ) لنتجه الآن إلى الشكل الآخر للتابع , الشكل المفصل : ثانياً- النسخة المفصلة للتابع : إذا رأينا اننا بحاجة إلى أعادة تعريف العملية > لاستخدام هذا التابع , فربما يكون أكثر وضوحاً ان نستخدم الشكل المفصل للتابع : template <class ForwardIterator, class Compare> ForwardIterator max_element (ForwardIterator first, ForwardIterator last, Compare comp);الوسيط الآخير , هو تابع compare له نفس شكل العملية >operator ويعيد قيمة bool تكون true عندما يكون الوسيط الأول أصغر من الثاني , ولكن لننظر إلى الأمر بشكل مختلف , عندما نبحث عن max_element فالعنصر الذي نعرّفه كـ max هو العنصر الذي يعيد false عندما يتم استدعاء التابع compare ووضعه كوسيط أول مهما كان الوسيط الثاني , وكذلك العنصر الـ min هو العنصر الذي يعيد التابع compare قيمة true إذا كان هو الوسيط الأول مهما يكن الوسيط الثاني (طبعاً في كلا الحالتين نستثني أن يكون الوسيط الثاني هو نفس الوسيط الأول ) لنرجع إلى مثال koko بدلاً من إعادى تعريف العملية > كما يلي : bool operator<(const koko&first,const koko&second){    if(first.a<=second.a)        return false;    else        return true;}سنكتب التابع compare كما يلي : bool compare(const koko&first,const koko&second){    if(first.a<=second.a)        return false;    else        return true;}وسيصبح الاستدعاء كما يلي : max_element(A.begin()+3,A.begin()+8,compare)لاحظ أننا نمرر اسم التابع فقط . يمكننا الآن التخلي عن البنية التغليفية koko (حيث وضعناها فقط لأن إعادة تعريف العملية > بالنسبة لـ int أمر ممنوع) وذلك بفضل التابع compare انظر إلى الكود التالي : #include <iostream>#include <algorithm>#include <vector>using namespace std;bool compare(const int&first,const int&second){    if(first<=second)        return false;    else        return true;}int main(){    vector<int> A={8,5,7,1,2,4,9,3,4,7};    cout<<(*max_element(A.begin()+3,A.begin()+8,compare));    return 0;}مارأيك لو نبحث عن أكبر عدد زوجي ضمن القائمة ؟ كل ما علينا هو تعديل كود التابع compare bool compare(const int&first,const int&second){    if(second%2==0 and first<second)        {            return true;        }    else        return false;}العبارة الفاصلة والتي يجب أن تكون خلاصة هذا المقال هي : يعيد التابع max_element العنصر الذي لا يوجد عنصر أكبر منه , وهذا يعني أن أي مقارنة يكون هو الـ second كوسيط فيها يجب أن تعيد true وأي مقارنة يكون هو الـ first فيها يجب أن تعيد false وذلك واضح من كون عملية المقارنة هي first<second وطالما أنك تحقق هذه العلاقة يمكنك القيام بأي اختبار تريده . ما رأيك بأكبر عدد أولي في القائمة !! واثق من أن الكود التالي سينال إعجابك ! #include <iostream>#include <algorithm>#include <vector>#include <cstdlib>#include <ctime>using namespace std;bool is_prime(const int &x){    for(int i=2;i*i<=x;i++)        if(x%i==0)            return false;    return true;}bool compare(const int&first,const int&second){    if(first<second)        {            if(is_prime(second))                return true;            else                return false;        }    else if(second<first)        {            if(!is_prime(first) and is_prime(second))                return true;            return false;        }    else        return false;}int main(){    vector<int> A={8,5,7,1,2,4,9,3,4,7};    srand(time(0));    for(int i=0;i<100;i++)        A.push_back(rand());    cout<<*max_element(A.begin(),A.end(),compare);    return 0;}ما رأيك بجعله يعيد أقرب عنصر للمتوسّط !! #include <iostream>#include <algorithm>#include <vector>#include <cmath>#include <cstdlib>#include <ctime>using namespace std;int average;bool compare(const int&first,const int&second){    if(abs(first-average)<abs(second-average))        return false;    return true;}int main(){    vector<int> A={8,5,7,1,2,4,9,3,4,7};    srand(time(0));    for(int i=0;i<100;i++)        A.push_back(rand());    average=0;    for(int x:A)        average+=x;    average/=A.size();    cout<<"average = "<<average<<endl;    cout<<*max_element(A.begin(),A.end(),compare);    return 0;}الـ max هو الذي يعيد false كلما كان هو الوسيط الأول ويعيد true كلما كان هو الوسيط الثاني (في تابع المقارنة)   تجدر الإشارة إلى أن جسم التابع هو مشابه لما يلي : template <class ForwardIterator> ForwardIterator max_element ( ForwardIterator first, ForwardIterator last ){ if (first==last) return last; ForwardIterator largest = first; while (++first!=last) if (*largest<*first) // or: if (comp(*largest,*first)) for version (2) largest=first; return largest;}-أخيراً من الأمور التي يجب معرفتها أن بعض البنى لا توفر Forward Iterator مثل stack و queue .. وهذه لا يمكن البحث بداخلها عن أكبر عنصر باستخدام هذا التابع .   المراجع : cpp-reference أسئلة وأمثلة : مثال مباشر وواضح stackoverflow   والله ولي التوفيق