بما أني لا أجيد قراءة الخوارزميات، واحتجت إلى خوارزمية ترتيب، فقد صممت واحدة، أحببت أن أشارك بها لمن لا يجيد قراءة الخوارزميات.
خوارزمية ترتيب
لنفرض السلسلة التالية من الأرقام المسجلة عشوائيا في خانات هذه السلسلة (س) ونريد أن نرتبها تصاعديا:
الخانة: 0 1 2 3 4 5 6 7 8 9
القيمة: 15 12 68 56 23 82 28 7 14 89
نختار إحدى القيم عشوائيا، ولتكن القيمة المسجلة في الخانة (0)، وهي 15
نبدأ دورة المقارنة:
- نسمي القيمة التي اخترناها بـ (الأساس)
- نسمي رقم الخانة التي تحوي الأساس بـ(المبدأ)
في هذه الحالة: الأساس: 15، المبدأ 0
- ننشيء سلسلتين فارغتين، الأولى للقيم الأعلى من الأساس (سع)، والثانية للأصغر(سص).
- نبدأ حلقة المقارنة، وعند كل عملية مقارنة، يجب أن نصل إلى نتيجة: القيمة المقارنة أصغر أو أكبر من الأساس. (طبعا لا يجب أن نقارن الأساس مع نفسه، لذا وفي هذه الحالة، كان الأساس هو الخانة (0)، لذا نبدأ من الخانة (1) بعملية المقارنة)
- نسجل القيمة التي قارناها بحسب نتيجة المقارنة، فإذا كانت القيمة أكبر من الأساس تسجل في السلسلة الخاصة بالقيم الأعلى، والعكس بالعكس. مثلا: مقارنة (1) مع (أساس) تعطي أن (1) أصغر، وبالتالي (1) يتم تسجيلها في (سص) سلسلة الأصغر.
- تنتهي حلقة المقارنة، ونخرج بسلسلتين (سع) و(سص) حيث أن جميع عناصر (سع) أكبر من (0) أو (أساس) وجميع عناصر (سص) أصغر من (أساس) أو (0).
- عرفنا الآن وبشكل مباشر موقع (0) الجديد والنهائي وفق الترتيب التصاعدي الذي اخترناه سلفا، والترتيب الجديد للقيمة الموجودة في (0) (تصاعديا) هو طول السلسلة (سص) + مبدأ!! وهذا طبيعي(أنظر الخطوة السابقة لتعرف لماذا)، المهم الآن أن نسمي الموقع الجديد للأساس والذي اكتشفناه للتو، وليكن اسمه (مرتب).
- بما أن الخوارزمية عودية (تكرارية)، ننفذ هذه الحلقة من جديد مرة بالنسبة لـ(سص) ومرة بالنسبة لـ(سع).
- عند تنفيذ الحلقة بالنسبة لـ(سع)، وكما في بداية الحلقة، يجب أن نحدد الأساس والمبدأ في السلسلة الجديدة، فإذا اخترنا سع(0) كأساس، يكون المبدأ: (مرتب) + 0 + 1، وإذا كان الأساس لـ (سع) هو سع(3) يكون المبدأ: (مرتب) + 3 + 1
أما بالنسبة لـ(سص) يكون المبدأهو نفس المبدأ الحالي.
الشرح:
لنحاكي مجرى الأحداث لكي نفهم خطوات الخوارزمية:
بداية ننشيء سلسلة جديدة (ر) تختوي الترتيب النهائي لعناصر س، وهي بنفس طول س.
أول مرة:
- المبدأ = 0
- الأساس = س(0) = 15
- سص = سلسلة جديدة (وهي سلسلة الأرقام الأصغر من أساس)
- سع = سلسلة جديدة (وهي سلسلة الأرقام الأعلى من أساس)
حلقة مقارنة(ب = 1، إلى ب < طول(س)، ب + 1)
إذاكانت س(ب) أصغر من أساس، أضف س(ب) إلى سص
إذا س(ب) أكبر أو تساوي أساس، أضف س(ب) إلى سع
انتهت الحلقة.
ينتج من الحلقة:
سص{12، 7، 14}
سع{68، 56، 23، 82، 28، 89}
نحسب الموقع الجديد(مرتب) لـ(أساس) ضمن السلسلة النهائية(ر)
مرتب = مبدأ + طول(سص) = 0 + 3 = 3
إذن، ر(3) = أساس = 15
الآن يجب أن نعيد الكرة لـ(سص) و(سع)، وهذا يستوجب منا تحديد المعطيات الجديدة لكل حالة.
من أجل سص:
الأساس = سص(0) = 12
// المبدأ = المبدأ(الحالي) = 0
ونبدأ الحلقة على هذا الأساس، وبنهايتها، نجد:
(انتبه أن سص، و سع هنا هما غير السابقتين، لأننا نفوم بالحلقة على سص السابقة وليس س)
سص{7}
سع{14}
في حالة كهذه، نجد أن المجموعة سص أو سع تحوي عنثر واحد، وهذا هو أحد مؤشرات نهاية جانب من العمليات، وبالتالي من المفيد قبل إرسال أي سلسلة إلى الدورة التحقق من طولها، فقد تكون فارغة أو أحادية العنصر أو ثنائيته، وهنا من الأجدى معالجة هذه الحالات بدون دورات.
على كل يجب أن نحدد الموقع الجديد للأساس قبل كل شيء.
كما في السابق: مرتب = مبدأ + طول(سص) = 0 + 1 = 1
أي أن ر(1) = أساس = 12
تقوم بالتحقق من طول(سص) قبل إرسالها بشكل تكراري للدورة، نجد أن طولها < 3 هذا معناه أنه من الأفقضل أن نعالجها بشكل يدوي، بطبيعة الحال نكتشف أن الموقع الجديد للعنصر الوحيد لـ(سص) هو:
مرتب – 1 = 0
أي أن ر(مرتب - 1) = سص(0) = 7
هنا ر(0) = 7
وهي أصغر قيمة في السلسلة (س)
أيضا سع أحادية، وبالتالي ر(مرتب + 1) = سع(0)
هنا ر(2) = 14
أصبحت السلسلة ر:
{7، 12، 14، 15، ؟، ؟، ؟، ؟، ؟، ؟}
العلامة (؟) تعني أننا لم نضع فيها شيء بعد.
من أجل سع: (الخاصة بـ (س))
للتذكير: سع{68، 56، 23، 82، 28، 89}
الأساس = سع(0) = 68
المبدأ = المرتب + 1 = 3 + 1 = 4
نلاحظ أهملت الصفر الخاص بـ سع(0)، لكن لو كان الأساس الجديد من خانة غير الصفر وجبت إضافته.
بتنفيذ الحلقة:
سص{56، 23، 28}
سع{82، 89}
نحسب الموقع الجديد لـ(أساس) ضمن ر
مرتب = مبدأ + طول(سص) = 4 + 3 = 7
تصبح ر:
{7، 12، 14، 15، ؟، ؟، ؟، 68، ؟، ؟}
من الواضح أن (سع) هي إحدى الحالات الخاصة والتي تعالج بدون الحالجة لدورة كاملة، فهي ثنائية العناصر (أي أن كل الحالات الخاصة هي للمجموعات ذات عدد عناصر أصغر من ثلاثة)
وبالتالي وعند معالجاتها، تصبح ر:
{7، 12، 14، 15، ؟، ؟، ؟، 68، 82، 89}
بقي لدينا (سص)، وبالتالي يجب أن نحدد المبدأ لها:
المبدأ = المبدأ(الحالي) = 4
الأساس = سص(0) = 56
نحصل على:
سص{23، 28}
سع{}
نحسب المرتب:
مرتب = مبدأ + طول(سص) = 4 + 2 = 6
أي أن ر(6) = أساس = 56
واضح أن سع هي حالة خاصة لأنها فارغة، ولا داعي لفعل شيء لها، أيضا سص حالة خاصة.
تصبح ر:
{7، 12، 14، 15، ؟، ؟، 56، 68، 82، 89}
وبحل سص، تصبح ر:
{7، 12، 14، 15، 23، 28، 56، 68، 82، 89}
المهم في هذه الخوارزمية تذكر أن (مرتب) و(مبدأ) أي عملية هو كالتالي:
مرتب = مبدأ + طول(سص)
مبدأ:
بالنسبة لـ (سص) هو نفسه مبدأ العملية التي جرت.
بالنسبة لـ(سع) هو المرتب الذي حسبناه مضافا إليه واحد: مبدأ = مرتب + 1
أما بالنسبة لأول مرة، تكون هذه القيم صفر:
مرتب = 0
مبدأ = 0
يمكن البدء من موقع غير الصفر، ولكن تجنبا للتعقيد فضلت الصفر، عادة أختار موقع غير الصفر للكشف عما إذا كانت السلسلة مرتبة سلفا، أو لإيجاد قيمة وسطية بحيث تكون أطوال سص و سع متقاربة قدر الإمكان.
من ميزات هذه الخوارزمية، أن كل دورة تحدد لنا ترتيب نهائي لقيمة واحدة، أي أن عدد الدورات مساو أو أقل من طول السلسلة الأساسية(أقل عند ظهور الحالات الخاصة).
أيضا تتجنب الدخول في حلقة عند ظهور حالة خاصة بالإضافة لسهولة تتطبيقها، في الواقع أجد شرحها أطول من تطبيقها.
قمت بتجربتها على سجل يحوي أكثر من ألف اسم للقيام بترتيب الأسماء أبجديا، وكان أداؤها جيدا.
من مساوئها أنها غير عملية عند إضافة خانات جديدة للسلسلة، وهنا يجب اتباع تكتيك آخر.
أيضا من مساوئها أننا نحتاج إلى سلسلة إضافية (ر) لتخزين القيم المرتبة مما يضاعف حجم الذاكرة المطلوبة.
بالنهاية هناك الكثير مما يمكن فعله لتطوير هذه الخوارزمية مثل التخلص من السلسلة الإضافية، وأتوقع أن تكون هذه الخوارزمية موجودة أساسا وهناك ما هو أفضل منها بكثير، ولكن أعتز بها لأنني صممتها بنفسي.
على كل حال هذه مساهمتي، أتمنى أن تفيد وأن تطلعوني عما لديكم.
أرجو أن أكون قد أوضحت الفكرة.