الحاويات الديناميكية (STL Components) في C++
مفهوم STL في C++
STL هي إختصار لجملة Standard Template Library و هي عبارة عن مكتبة ضخمة تحتوي على دوال و كلاسات جاهزة تستخدم لتخزين مجموعة من القيم بشكل مرن جداً يجعل التعامل معها سهل للغاية من ناحية إضافة عناصر فيها, حذف عناصر منها, تحديث قيم عناصرها, ترتيب عناصرها و البحث فيها. و هي تتضمن الأشياء التالية:
حاويات (Containers).
خوارزميات (Algorithms).
دوال (Functions).
متواليات (Iterators).
في هذا الدرس سنتعرف على جميع أنواع الحاويات الموجودة في هذه المكتبة و ستتعلم كيفية التعامل معها بتفصيل ممل.
الحاويات الدينامكية في C++
الحاويات تنقسم لأربع فئات أساسية من ناحية الطريقة التي يتم فيها تخزين البيانات و من ثم إمكانية الوصول لها و كل فئة تحتوي على مجموعة كلاسات كالتالي.
1- مفهوم Sequence Containers في C++
الحاوية التي تندرج تحت هذا النوع يقصد بها أن الحاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض مع إعطاء كل عنصر منهم رقم Index و كأنها مصفوفة عادية.
2- مفهوم Container Adaptors في C++
الحاوية التي تندرج تحت هذا النوع يقصد بها أن الحاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض مع القدرة على الوصول إليها بحسب الترتيب الذي تم فيه إدخالها بأسلوب FIFO أو بأسلوب LIFO أو بحسب الأولوية المعطات لعناصرها.
3- مفهوم Associative Containers في C++
الحاوية التي تندرج تحت هذا النوع يقصد بها أن الحاوية تخزن العناصر التي نضيفها فيها بشكل جدول حيث أن كل عنصر نضيفه فيها يحتوي على مفتاح ( Key ) و قيمة ( Value ) مع الإشارة إلى أنها تخزن المفاتيح بترتيب بشكل أبجدي أو رقمي على حسب نوعها.
4- مفهوم Unordered Associative Containers في C++
الحاوية التي تندرج تحت هذا النوع يقصد بها أن الحاوية تخزن العناصر التي نضيفها فيها على شكل Buckets مما يجعل الوصول إليها سريع جداً.
الفرق بين المصفوفة العادية و الحاوية الدينامكية في C++
المصفوفات العادية تجبرك على تحديد عدد عناصرها لحظة إنشاءها حتى يتم حجز مساحة ثابتة لها في الذاكرة و من بعدها تستطيع التعامل معها.
الحاويات الدينامكية تحجز مساحة في الذاكرة للعنصر الذي تضيفه فيها في ذات اللحظة, و عند حذف عنصر منها تقوم بالتخلي عن المساحة المحجوزة مما يجعل برنامجك أخف على الذاكرة.
المصفوفة العادية نتعامل مع عناصرها فقط من خلال رقم Index العنصر أما في الحاويات الدينامكية فيوجد دوال عديدة نستخدمها للتعامل مع العناصر.
الكلاسات الموجودة في STL في C++
الجدول التالي يحتوي على جميع الكلاسات الموجودة في STL و التي تمثل حاويات دينامكية.
الكلاس مع تعريفه | |
---|---|
array
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11 و هو يستخدم لإنشاء كائن يمثل مصفوفة متطورة مقارنةً بالمصفوفة العادية حيث أن التعامل معها مرن أكثر لأنك تستطيع معرفة عدد عناصرها و الحصول على قيمة أول و آخر عنصر فيها بكل سهولة.المزيد » |
|
vector
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض مع إعطاء كل عنصر منهم رقم Index.إذاً يشبه المصفوفة العادية إلى حد ما و لكن الفرق الأساسي بينهما أن حجمه ليس ثابتاً حيث يمكنك إضافة العدد الذي تريده من العناصر فيه وقتما شئت. المزيد » |
|
forward_list
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11 و هو يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض مع إعطاء كل عنصر منهم عنوان العنصر الذي يليه في الذاكرة حتى يتم الحفاظ على الترتيب الذي تم فيه تخزينهم.المزيد » |
|
list
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض مع إعطاء كل عنصر منهم عنوان العنصر الذي يسبقه و عنوان العنصر الذي يليه في الذاكرة حتى يتم الحفاظ على الترتيب الذي تم فيه تخزينهم و لتتمكن من التنقل بين العناصر بالإتجاهين; من الأول إلى الآخر و بالعكس.المزيد » |
|
stack
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل فوق بعضها البعض بأسلوب LIFO الذي يعني أن العنصر الذي يدخل أولاً يخرج أخيراً, و هذا يجعلك قادر فقط على التعامل مع العنصر الموجود في أعلاها.المزيد » |
|
queue
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض بأسلوب FIFO الذي يعني أن العنصر الذي يدخل أولاً يخرج أولاً, و هذا يجعلك قادر فقط على التعامل مع العنصر الموجود في آخرها.المزيد » |
|
priority_queue
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض و بترتيب معين حيث يتم وضع العنصر الذي يملك القيمة الأكبر في البداية و العنصر الذي يملك القيمة الأصغر في النهاية, بالإضافة إلى أنه يسمح لك بالوصول لأعلى و أدنى قيمة فقط لأنها موجودة على أطراف الحاوية مع إمكانية حذف القيمة الأدنى منها فقط.المزيد » |
|
deque
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل مع إعطاء كل عنصر منهم رقم Index مما يجعلك قادر على الوصول إلى جميع عناصرها و إضافة عناصر جديدة في أي مكان فيها, و يميز هذه الحاوية بأنك قادر على التعامل مع العناصر الموجودة على أطرافها بشكل مباشر.المزيد » |
|
set
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض و بترتيب معين حيث يتم وضع العنصر الذي يملك القيمة الأصغر في البداية و العنصر الذي يملك القيمة الأكبر في النهاية أو العكس, مع الإشارة إلى أنه لا يمكن تخزين قيم مكررة فيها.المزيد » |
|
multiset
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض و بترتيب معين حيث يتم وضع العنصر الذي يملك القيمة الأصغر في البداية و العنصر الذي يملك القيمة الأكبر في النهاية أو العكس, مع الإشارة إلى أنه يمكن تخزين قيم مكررة فيها.المزيد » |
|
map
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل جدول يتألف من عمودين حيث يتكون كل عنصر من مفتاح ( Key ) يوضع في العمود الأول و قيمة ( Value ) توضع في العمود الثاني بالإضافة إلى أنها ترتب العناصر بشكل تصاعدي على حسب قيم المفاتيح.المزيد » |
|
multimap
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل جدول يتألف من عمودين حيث يتكون كل عنصر من مفتاح ( Key ) يوضع في العمود الأول و قيمة ( Value ) توضع في العمود الثاني بالإضافة إلى أنها ترتب العناصر بشكل تصاعدي على حسب قيم المفاتيح مع الإشارة إلى أنه يمكن وضع نفس المفتاح لأكثر من عنصر.المزيد » |
|
unordered_set
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11 و هو يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بترتيب معين يتم تحديده من قبل دالة مخصصة لذلك إسمها Hash() تقوم بالتشييك على قيم أي عنصر سيتم إدخاله لتحديد المكان الذي يجب وضعه فيه.المزيد » |
|
unordered_multiset
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11 و هو يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بترتيب معين يتم تحديده من قبل دالة مخصصة لذلك إسمها Hash() تقوم بالتشييك على قيم أي عنصر سيتم إدخاله لتحديد المكان الذي يجب وضعه فيه مع الإشارة إلى أنه يمكن تخزين قيم مكررة فيها.المزيد » |
|
unordered_map
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11 و هو يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل جدول يتألف من عمودين حيث يتكون كل عنصر من مفتاح ( Key ) يوضع في العمود الأول و قيمة ( Value ) توضع في العمود الثاني بالإضافة إلى أنها ترتب العناصر بالإعتماد على دالة مخصصة لذلك إسمها Hash() تقوم بالتشييك على مفتاح أي عنصر سيتم إدخاله لتحديد المكان الذي يجب وضعه فيها.المزيد » |
|
unordered_multimap
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11 و هو يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل جدول يتألف من عمودين حيث يتكون كل عنصر من مفتاح ( Key ) يوضع في العمود الأول و قيمة ( Value ) توضع في العمود الثاني بالإضافة إلى أنها ترتب العناصر بالإعتماد على دالة مخصصة لذلك إسمها Hash() تقوم بالتشييك على مفتاح أي عنصر سيتم إدخاله لتحديد المكان الذي يجب وضعه فيها مع الإشارة إلى أنه يمكن وضع نفس المفتاح لأكثر من عنصر.المزيد » |
الكلاس array
في C++
تعريف الكلاس array
في C++
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11
و هو يستخدم لإنشاء كائن يمثل مصفوفة متطورة مقارنةً بالمصفوفة العادية حيث أن التعامل معها مرن أكثر لأنك تستطيع معرفة عدد عناصرها و الحصول على قيمة أول و آخر عنصر فيها بكل سهولة.
بعد أن يتم تحديد عدد العناصر التي يمكن إضافتها فيه, لا يمكن تغييره كما هو الحال في المصفوفات العادية.
لاستخدام الكلاس array
يجب تضمين الملف #include<array>
لأنه موجود فيه.
template < class T, size_t N > class array
إذاً عند إنشاء كائن من الكلاس array
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر T
و عدد العناصر الأقصى الذي قد نحتاج تخزينه فيه مكان الباراميتر .N
دوال الكلاس array
في C++
الجدول التالي يحتوي على دوال الكلاس array
الأكثر إستخداماً.
الدالة مع تعريفها | |
---|---|
T at(size_t n)
ترجع العنصر الموجود على الـ index الذي نمرره لها مكان الباراميتر n عند استدعائها.ترمي الإستثناء out_of_range في حال كان الـ index المحدد فيها أصغر من 0 أو أكبر من عدد العناصر الموجودة.معلومة: يمكنك استخدام العامل [] للوصول للعنصر و لكن عليك معرفة أن استخدام هذا العامل لا يرمي إستثناء في حال تمرير index غير موجود في الكائن. |
|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
T front()
ترجع قيمة أول عنصر موجود في الكائن الذي قام باستدعائها.قد تسبب مشكلة في حال كان الكائن لا يملك أي عنصر, لذلك يفضل التأكد من أن الكائن غير فارغ باستخدام الدالة empty() قبل استخدامها. |
|
T back()
ترجع قيمة آخر عنصر موجود في الكائن الذي قام باستدعائها.قد تسبب مشكلة في حال كان الكائن لا يملك أي عنصر, لذلك يفضل التأكد من أن الكائن غير فارغ باستخدام الدالة empty() قبل استخدامها. |
|
void fill(T val)
تستخدم لإعطاء قيمة لكل عنصر موجود الكائن الذي قام باستدعائها.مكان الباراميتر val يجب أن تمرر قيمة من نفس نوع البيانات التي يمكن للكائن في الأساس أن يخزّنها. |
|
size_t size()
تستخدم للحصول على عدد عناصر الكائن الذي قام باستدعائها.القيمة التي ترجعها هي نفسها القيمة التي نمررها مكان الباراميتر الثاني الذي نمرره عند إنشاء الكائن و الذي يمثل عدد عناصره. معلومة: الفرق بين الدالة size() و العامل sizeof هو أن هذا الأخير يرجع حجم العناصر في الذاكرة بالوحدة Byte و ليس عددها. |
|
void swap(array& anotherArray)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherArray نمرر لها كائن من الكلاس array يملك نفس نوع و عدد عناصر الكائن الذي قام باستدعاء. |
أمثلة شاملة حول التعامل مع الكلاس array
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من array
مع تحديد أنه يمكن أن يحتوي على 5 عناصر نوعها int
.
بعدها قمنا بوضع 0
كقيمة أولية لجميع عناصره و ثم عرض جميع قيمه باستخدام حلقة.
ملاحظة: قمنا باستخدام العامل []
للوصول إلى العناصر و الدالة size()
لمعرفة حجم المصفوفة.
#include <iostream> #include <array> using namespace std; int main() { // int يمكنه أن يحتوي على 5 قيم نوعها array هنا قمنا بتعريف كائن من الكلاس array<int,5> myArray; // هنا قمنا بوضع القيمة 0 كقيمة أولية لجميع عناصره myArray.fill(0); // إلى 5 myArray هنا قمنا بتغير قيمة أول عنصر في الكائن myArray[0] = 5; // إلى 7 myArray هنا قمنا بتغير قيمة ثالث عنصر في الكائن myArray[2] = 7; // إلى 9 myArray هنا قمنا بتغير قيمة آخر عنصر في الكائن myArray[myArray.size()-1] = 9; cout << "Array values = "; // myArray هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(size_t i=0; i<myArray.size(); i++) { cout << myArray[i] << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Array values = 5 0 7 0 9
في المثال التالي قمنا بتعريف كائن من array
أدخلنا فيه 5 عناصر نصية.
بعدها قمنا بطباعة عدد عناصره و أول و آخر قيمة فيه.
ملاحظة: قمنا باستخدام الدالة empty()
لمعرفة ما إن كانت المصفوفة فارغة أم لا, الدالة front()
للحصول على قيمة أول عنصر و الدالة back()
للحصول على قيمة آخر عنصر.
#include <iostream> #include <array> using namespace std; int main() { // بالإضافة إلى أننا قمنا بوضع قيم أولية في عناصره string يمكنه أن يحتوي على 5 قيم نوعها array هنا قمنا بتعريف كائن من الكلاس array<string,5> myArray = {"One", "Two", "Three", "Four", "Five"}; // size() باستخدام الدالة myArray هنا قمنا بطباعة عدد عناصر الكائن cout << "Array size = " << myArray.size() << endl; // و إن لم يكن فارغاً سيتم طباعة أول و آخر قيمة فيه empty() باستخدام الدالة myArray هنا قمنا بالتشييك على عدد عناصر الكائن if (!myArray.empty()) { cout << "Array first element value = " << myArray.front() << endl; cout << "Array last element value = " << myArray.back(); } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Array size = 5 Array first element value = One Array last element value = Five
في المثال التالي قمنا بتعريف كائنين من array
في كل منهما 4 عناصر من النوع نوعها int
.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة القيم التي أصبحت موجودة في كلٍّ منهما.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل قيمهما و الدالة at()
للوصول لقيم العناصر الموجودة فيهما.
#include <iostream> #include <array> using namespace std; int main() { // مع إعطاؤهما قيم أولية int يحتوي كل منهما على 4 عناصر نوعها array هنا قمنا بتعريف كائنين من الكلاس array<int,4> arr1 = {1, 2, 3, 4}; array<int,4> arr2 = {5, 6, 7, 8}; // arr2 مع قيم الكائن arr1 هنا قمنا بتبديل قيم الكائن arr1.swap(arr2); cout << "arr1 values = "; // arr1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(size_t i=0; i<arr1.size(); i++) { cout << arr1.at(i) << " "; } cout << "\narr2 values = "; // arr2 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(size_t i=0; i<arr2.size(); i++) { cout << arr2.at(i) << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
arr1 values = 5 6 7 8 arr2 values = 1 2 3 4
الكلاس vector
في C++
تعريف الكلاس vector
في C++
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض مع إعطاء كل عنصر منهم رقم Index.
إذاً يشبه المصفوفة العادية إلى حد ما و لكن الفرق الأساسي بينهما أن حجمه ليس ثابتاً حيث يمكنك إضافة العدد الذي تريده من العناصر فيه وقتما شئت.
لاستخدام الكلاس vector
يجب تضمين الملف #include<vector>
لأنه موجود فيه.
template < class T, class Alloc = allocator<T> > class vector
إذاً عند إنشاء كائن من الكلاس vector
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر T
.
دوال الكلاس vector
في C++
الجدول التالي يحتوي على دوال الكلاس vector
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator rbegin()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
|
iterator rend()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
الجدول التالي يحتوي على دوال الكلاس vector
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
|
void resize(size_type n)
تستخدم لحجز مساحة للعناصر التي تنوي تخزينها لاحقاً في الكائن الذي قام باستدعائها.عند تمرير قيمة للبارميتر n يجب أن لا تكون أصغر من عدد العناصر الموجودة في الكائن, لأنك إذا فعلت ذلك سيتم حذف العناصر التي لم يعد الكائن قادر على تخزينها.كما أنها ترمي الإستثناء bad_alloc في حال قمت بتمرير قيمة أكبر من عدد العناصر الأقصى التي يمكن تخزينها في الكائن. معلومة: هذه الدالة قد تكون مفيدة في حال أردت حجز مساحة أوليّة للعناصر قبل البدء بإضافتهم بدل جعل المترجم يفعل ذلك كلما أضفت عنصر جديد. هذه المعلومة غير مذكورة في المرجع الرسمي للغة C++ لذا قد تكون غير دقيقة. |
|
size_t capacity()
تستخدم للحصول على عدد العناصر التي تم حجز مساحة لها في الذاكرة من أجل الكائن الذي قام باستدعائها.معلومة: الرقم الذي ترجعه هذه الدالة في العادة يكون أكبر بنسبة قليلة من الرقم الذي ترجعه الدالة size() و سبب ذلك أن المترجم يقوم بتخصيص مساحة زيادة للكائن حتى يستخدمها عندما يحتاجها. |
|
void shrink_to_fit()
تستخدم للتخلي عن أي مساحة زيادة مخصصة في الذاكرة للكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس vector
التي تستخدم للوصول لقيم عناصره.
الدالة مع تعريفها | |
---|---|
T at(size_t n)
تستخدم للوصول لقيمة عنصر محدد في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.مكان الباراميتر n نمرر لها رقم يمثل index العنصر الذي نريد الوصول إليه.ترمي الإستثناء out_of_range في حال كانت قيمة n أصغر من 0 أو أكبر من عدد العناصر الموجودة.معلومة: يمكنك استخدام العامل [] للوصول للعنصر و لكن عليك معرفة أن استخدام هذا العامل لا يرمي إستثناء في حال تمرير index غير موجود في الكائن. |
|
T front()
تستخدم للوصول لقيمة أول عنصر موجود في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.قد تسبب مشكلة في حال كان الكائن لا يملك أي عنصر, لذلك يفضل التأكد من أن الكائن غير فارغ باستخدام الدالة empty() قبل استخدامها. |
|
T back()
تستخدم للوصول لقيمة آخر عنصر موجود في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.قد تسبب مشكلة في حال كان الكائن لا يملك أي عنصر, لذلك يفضل التأكد من أن الكائن غير فارغ باستخدام الدالة empty() قبل استخدامها. |
|
T* data()
ترجع مؤشر لقيمة أول عنصر موجود في الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس vector
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
void assign(size_t n, const T& val)
تستخدم لإضافة عدة عناصر في الكائن الذي قام باستدعائها و هي تحذف أي عناصر أخرى موجودة فيه في حال لم يكن فارغاً.مكان الباراميتر n نمرر عدد العناصر التي نريد إضافتها في الكائن الذي قام باستدعائها.مكان الباراميتر val نمرر القيمة التي نريد وضعها للعناصر التي سيتم إضافتها في الكائن الذي قام باستدعائها. |
|
void push_back(T& val)
تستخدم لإضافة عنصر جديد في آخر الكائن الذي قام باستدعائها. |
|
void pop_back()
تستخدم لحذف آخر عنصر موجود في الكائن الذي قام باستدعائها. |
|
iterator insert(const_iterator position, T& val)
تستخدم لإضافة عنصر جديد في مكان محدد - أي عند عنوان محدد - في الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان المكان الذي سيتم إضافة العنصر عنده في الذاكرة.مكان الباراميتر val نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.كما أنها ترجع كائن أصله من Iterator يمثل عنوان العنصر الذي تم إضافته. |
|
void clear()
تستخدم لحذف جميع العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
iterator erase(const_iterator position)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه. |
|
iterator erase(const_iterator first, const_iterator last)
تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها.مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده. |
|
void swap(vector& anotherVector)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherVector نمرر لها كائن من الكلاس vector يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
أمثلة شاملة حول التعامل مع الكلاس vector
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من vector
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة 5 قيم فيه و من ثم عرض جميع قيمه باستخدام حلقة.
ملاحظة: قمنا باستخدام الدالة push_back()
لإضافة العناصر, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها, العامل []
للوصول إلى العناصر.
المثال الأول
#include <iostream> #include <vector> using namespace std; int main() { // int يمكنه أن يحتوي على قيم نوعها vector هنا قمنا بتعريف كائن من الكلاس vector<int> myVector; // push_back() باستخدام الدالة myVector هنا قمنا بإضافة 5 عناصر في الكائن myVector.push_back(1); myVector.push_back(2); myVector.push_back(3); myVector.push_back(4); myVector.push_back(5); cout << "Vector values = "; // myVector هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(size_t i=0; i<myVector.size(); i++) { cout << myVector[i] << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Vector values = 1 2 3 4 5
في المثال التالي قمنا بتعريف كائن من vector
أدخلنا فيه 5 عناصر نصية.
بعدها قمنا بإضافة 5 قيم فيه و من ثم عرض عدد جميع عناصره, عدد العناصر التي قام المترجم بتخصيص مساحة لها في الذاكرة في حال أردنا إضافة عناصر جديدة, عدد جميع العناصر التي يمكن إضافتها فيه, بالإضافة لأول و آخر قيمة موجودة فيه.
ملاحظة: قمنا باستخدام الدالة size()
لمعرفة عدد العناصر التي تم إضافتها, الدالة capacity()
لمعرفة عدد العناصر المخصصة حالياً للكائن في الذاكرة حتى لو لم يحتاج إليها, الدالة max_size()
لمعرفة أكبر عدد عناصر يمكن إضافتها فيه, الدالة empty()
لمعرفة ما إن كانت المصفوفة فارغة أم لا, الدالة front()
للحصول على قيمة أول عنصر و الدالة back()
للحصول على قيمة آخر عنصر.
#include <iostream> #include <vector> using namespace std; int main() { // string يمكنه أن يحتوي على 5 قيم نوعها vector هنا قمنا بتعريف كائن من الكلاس vector<string> myVector; // push_back() باستخدام الدالة myVector هنا قمنا بإضافة 5 عناصر في الكائن myVector.push_back("One"); myVector.push_back("Two"); myVector.push_back("Three"); myVector.push_back("Four"); myVector.push_back("Five"); // size() باستخدام الدالة myVector هنا قمنا بطباعة عدد عناصر الكائن cout << "Vector size = " << myVector.size() << endl; // capacity() باستخدام الدالة myVector هنا قمنا بطباعة عدد العناصر التي تم تخصيص لها مساحة في الذاكرة حالياً من أجل الكائن cout << "Vector capacity = " << myVector.capacity() << endl; // max_size() باستخدام الدالة myVector هنا قمنا بطباعة عدد العناصر الأقصى التي يمكن تخزينها في الكائن cout << "Vector max size = " << myVector.max_size() << endl; // و إن لم يكن فارغاً سيتم طباعة أول و آخر قيمة فيه empty() باستخدام الدالة myVector هنا قمنا بالتشييك على عدد عناصر الكائن if (!myVector.empty()) { cout << "Vector first element value = " << myVector.front() << endl; cout << "Vector last element value = " << myVector.back(); } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Vector size = 5 Vector capacity = 8 Vector max size = 576460752303423487 Vector first element value = One Vector last element value = Five
في المثال التالي قمنا بتعريف كائن من vector
مخصص لتخزين قيم نوعها int
مع إضافة 9 قيم فيه عند تعريفه.
بعدها قمنا بحذف عدة عناصر منه بطرق مختلفة و من ثم طباعة قيم العناصر المتبقية.
ملاحظة: قمنا باستخدام الدالة pop_back()
لحذف آخر عنصر من الكائن, الدالة erase()
لحذف عنصر واحد, الدالة erase()
مرة ثانية لحذف أكثر من عنصر في وقت واحد و الدالة begin()
للحصول على عدّاد يمكن من خلاله تحديد مكان العناصر التي سيتم حذفها.
#include <iostream> #include <vector> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة 9 قيم فيه int يمكنه أن يحتوي على عناصر نوعها vector هنا قمنا بتعريف كائن من الكلاس vector<int> myVector = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // myVector هنا قمنا بحذف آخر عنصر موجود في الكائن // {1, 2, 3, 4, 5, 6, 7, 8} أصبح فيه القيم التالية myVector إذاً الكائن myVector.pop_back(); // myVector يساوي 2 في الكائن index هنا قمنا بحذف العنصر الذي يملك // {1, 2, 4, 5, 6, 7, 8} أصبح فيه القيم التالية myVector إذاً الكائن myVector.erase(myVector.begin() + 2); // يساوي 1 وصولاً إلى index إبتداءاً من العنصر الذي يملك myDeque هنا قمنا بحذف العناصر الموجودة في الكائن // {1, 6, 7, 8} أصبح فيه القيم التالية myVector يساوي 4. و بالتالي الكائن index ما قبل العنصر الذي يملك myVector.erase(myVector.begin() + 1, myVector.begin() + 4); cout << "Vector values = "; // myVector هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(size_t i=0; i<myVector.size(); i++) { cout << myVector[i] << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Vector values = 1 6 7 8
في المثال التالي قمنا بتعريف كائن من vector
مخصص لتخزين قيم نوعها int
مع إضافة 5 قيم فيه عند تعريفه.
بعدها قمنا بعرض جميع عناصره مرتين, مرة من أول عنصر لآخر عنصر, و مرة من آخر عنصر لأول عنصر.
ملاحظة: عند البدء من أول عنصر لآخر عنصر, قمنا باستخدام الدالة begin()
للحصول على عدّاد يمكن من خلاله البدئ من العنصر الأول و الدالة end()
للحصول على قيمة العدّاد التي من خلالها نعرف أننا وصلنا لآخر عنصر.
و عند البدء من آخر عنصر لأول عنصر, قمنا باستخدام الدالة rbegin()
للحصول على عدّاد يمكن من خلاله البدئ من آخر عنصر و الدالة rend()
للحصول على قيمة العدّاد التي من خلالها نعرف أننا وصلنا لأول عنصر بدون الحاجة لتغيير شكل الحلقة التي استخدمناها في المرة الأولى.
#include <iostream> #include <vector> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة 5 قيم فيه int يمكنه أن يحتوي على عناصر نوعها vector هنا قمنا بتعريف كائن من الكلاس vector<int> myVector = {1, 2, 3, 4, 5}; cout << "Vector values from begin to end = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myVector هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(auto it=myVector.begin(); it<myVector.end(); it++) { cout << *it << " "; } cout << "\nVector values from end to begin = "; // إبتداءاً من آخر عنصر وصولاً لأول عنصر فيه myVector هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(auto it=myVector.rbegin(); it<myVector.rend(); it++) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Vector values from begin to end = 1 2 3 4 5 Vector values from end to begin = 5 4 3 2 1
في المثال التالي قمنا بتعريف كائن من vector
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة 5 قيم فيه, و من ثم عرض عدد جميع عناصره و عدد العناصر التي قام المترجم بتخصيص مساحة لها في الذاكرة في حال أردنا إضافة عناصر جديدة.
بعدها قمنا بالتخلي عن أي مساحة خصصها المترجم بشكل إفتراضي للكائن حتى يخزن قيم فيها إن إحتاجها.
في الأخير قمنا بإعادة عرض المعلومات السابقة للتأكد ما إن تم التخلي عن المساحة التي يستخدمها الكائن أم لا.
ملاحظة: قمنا باستخدام الدالة size()
لمعرفة عدد العناصر التي تم إضافتها, الدالة capacity()
لمعرفة عدد العناصر المخصصة حالياً للكائن في الذاكرة حتى لو لم يحتاج إليها و الدالة shrink_to_fit()
للتخلي عن أي مساحة في الذاكرة لم يحتاج إليها الكائن.
#include <iostream> #include <vector> using namespace std; int main() { // int يمكنه أن يحتوي على قيم نوعها vector هنا قمنا بتعريف كائن من الكلاس vector<int> myVector; // push_back() باستخدام الدالة myVector هنا قمنا بإضافة 5 عناصر في الكائن myVector.push_back(1); myVector.push_back(2); myVector.push_back(3); myVector.push_back(4); myVector.push_back(5); // size() باستخدام الدالة myVector هنا قمنا بطباعة عدد عناصر الكائن cout << "Vector size = " << myVector.size() << endl; // capacity() باستخدام الدالة myVector هنا قمنا بطباعة عدد العناصر التي تم تخصيص لها مساحة في الذاكرة حالياً من أجل الكائن cout << "Vector capacity = " << myVector.capacity() << endl; // myVector هنا قمنا بالتخلي عن أي مساحة إضافية حجزها المترجم بشكل تلقائي للكائن myVector.shrink_to_fit(); cout << "\nAfter shrinking the vector\n\n"; // size() باستخدام الدالة myVector هنا قمنا بإعادة طباعة عدد عناصر الكائن cout << "Vector size = " << myVector.size() << endl; // capacity() باستخدام الدالة myVector هنا قمنا بإعادة طباعة عدد العناصر التي تم تخصيص لها مساحة في الذاكرة حالياً من أجل الكائن cout << "Vector capacity = " << myVector.capacity() << endl; return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Vector size = 5 Vector capacity = 8 After shrinking the vector Vector size = 5 Vector capacity = 5
في المثال التالي قمنا بتعريف كائن من vector
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة 5 قيم فيه وراء بعضها.
بعدها قمنا بإضافة قيمة في مكان محدد فيه.
في الأخير قمنا بعرض جميع قيمه باستخدام حلقة.
ملاحظة: قمنا باستخدام الدالة insert()
لإضافة القيمة في مكان محدد في الكائن.
المثال السادس
#include <iostream> #include <vector> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة 5 قيم فيه int يمكنه أن يحتوي على عناصر نوعها vector هنا قمنا بتعريف كائن من الكلاس vector<int> myVector = {1, 2, 3, 4, 5}; // myVector رقم 2 بالنسبة للكائن index هنا قمنا بإضافة القيمة 8 في الـ // {1, 2, 8, 3, 4, 5} أصبح فيه القيم التالية myVector إذاً الكائن myVector.insert(myVector.begin() + 2, 8); cout << "Vector values = "; // myVector هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(size_t i=0; i<myVector.size(); i++) { cout << myVector[i] << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Vector values = 1 2 8 3 4 5
الكلاس forward_list
في C++
تعريف الكلاس forward_list
في C++
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11
و هو يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض مع إعطاء كل عنصر منهم عنوان العنصر الذي يليه في الذاكرة حتى يتم الحفاظ على الترتيب الذي تم فيه تخزينهم كالتالي.
الكائن يملك خانة أساسية يقال لها Head و هي تشير لعنوان أول عنصر موجود فيه.
العنصر الأخير لا يوجد أي عنصر بعده, لهذا يكون عنوان العنصر التالي بالنسبة له يساوي
null
للإشارة إلى أنه لا يوجد عنصر أصلاً بعده.Tail تعني ذَيل و يقصد بها آخر عنصر موجود في الكائن.
لاستخدام الكلاس forward_list
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<forward_list>
لأنه موجود فيه.
template < class T, class Alloc = allocator<T> > class forward_list;
إذاً عند إنشاء كائن من الكلاس forward_list
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر T
.
دوال الكلاس forward_list
في C++
الجدول التالي يحتوي على دوال الكلاس forward_list
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator before_begin()
ترجع كائن iterator يشير للمكان الذي يبدأ عنده تخزين عناصر الكائن في الذاكرة.تستخدم هذه الدالة بشكل أساسي إذا أردت إضافة عنصر جديد قبل أول عنصر موجود في الكائن. |
الجدول التالي يحتوي على دوال الكلاس forward_list
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
|
void resize(size_type n)
تستخدم لحجز مساحة للعناصر التي تنوي تخزنيها لاحقاً في الكائن الذي قام باستدعائها.عند تمرير قيمة للبارميتر n يجب أن لا تكون أصغر من عدد العناصر الموجودة في الكائن, لأنك إذا فعلت ذلك سيتم حذف العناصر التي لم يعد الكائن قادر على تخزينها.كما أنها ترمي الإستثناء bad_alloc في حال قمت بتمرير قيمة أكبر من عدد العناصر الأقصى التي يمكن تخزينها في الكائن. معلومة: هذه الدالة قد تكون مفيدة في حال أردت حجز مساحة أوليّة للعناصر قبل البدء بإضافتهم بدل جعل المترجم يفعل ذلك كلما أضفت عنصر جديد. هذه المعلومة غير مذكورة في المرجع الرسمي للغة C++ لذا قد تكون غير دقيقة. |
الجدول التالي يحتوي على دوال الكلاس forward_list
التي تستخدم للوصول لقيم عناصره.
الدالة مع تعريفها | |
---|---|
reference front()
تستخدم لتغيير قيمة أول عنصر موجود في الكائن الذي قام باستدعائها أو للحصول على قيمته.قد تسبب مشكلة في حال كان الكائن لا يملك أي عنصر, لذلك يفضل التأكد من أن الكائن غير فارغ باستخدام الدالة empty() قبل استخدامها. |
الجدول التالي يحتوي على دوال الكلاس forward_list
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
void assign(initializer_list<T> aList)
تستخدم لوضع مصفوفة من العناصر بدل العناصر الموجودة في الكائن الذي قام باستدعائها.بشكل عام, يمكنك الإستفادة منها في حال أردت تخزين مجموعة من العناصر في الكائن بعد إنشائه. مكان الباراميتر aList نمرر مصفوفة من العناصر التي تحتوي على قيم من نفس نوع الكائن الذي قام باستدعائها. |
|
void emplace_front(T& val)
تستخدم لإضافة عنصر في بداية الكائن الذي قام باستدعائها.مكان الباراميتر val نمرر العنصر الذي نريد إضافته في أول الكائن الذي قام باستدعائها. |
|
void push_front(T& val)
تستخدم لإضافة عنصر في بداية الكائن الذي قام باستدعائها تماماً كالدالة emplace_front() .مكان الباراميتر val نمرر العنصر الذي نريد إضافته في أول الكائن الذي قام باستدعائها. |
|
iterator emplace_after(const_iterator position, T& val)
تستخدم لإضافة عنصر جديد في مكان محدد - أي عند عنوان محدد - في الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يمثل عنوان العنصر الذي سيتم إضافة العنصر الجديد بعده مباشرةً في الذاكرة.مكان الباراميتر val نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.كما أنها ترجع كائن أصله من Iterator يمثل عنوان العنصر الذي تم إضافته. |
|
iterator insert_after(const_iterator position, T& val)
تستخدم لإضافة عنصر جديد في مكان محدد - أي عند رقم عنوان محدد - في الكائن الذي قام باستدعائها تماماً كالدالة emplace_after() .مكان الباراميتر position نمرر كائن أصله من Iterator يمثل عنوان العنصر الذي سيتم إضافة العنصر الجديد بعده مباشرةً في الذاكرة.مكان الباراميتر val نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.كما أنها ترجع كائن أصله من Iterator يمثل عنون العنصر الذي تم إضافته. |
|
iterator erase_after(const_iterator position)
تستخدم لحذف عنصر موجود بعد عنصر محدد في الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يمثل عنوان العنصر الذي سيتم حذف العنصر التالي الموجود بعده.كما أنها ترجع كائن أصله من Iterator يمثل عنوان العنصر الموجود بعد العنصر الذي تم حذفه. |
|
void clear()
تستخدم لحذف جميع العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
void swap(forward_list& anotherList)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherList نمرر لها كائن من الكلاس forward_list يملك نفس نوع عناصر الكائن الذي قام باستدعائه. |
|
void resize(size_type n)
تستخدم لحجز مساحة للعناصر التي تنوي تخزينها لاحقاً في الكائن الذي قام باستدعائها.عند تمرير قيمة للبارميتر n يجب أن لا تكون أصغر من عدد العناصر الموجودة في الكائن, لأنك إذا فعلت ذلك سيتم حذف العناصر التي لم يعد الكائن قادر على تخزينها.معلومة: هذه الدالة قد تكون مفيدة في حال أردت حجز مساحة أوليّة للعناصر قبل البدء بإضافتهم بدل جعل المترجم يفعل ذلك كلما أضفت عنصر جديد. هذه المعلومة غير مذكورة في المرجع الرسمي للغة C++ لذا قد تكون غير دقيقة. |
|
iterator splice_after(const_iterator position, forward_list& anotherList)
تستخدم لإضافة عناصر كائن من forward_list في مكان محدد في الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يمثل عنوان العنصر الذي سيتم إضافة عناصر الكائن anotherList إبتداءاً من عنده.مكان الباراميتر anotherList نمرر الكائن الذي نريد نسخ عناصره و الذي يجب أن تكون عناصره من نفس نوع عناصر الكائن الذي قام باستدعائها. |
|
void remove(const T& val)
تستخدم لحذف جميع العناصر الموجودة في الكائن الذي قام باستدعائها في حال كانت قيمتها تساوي القيمة التي نمررها لها مكان الباراميتر val . |
|
void remove_if(Predicate pred)
تستخدم هذه الدالة لحذف عناصر من الكائن الذي قام باستدعائها في حال كانت قيمه تطابق الشرط الذي نقوم بتمريره لها مكان الباراميتر pred .الباراميتر pred الذي يجب أن نمرره لها سيكون عبارة عن دالة ترجع true في حال كان يجب حذف العنصر و false في حال لم يكن يجب ذلك. |
|
void unique()
تستخدم لحذف القيم المكررة من الكائن الذي قام باستدعائها.بمعنى آخر, تقوم بحذف أي قيمة تجدها متكررة فيه و تترك نسخة واحدة منها. معلومة: عند استخدام هذه الدالة يجب أن تكون القيم المكررة مرتبة وراء بعضها البعض و لفعل هذا الأمر قم فقط باستدعاء الدالة sort() من الكائن قبل استدعاء هذه الدالة. |
|
void merge(forward_list& anotherList)
تستخدم لنقل عناصر كائن من forward_list في آخر الكائن الذي قام باستدعائها.عند نقل عناصر الكائن anotherList إلى الكائن الذي قام باستدعائها يصبح فارغاً. |
|
void sort()
تستخدم لترتيب عناصر الكائن الذي قام باستدعائها من الأصغر إلى الأكبر. |
|
void reverse()
تستخدم لترتيب عناصر الكائن الذي قام باستدعائها بشكل عكسي. |
أمثلة شاملة حول التعامل مع الكلاس forward_list
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من forward_list
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة 5 قيم فيه بطرق مختلفة و من ثم عرض جميع قيمه باستخدام حلقة.
ملاحظة: قمنا باستخدام الدالة assign()
لإضافة مجموعة من العناصر فيه دفعة واحدة, الدالة push_front()
لإضافة عنصر واحد في بدايته و الدالة emplace_front()
لإضافة عنصر واحد في بدايته أيضاً. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير لأننا سنتوقف عنده.
#include <iostream> #include <forward_list> using namespace std; int main() { // int يمكنه أن يحتوي على قيم نوعها forward_list هنا قمنا بتعريف كائن من الكلاس forward_list<int> myList; // assign() باستخدام الدالة myList هنا قمنا بإضافة 3 عناصر أولية في الكائن // {3, 4, 5} أصبح فيه القيم التالية myList إذاً الكائن myList.assign({3, 4, 5}); // push_front() قيمته العدد 2 باستخدام الدالة myList هنا قمنا بإضافة عنصر في أول الكائن // {2, 3, 4, 5} أصبح فيه القيم التالية myList إذاً الكائن myList.push_front(2); // emplace_front() قيمته العدد 1 باستخدام الدالة myList هنا قمنا بإضافة عنصر في أول الكائن // {1, 2, 3, 4, 5} أصبح فيه القيم التالية myList إذاً الكائن myList.emplace_front(1); cout << "List values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myList هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = myList.begin(); it != myList.end(); ++it) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
List values = 1 2 3 4 5
في المثال التالي قمنا بتعريف دالة إسمها printList()
عند استدعائها نمرر لها كائن من forward_list
فتقوم بطباعة كل قيم عناصره حتى لا نقوم بتكرار نفس الكود كلما أردنا طباعة قيم عناصر الكائن.
بعدها قمنا بتعريف كائن من forward_list
مخصص لتخزين قيم نوعها int
مع إضافة 5 قيم فيه عند تعريفه.
بعدها قمنا بعرض القيم الموجودة فيه كما هي, ثم ترتيبها من الأصغر إلى الأكبر و عرضها, ثم ترتيبها بشكل عكسي و عرضها.
ملاحظة: قمنا باستخدام الدالة sort()
لترتيب عناصر الكائن من الأصغر إلى الأكبر و الدالة reverse()
لعكس ترتيب العناصر.
#include <iostream> #include <forward_list> using namespace std; // فتقوم بطباعة القيم الموجودة فيه forward_list عند استدعائها نمرر لها كائن من printList هنا قمنا بتعريف دالة إسمها void printList(forward_list<int> &aList) { // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myList هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = aList.begin(); it != aList.end(); ++it) { cout << *it << " "; } } // main() هنا قمنا بتعريف الدالة int main() { // بالإضافة إلى أننا قمنا بإضافة 5 قيم فيه int يمكنه أن يحتوي على عناصر نوعها forward_list هنا قمنا بتعريف كائن من الكلاس forward_list<int> myList = {3, 5, 1, 4, 2}; // كما أضفناها فيه myList لعرض قيم عناصر الكائن printList() هنا قمنا باستدعاء الدالة cout << "List values\n"; printList(myList); // من الأصغر إلى الأكبر myList لترتيب قيم عناصر الكائن sort() هنا قمنا باستدعاء الدالة myList.sort(); // بعد أن قمنا بترتيبها myList لعرض قيم عناصر الكائن printList() هنا قمنا باستدعاء الدالة cout << "\n\nAfter sorting list values\n"; printList(myList); // myList لعكس ترتيب قيم عناصر الكائن sort() هنا قمنا باستدعاء الدالة myList.reverse(); // بعد أن قمنا بترتيبها myList لعرض قيم عناصر الكائن printList() هنا قمنا باستدعاء الدالة cout << "\n\nAfter reverse list values\n"; printList(myList); return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
List values 3 5 1 4 2 After sorting list values 1 2 3 4 5 After reverse list values 5 4 3 2 1
في المثال التالي قمنا بتعريف كائنين من forward_list
في كل منهما 4 عناصر من النوع نوعها int
.
بعدها قمنا بدمج الكائنين في كائن واحد حيث قمنا بنقل العناصر الموجودة في الكائن الثاني إلى الكائن الأول.
في النهاية قمنا بطباعة القيم التي أصبحت موجودة في الكائن الأول, و ما إن كان الكائن الثاني قد أصبح فارغاً أم لا.
ملاحظة: قمنا باستخدام الدالة merge()
لنقل العناصر من كائن لآخر و الدالة empty()
لمعرفة ما إن كان الكائن قد أصبح فارغاً أم لا.
#include <iostream> #include <forward_list> using namespace std; int main() { // int يحتوي كل منهما على 4 عناصر نوعها forward_list هنا قمنا بتعريف كائنين من الكلاس forward_list<int> list1 = {1, 2, 3, 4}; forward_list<int> list2 = {5, 6, 7, 8}; // list1 في آخر الكائن list2 هنا قمنا بنقل عناصر الكائن // {1, 2, 3, 4, 5, 6, 7, 8} أصبح فيه القيم التالية list1 إذاً الكائن list1.merge(list2); cout << "First list values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه list1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = list1.begin(); it != list1.end(); ++it) { cout << *it << " "; } // قد أصبح فارغاً أم لا list2 هنا قمنا بطباعة ما إن كان الكائن cout << "\nIs second list empty? " << ((list2.empty())? "Yes": "No"); return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
First list values = 1 2 3 4 5 6 7 8 Is second list empty? Yes
في المثال التالي قمنا بتعريف كائن من forward_list
مخصص لتخزين قيم نوعها int
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بإزالة العناصر الموجودة فيه و التي تملك قيم مكررة.
في الأخير قمنا بعرض القيم الموجودة فيه كما هي.
ملاحظة: قمنا باستخدام الدالة sort()
لترتيب عناصر الكائن من الأصغر إلى الأكبر و الدالة unique()
من بعدها لإبقاء نسخة واحدة فقط من العناصر التي تملك نفس القيمة.
#include <iostream> #include <forward_list> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها forward_list هنا قمنا بتعريف كائن من الكلاس forward_list<int> myList = {1, 4, 2, 4, 5, 3, 1, 5}; // من الأصغر إلى الأكبر حتى يتم وضع القيم المكررة وراء بعضها myList هنا قمنا بترتيب عناصر الكائن // {1, 1, 2, 3, 4, 4, 5, 5} أصبحت مرتبة كتالي myList إذاً عناصر الكائن myList.sort(); // myList هنا قمنا بإبقاء نسخة واحدة من كل قيمة مكررة موجودة في الكائن // {1, 2, 3, 4, 5} أصبح فيه القيم التالية myList إذاً الكائن myList.unique(); cout << "List values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myList هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = myList.begin(); it != myList.end(); ++it) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
List values = 1 2 3 4 5
في المثال التالي قمنا بتعريف كائن من forward_list
مخصص لتخزين قيم نوعها int
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بحذف أي عنصر يملك قيمة تساوي 0
و من ثم قمنا بحذف أي قيمة أكبر من 3
.
في الأخير قمنا بعرض القيم الموجودة فيه كما هي.
ملاحظة: قمنا باستخدام الدالة remove()
لحذف العناصر التي تملك قيمة محددة ألا و هي 0
و الدالة remove_if()
لحذف العناصر في حال كانت قيمتها أكبر من 3
.
#include <iostream> #include <forward_list> using namespace std; // سنستخدمها لاحقاً عند التشييك على قيم العناصر التي يجب حذفها أم لا shouldBeRemoved هنا قمنا بتعريف دالة إسمها bool shouldBeRemoved(const int& value) { // لإعلام المترجم أنه يجب حذف العنصر من الكائن الذي قام باستدعائها true هنا قلنا أن أي عنصر تكون قيمته أكبر من 3 سترجع الدالة if (value > 3) { return true; } // لإعلام المترجم أنه يجب عدم حذف العنصر من الكائن الذي قام باستدعائها false في حال لم تكن قيمة العنصر أكبر من 3 سيتم إرجاع القيمة return false; } // main() هنا قمنا بتعريف الدالة int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها forward_list هنا قمنا بتعريف كائن من الكلاس forward_list<int> myList = {1, 0, 3, 2, 0, 0, 4, 2, 5, 0, 1, 5}; // هنا قمنا بحذف كل عنصر قيمته تساوي 0 // {1, 3, 2, 4, 2, 5, 1, 5} أصبح فيه القيم التالية myList إذاً الكائن myList.remove(0); // لها shouldBeRemoved و تمرير إسم الدالة myList من الكائن remove_if() هنا قمنا باستدعاء الدالة // shouldBeRemoved لإعلام المترجم أننا نريد التشييك على قيم العناصر التي نريد حذفها من خلال الدالة // و هي من ستقرر ما إن كان يجب حذفه أم لا shouldBeRemoved سيتم تمريره للدالة myList إذاً كل عنصر في الكائن // {1, 3, 2, 2, 1} أصبح فيه القيم التالية myList إذاً الكائن myList.remove_if(shouldBeRemoved); cout << "List values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myList هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = myList.begin(); it != myList.end(); ++it) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
List values = 1 3 2 2 1
الكلاس list
في C++
تعريف الكلاس list
في C++
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض مع إعطاء كل عنصر منهم عنوان العنصر الذي يسبقه و عنوان العنصر الذي يليه في الذاكرة حتى يتم الحفاظ على الترتيب الذي تم فيه تخزينهم و لتتمكن من التنقل بين العناصر بالإتجاهين; من الأول إلى الآخر و بالعكس كالتالي.
الكائن يملك خانة أساسية يقال لها Head و هي تشير لعنوان أول عنصر موجود فيه.
العنصر الأول لا يوجد أي عنصر قبله, لهذا يكون عنوان العنصر السابق بالنسبة له يساوي
null
للإشارة إلى أنه لا يوجد عنصر قبله.العنصر الأخير لا يوجد أي عنصر بعده, لهذا يكون عنوان العنصر التالي بالنسبة له يساوي
null
للإشارة إلى أنه لا يوجد عنصر بعده.
لاستخدام الكلاس list
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<list>
لأنه موجود فيه.
template < class T, class Alloc = allocator<T> > class list;
إذاً عند إنشاء كائن من الكلاس list
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر T
.
دوال الكلاس list
في C++
الجدول التالي يحتوي على دوال الكلاس list
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator rbegin()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
|
iterator rend()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
الجدول التالي يحتوي على دوال الكلاس list
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
|
void resize(size_type n)
تستخدم لحجز مساحة للعناصر التي تنوي تخزنيها لاحقاً في الكائن الذي قام باستدعائها.عند تمرير قيمة للبارميتر n يجب أن لا تكون أصغر من عدد العناصر الموجودة في الكائن, لأنك إذا فعلت ذلك سيتم حذف العناصر التي لم يعد الكائن قادر على تخزينها.كما أنها ترمي الإستثناء bad_alloc في حال قمت بتمرير قيمة أكبر من عدد العناصر الأقصى التي يمكن تخزينها في الكائن. معلومة: هذه الدالة قد تكون مفيدة في حال أردت حجز مساحة أوليّة للعناصر قبل البدء بإضافتهم بدل جعل المترجم يفعل ذلك كلما أضفت عنصر جديد. هذه المعلومة غير مذكورة في المرجع الرسمي للغة C++ لذا قد تكون غير دقيقة. |
الجدول التالي يحتوي على دوال الكلاس list
التي تستخدم للوصول لقيم عناصره.
الدالة مع تعريفها | |
---|---|
reference front()
تستخدم للوصول لقيمة أول عنصر موجود في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.قد تسبب مشكلة في حال كان الكائن لا يملك أي عنصر, لذلك يفضل التأكد من أن الكائن غير فارغ باستخدام الدالة empty() قبل استخدامها. |
|
reference back()
تستخدم للوصول لقيمة آخر عنصر موجود في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.قد تسبب مشكلة في حال كان الكائن لا يملك أي عنصر, لذلك يفضل التأكد من أن الكائن غير فارغ باستخدام الدالة empty() قبل استخدامها. |
الجدول التالي يحتوي على دوال الكلاس list
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
void assign(initializer_list<T> aList)
تستخدم لوضع مصفوفة من العناصر بدل العناصر الموجودة في الكائن الذي قام باستدعائها.بشكل عام, يمكنك الإستفادة منها في حال أردت تخزين مجموعة من العناصر في الكائن بعد إنشائه. مكان الباراميتر aList نمرر مصفوفة من العناصر التي تحتوي على قيم من نفس نوع الكائن الذي قام باستدعائها. |
|
void emplace_front(T& val)
تستخدم لإضافة عنصر في بداية الكائن الذي قام باستدعائها.مكان الباراميتر val نمرر العنصر الذي نريد إضافته في أول الكائن الذي قام باستدعائها. |
|
void push_front(T& val)
تستخدم لإضافة عنصر في بداية الكائن الذي قام باستدعائها تماماً كالدالة emplace_front() .مكان الباراميتر val نمرر العنصر الذي نريد إضافته في أول الكائن الذي قام باستدعائها. |
|
void pop_front()
تستخدم لحذف أول عنصر موجود في الكائن الذي قام باستدعائها. |
|
void emplace_back(T& val)
تستخدم لإضافة عنصر في آخر الكائن الذي قام باستدعائها.مكان الباراميتر val نمرر العنصر الذي نريد إضافته في آخر الكائن الذي قام باستدعائها. |
|
void push_back(T& val)
تستخدم لإضافة عنصر في آخر الكائن الذي قام باستدعائها تماماً كالدالة emplace_back() .مكان الباراميتر val نمرر العنصر الذي نريد إضافته في أول الكائن الذي قام باستدعائها. |
|
void pop_back()
تستخدم لحذف آخر عنصر موجود في الكائن الذي قام باستدعائها. |
|
iterator insert(const_iterator position, T& val)
تستخدم لإضافة عنصر جديد في مكان محدد - أي عند عنوان محدد - في الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان المكان الذي سيتم إضافة العنصر عنده في الذاكرة.مكان الباراميتر val نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.كما أنها ترجع كائن أصله من Iterator يمثل عنوان العنصر الذي تم إضافته. |
|
iterator erase(const_iterator position)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه. |
|
iterator erase(const_iterator first, const_iterator last)
تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها.مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده. |
|
void swap(list& anotherList)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherList نمرر لها كائن من الكلاس list يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
|
iterator splice(const_iterator position, list& anotherList)
تستخدم لإضافة عناصر كائن من list في مكان محدد في الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يمثل عنوان العنصر الذي سيتم إضافة عناصر الكائن anotherList إبتداءاً من عنده.مكان الباراميتر anotherList نمرر الكائن الذي نريد نسخ عناصره و الذي يجب أن تكون عناصره من نفس نوع عناصر الكائن الذي قام باستدعائها. |
|
void remove(const T& val)
تستخدم لحذف جميع العناصر الموجودة في الكائن الذي قام باستدعائها في حال كانت قيمتها تساوي القيمة التي نمررها لها مكان الباراميتر val . |
|
void remove_if(Predicate pred)
تستخدم هذه الدالة لحذف عناصر من الكائن الذي قام باستدعائها في حال كانت قيمه تطابق الشرط الذي نقوم بتمريره لها مكان الباراميتر pred .الباراميتر pred الذي يجب أن نمرره لها سيكون عبارة عن دالة ترجع true في حال كان يجب حذف العنصر و false في حال لم يكن يجب ذلك. |
|
void unique()
تستخدم لحذف القيم المكررة من الكائن الذي قام باستدعائها.بمعنى آخر, تقوم بحذف أي قيمة تجدها متكررة فيه و تترك نسخة واحدة منها. معلومة: عند استخدام هذه الدالة يجب أن تكون القيم المكررة مرتبة وراء بعضها البعض و لفعل هذا الأمر قم فقط باستدعاء الدالة sort() من الكائن قبل استدعاء هذه الدالة. |
|
void merge(list& anotherList)
تستخدم لنقل عناصر كائن من list في آخر الكائن الذي قام باستدعائها.عند نقل عناصر الكائن anotherList إلى الكائن الذي قام باستدعائها يصبح فارغاً. |
|
void sort()
تستخدم لترتيب عناصر الكائن الذي قام باستدعائها من الأصغر إلى الأكبر. |
|
void reverse()
تستخدم لترتيب عناصر الكائن الذي قام باستدعائها بشكل عكسي. |
أمثلة شاملة حول التعامل مع الكلاس list
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من list
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة 7 قيم فيه بطرق مختلفة و من ثم عرض جميع قيمه باستخدام حلقة.
ملاحظة: قمنا باستخدام الدالة assign()
لإضافة مجموعة من العناصر فيه دفعة واحدة, الدالة push_front()
لإضافة عنصر واحد في بدايته و الدالة emplace_front()
لإضافة عنصر واحد في بدايته أيضاً, الدالة push_back()
لإضافة عنصر واحد في آخره و الدالة emplace_back()
لإضافة عنصر واحد في آخره أيضاً. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير لأننا سنتوقف عنده.
#include <iostream> #include <list> using namespace std; int main() { // int يمكنه أن يحتوي على قيم نوعها list هنا قمنا بتعريف كائن من الكلاس list<int> myList; // assign() باستخدام الدالة myList هنا قمنا بإضافة 3 عناصر أولية في الكائن // {3, 4, 5} أصبح فيه القيم التالية myList إذاً الكائن myList.assign({3, 4, 5}); // push_front() قيمته العدد 2 باستخدام الدالة myList هنا قمنا بإضافة عنصر في أول الكائن // {2, 3, 4, 5} أصبح فيه القيم التالية myList إذاً الكائن myList.push_front(2); // emplace_front() قيمته العدد 1 باستخدام الدالة myList هنا قمنا بإضافة عنصر في أول الكائن // {1, 2, 3, 4, 5} أصبح فيه القيم التالية myList إذاً الكائن myList.emplace_front(1); // push_back() قيمته العدد 6 باستخدام الدالة myList هنا قمنا بإضافة عنصر في آخر الكائن // {1, 2, 3, 4, 5, 6} أصبح فيه القيم التالية myList إذاً الكائن myList.push_back(6); // emplace_back() قيمته العدد 7 باستخدام الدالة myList هنا قمنا بإضافة عنصر في آخر الكائن // {1, 2, 3, 4, 5, 6, 7} أصبح فيه القيم التالية myList إذاً الكائن myList.emplace_back(7); cout << "List values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myList هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = myList.begin(); it != myList.end(); ++it) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
List values = 1 2 3 4 5 6 7
في المثال التالي قمنا بتعريف دالة إسمها printList()
عند استدعائها نمرر لها كائن من list
فتقوم بطباعة كل قيم عناصره حتى لا نقوم بتكرار نفس الكود كلما أردنا طباعة قيم عناصر الكائن.
بعدها قمنا بتعريف كائن من list
مخصص لتخزين قيم نوعها int
مع إضافة 5 قيم فيه عند تعريفه.
بعدها قمنا بعرض القيم الموجودة فيه كما هي, ثم ترتيبها من الأصغر إلى الأكبر و عرضها, ثم ترتيبها بشكل عكسي و عرضها.
ملاحظة: قمنا باستخدام الدالة sort()
لترتيب عناصر الكائن من الأصغر إلى الأكبر و الدالة reverse()
لعكس ترتيب العناصر.
#include <iostream> #include <list> using namespace std; // فتقوم بطباعة القيم الموجودة فيه list عند استدعائها نمرر لها كائن من printList هنا قمنا بتعريف دالة إسمها void printList(list<int> &aList) { // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myList هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = aList.begin(); it != aList.end(); ++it) { cout << *it << " "; } } // main() هنا قمنا بتعريف الدالة int main() { // بالإضافة إلى أننا قمنا بإضافة 5 قيم فيه int يمكنه أن يحتوي على عناصر نوعها list هنا قمنا بتعريف كائن من الكلاس list<int> myList = {3, 5, 1, 4, 2}; // كما أضفناها فيه myList لعرض قيم عناصر الكائن printList() هنا قمنا باستدعاء الدالة cout << "List values\n"; printList(myList); // من الأصغر إلى الأكبر myList لترتيب قيم عناصر الكائن sort() هنا قمنا باستدعاء الدالة myList.sort(); // بعد أن قمنا بترتيبها myList لعرض قيم عناصر الكائن printList() هنا قمنا باستدعاء الدالة cout << "\n\nAfter sorting list values\n"; printList(myList); // myList لعكس ترتيب قيم عناصر الكائن sort() هنا قمنا باستدعاء الدالة myList.reverse(); // بعد أن قمنا بترتيبها myList لعرض قيم عناصر الكائن printList() هنا قمنا باستدعاء الدالة cout << "\n\nAfter reverse list values\n"; printList(myList); return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
List values 3 5 1 4 2 After sorting list values 1 2 3 4 5 After reverse list values 5 4 3 2 1
في المثال التالي قمنا بتعريف كائنين من list
في كل منهما 4 عناصر من النوع نوعها int
.
بعدها قمنا بدمج الكائنين في كائن واحد حيث قمنا بنقل العناصر الموجودة في الكائن الثاني إلى الكائن الأول.
في النهاية قمنا بطباعة القيم التي أصبحت موجودة في الكائن الأول, و ما إن كان الكائن الثاني قد أصبح فارغاً أم لا.
ملاحظة: قمنا باستخدام الدالة merge()
لنقل العناصر من كائن لآخر و الدالة empty()
لمعرفة ما إن كان الكائن قد أصبح فارغاً أم لا.
#include <iostream> #include <list> using namespace std; int main() { // int يحتوي كل منهما على 4 عناصر نوعها list هنا قمنا بتعريف كائنين من الكلاس list<int> list1 = {1, 2, 3, 4}; list<int> list2 = {5, 6, 7, 8}; // list1 في آخر الكائن list2 هنا قمنا بنقل عناصر الكائن // {1, 2, 3, 4, 5, 6, 7, 8} أصبح فيه القيم التالية list1 إذاً الكائن list1.merge(list2); cout << "First list values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه list1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = list1.begin(); it != list1.end(); ++it) { cout << *it << " "; } // قد أصبح فارغاً أم لا list2 هنا قمنا بطباعة ما إن كان الكائن cout << "\nIs second list empty? " << ((list2.empty())? "Yes": "No"); return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
First list values = 1 2 3 4 5 6 7 8 Is second list empty? Yes
في المثال التالي قمنا بتعريف كائن من list
مخصص لتخزين قيم نوعها int
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بإزالة العناصر الموجودة فيه و التي تملك قيم مكررة.
في الأخير قمنا بعرض القيم الموجودة فيه كما هي.
ملاحظة: قمنا باستخدام الدالة sort()
لترتيب عناصر الكائن من الأصغر إلى الأكبر و الدالة unique()
من بعدها لإبقاء نسخة واحدة فقط من العناصر التي تملك نفس القيمة.
#include <iostream> #include <list> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها list هنا قمنا بتعريف كائن من الكلاس list<int> myList = {1, 4, 2, 4, 5, 3, 1, 5}; // من الأصغر إلى الأكبر حتى يتم وضع القيم المكررة وراء بعضها myList هنا قمنا بترتيب عناصر الكائن // {1, 1, 2, 3, 4, 4, 5, 5} أصبحت مرتبة كتالي myList إذاً عناصر الكائن myList.sort(); // myList هنا قمنا بإبقاء نسخة واحدة من كل قيمة مكررة موجودة في الكائن // {1, 2, 3, 4, 5} أصبح فيه القيم التالية myList إذاً الكائن myList.unique(); cout << "List values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myList هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = myList.begin(); it != myList.end(); ++it) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
List values = 1 2 3 4 5
في المثال التالي قمنا بتعريف كائن من list
مخصص لتخزين قيم نوعها int
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بحذف أي عنصر يملك قيمة تساوي 0
و من ثم قمنا بحذف أي قيمة أكبر من 3
.
في الأخير قمنا بعرض القيم الموجودة فيه كما هي.
ملاحظة: قمنا باستخدام الدالة remove()
لحذف العناصر التي تملك قيمة محددة ألا و هي 0
و الدالة remove_if()
لحذف العناصر في حال كانت قيمتها أكبر من 3
.
#include <iostream> #include <list> using namespace std; // سنستخدمها لاحقاً عند التشييك على قيم العناصر التي يجب حذفها أم لا shouldBeRemoved هنا قمنا بتعريف دالة إسمها bool shouldBeRemoved(const int& value) { // لإعلام المترجم أنه يجب حذف العنصر من الكائن الذي قام باستدعائها true هنا قلنا أن أي عنصر تكون قيمته أكبر من 3 سترجع الدالة if (value > 3) { return true; } // لإعلام المترجم أنه يجب عدم حذف العنصر من الكائن الذي قام باستدعائها false في حال لم تكن قيمة العنصر أكبر من 3 سيتم إرجاع القيمة return false; } // main() هنا قمنا بتعريف الدالة int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها list هنا قمنا بتعريف كائن من الكلاس list<int> myList = {1, 0, 3, 2, 0, 0, 4, 2, 5, 0, 1, 5}; // هنا قمنا بحذف كل عنصر قيمته تساوي 0 // {1, 3, 2, 4, 2, 5, 1, 5} أصبح فيه القيم التالية myList إذاً الكائن myList.remove(0); // لها shouldBeRemoved و تمرير إسم الدالة myList من الكائن remove_if() هنا قمنا باستدعاء الدالة // shouldBeRemoved لإعلام المترجم أننا نريد التشييك على قيم العناصر التي نريد حذفها من خلال الدالة // و هي من ستقرر ما إن كان يجب حذفه أم لا shouldBeRemoved سيتم تمريره للدالة myList إذاً كل عنصر في الكائن // {1, 3, 2, 2, 1} أصبح فيه القيم التالية myList إذاً الكائن myList.remove_if(shouldBeRemoved); cout << "List values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myList هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = myList.begin(); it != myList.end(); ++it) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
List values = 1 3 2 2 1
في المثال التالي قمنا بتعريف كائن من list
مخصص لتخزين قيم نوعها int
مع إضافة 5 قيم فيه عند تعريفه.
بعدها قمنا بإزالة أول و آخر عنصر موجود فيه.
في الأخير قمنا بعرض القيم الموجودة فيه بشكل عكسي, أي من العنصر الأخير إلى العنصر الأول.
ملاحظة: قمنا باستخدام الدالة pop_front()
لحذف عنصر من أول الكائن, الدالة pop_back()
لحذف عنصر من آخر الكائن. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة rbegin()
للحصول على مؤشر للعنصر الأخير لأننا سنبدأ من عنده و الدالة rend()
للحصول على مؤشر للعنصر الأول لأننا سنتوقف عنده.
#include <iostream> #include <list> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة 5 قيم فيه int يمكنه أن يحتوي على عناصر نوعها list هنا قمنا بتعريف كائن من الكلاس list<int> myList = {1, 2, 3, 4, 5}; // pop_front() بواسطة الدالة myList هنا قمنا بحذف العنصر الأول من الكائن // {2, 3, 4, 5} أصبح فيه القيم التالية myList إذاً الكائن myList.pop_front(); // pop_back() بواسطة الدالة myList هنا قمنا بحذف العنصر الأخير من الكائن // {2, 3, 4} أصبح فيه القيم التالية myList إذاً الكائن myList.pop_back(); cout << "List values in descending order = "; // إبتداءاً من آخر عنصر وصولاً لأول عنصر فيه myList هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = myList.rbegin(); it != myList.rend(); ++it) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
List values in descending order = 4 3 2
الكلاس stack
في C++
تعريف الكلاس stack
في C++
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل فوق بعضها البعض مما يجعلك قادر فقط على التعامل مع العنصر الموجود في أعلاها.
طريقة تخزين العناصر في هذه الحاوية تعتمد أسلوب LIFO الذي هو اختصار لجملة Last In First out و التي تعني أن العنصر الأخير الذي يتم إضافته في الحاوية هو أول عنصر يمكن إخراجه منها كالتالي.
لاستخدام الكلاس stack
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<stack>
لأنه موجود فيه.
template < class T, class Alloc = allocator<T> > class stack;
إذاً عند إنشاء كائن من الكلاس stack
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر T
.
دوال الكلاس stack
في C++
الجدول التالي يحتوي على جميع دوال الكلاس stack
.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
reference& top()
تستخدم لتغيير قيمة العنصر الموجود في أعلى الكائن الذي قام باستدعائها أو للحصول على قيمته. |
|
void push(T& val)
تستخدم لإضافة عنصر جديد في أعلى الكائن الذي قام باستدعائها.مكان الباراميتر val نمرر العنصر الذي نريد إضافته. |
|
void emplace(T& val)
تستخدم لإضافة عنصر جديد في أعلى الكائن الذي قام باستدعائها تماماً كالدالة push() .مكان الباراميتر val نمرر العنصر الذي نريد إضافته. |
|
void pop()
تستخدم لحذف أعلى عنصر موجود في الكائن الذي قام باستدعائها. |
|
void swap(stack& anotherStack)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherStack نمرر لها كائن من الكلاس stack يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
أمثلة شاملة حول التعامل مع الكلاس stack
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من stack
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة بعض العناصر فيه و من ثم طباعة عدد العناصر التي قمنا بإضافتها.
بعدها قمنا بعرض جميع القيم الموجودة فيه من خلال حلقة تستمر في التنفيذ طالما أن الكائن غير فارغ; في كل دورة في الحلقة كنا نقوم بعرض قيمة العنصر الموجود في الأعلى و من ثم نحذفه حتى نتمكن من الوصول للعنصر الموجود بعده مباشرةً.
ملاحظة: قمنا باستخدام الدالة push()
لإضافة العناصر, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها, الدالة top()
للحصول على قيمة العنصر الموجود في أعلى الكائن في كل مرة, الدالة pop()
لحذف العنصر الموجود في أعلى الكائن و الدالة empty()
لمعرفة ما إن كان الكائن يحتوي على عناصر بعد أم لا.
#include <iostream> #include <stack> using namespace std; int main() { // int يمكنه أن يحتوي على قيم نوعها stack هنا قمنا بتعريف كائن من الكلاس stack<int> myStack; // push() باستخدام الدالة myStack هنا قمنا بإضافة 5 عناصر في الكائن myStack.push(1); myStack.push(2); myStack.push(3); myStack.push(4); myStack.push(5); // size() باستخدام الدالة myStack هنا قمنا بطباعة عدد عناصر الكائن cout << "Stack size = " << myStack.size() << endl; cout << "Popping out stack elements:"; // لا يزال يحتوي على عناصر myStack هنا قمنا بإنشاء حلقة تستمر في تنفيذ الأوامر الموجودة فيها طالما أن الكائن // بعدها سيتم حذفه مباشرةً ,myStack في كل دورة من دورات الحلقة سيتم طباعة قيمة العنصر الموجود في أعلى الكائن while (!myStack.empty()) { cout << " " << myStack.top(); myStack.pop(); } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Stack size = 5 Popping out stack elements: 5 4 3 2 1
في المثال التالي قمنا بتعريف كائنين من stack
مع تحديد أنه يمكن أن يحتويان على عناصر نوعها int
.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة القيم التي أصبحت موجودة في كلٍّ منهما.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل قيمهما.
#include <iostream> #include <stack> using namespace std; int main() { // int يمكنهما أن يحتويان على قيم نوعها stack هنا قمنا بتعريف كائنين من الكلاس stack<int> stack1; stack<int> stack2; // push() باستخدام الدالة stack1 هنا قمنا بإضافة 4 عناصر في الكائن stack1.push(1); stack1.push(2); stack1.push(3); stack1.push(4); // push() باستخدام الدالة stack2 هنا قمنا بإضافة 4 عناصر في الكائن stack2.push(5); stack2.push(6); stack2.push(7); stack2.push(8); // stack2 مع قيم الكائن stack1 هنا قمنا بتبديل قيم الكائن stack1.swap(stack2); cout << "Popping out stack1 elements:"; // لا يزال يحتوي على عناصر stack1 هنا قمنا بإنشاء حلقة تستمر في تنفيذ الأوامر الموجودة فيها طالما أن الكائن // بعدها سيتم حذفه مباشرةً ,stack1 في كل دورة من دورات الحلقة سيتم طباعة قيمة العنصر الموجود في أعلى الكائن while (!stack1.empty()) { cout << " " << stack1.top(); stack1.pop(); } cout << "\nPopping out stack2 elements:"; // لا يزال يحتوي على عناصر stack2 هنا قمنا بإنشاء حلقة تستمر في تنفيذ الأوامر الموجودة فيها طالما أن الكائن // بعدها سيتم حذفه مباشرةً ,stack2 في كل دورة من دورات الحلقة سيتم طباعة قيمة العنصر الموجود في أعلى الكائن while (!stack2.empty()) { cout << " " << stack2.top(); stack2.pop(); } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Popping out stack1 elements: 8 7 6 5 Popping out stack2 elements: 4 3 2 1
الكلاس queue
في C++
تعريف الكلاس queue
في C++
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض و كأنها موضوعة في نفق يمكن السير فيه باتجاه واحد, حيث أن العنصر يضاف فيها من جهة يمكن و من ثم يمكن إخراجه منها من الجهة المقابلة.
طريقة تخزين العناصر في هذه الحاوية تعتمد أسلوب FIFO الذي هو اختصار لجملة First In First out و التي تعني أن أول عنصر يتم إضافته في الحاوية هو أول عنصر يمكن إخراجه منها و كأنه يوجد جهة يتم منها إضافة العناصر و جهة يمكن إسترجاعها منها كالتالي.
لاستخدام الكلاس queue
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<queue>
لأنه موجود فيه.
template < class T, class Alloc = allocator<T> > class queue;
إذاً عند إنشاء كائن من الكلاس queue
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر T
.
دوال الكلاس queue
في C++
الجدول التالي يحتوي على جميع دوال الكلاس queue
.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
reference& front()
تستخدم لتغيير قيمة العنصر الأقدم في الكائن الذي قام باستدعائها أو للحصول على قيمته. |
|
reference& back()
تستخدم لتغيير قيمة العنصر الأحدث في الكائن الذي قام باستدعائها أو للحصول على قيمته. |
|
void push(T& val)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها.مكان الباراميتر val نمرر العنصر الذي نريد إضافته. |
|
void emplace(T& val)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها تماماً كالدالة push() .مكان الباراميتر val نمرر العنصر الذي نريد إضافته. |
|
void pop()
تستخدم لحذف العنصر الأقدم من الكائن الذي قام باستدعائها. |
|
void swap(queue& anotherQueue)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherQueue نمرر لها كائن من الكلاس queue يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
أمثلة شاملة حول التعامل مع الكلاس queue
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من queue
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة بعض العناصر فيه و من ثم طباعة عدد العناصر التي قمنا بإضافتها, قيمة أقدم عنصر و قيمة أحدث عنصر.
ملاحظة: قمنا باستخدام الدالة push()
لإضافة العناصر, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها, الدالة front()
للحصول على قيمة العنصر الأقدم في الكائن و الدالة back()
للحصول على قيمة العنصر الأحدث فيه.
#include <iostream> #include <queue> using namespace std; int main() { // int يمكنه أن يحتوي على قيم نوعها queue هنا قمنا بتعريف كائن من الكلاس queue<int> myQueue; // push() باستخدام الدالة myQueue هنا قمنا بإضافة 5 عناصر في الكائن myQueue.push(1); myQueue.push(2); myQueue.push(3); myQueue.push(4); myQueue.push(5); // size() باستخدام الدالة myQueue هنا قمنا بطباعة عدد عناصر الكائن cout << "Stack size = " << myQueue.size() << endl; // هنا قمنا بطباعة القيمة العنصر الأقدم في الكائن, أي قيمة أول عنصر تم إضافته فيه cout << "Oldest value = " << myQueue.front() << endl; // هنا قمنا بطباعة القيمة العنسر الأحدث في الكائن, أي قيمة آخر عنصر تم إضافته فيه cout << "Newest value = " << myQueue.back(); return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Stack size = 5 Oldest value = 1 Newest value = 5
في المثال التالي قمنا بتعريف كائن من queue
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة بعض العناصر فيه و من ثم قمنا بعرض جميع القيم الموجودة فيه من خلال حلقة تستمر في التنفيذ طالما أن الكائن غير فارغ; في كل دورة في الحلقة كنا نقوم بعرض قيمة العنصر الأقدم فيه و من ثم نحذفه حتى نتمكن من الوصول للعنصر الموجود خلفه مباشرةً.
ملاحظة: قمنا باستخدام الدالة push()
لإضافة العناصر, الدالة front()
للحصول على قيمة العنصر الأقدم في الكائن في كل مرة, الدالة pop()
لحذف العنصر الأقدم في الكائن و الدالة empty()
لمعرفة ما إن كان الكائن يحتوي على عناصر بعد أم لا.
#include <iostream> #include <queue> using namespace std; int main() { // int يمكنه أن يحتوي على قيم نوعها queue هنا قمنا بتعريف كائن من الكلاس queue<int> myQueue; // push() باستخدام الدالة myQueue هنا قمنا بإضافة 5 عناصر في الكائن myQueue.push(1); myQueue.push(2); myQueue.push(3); myQueue.push(4); myQueue.push(5); cout << "Popping out queue elements:"; // لا يزال يحتوي على عناصر myQueue هنا قمنا بإنشاء حلقة تستمر في تنفيذ الأوامر الموجودة في فيها طالما أن الكائن // بعدها سيتم حذفه مباشرةً ,myQueue في كل دورة من دورات الحلقة سيتم طباعة قيمة العنصر الموجود في أعلى الكائن while (!myQueue.empty()) { cout << " " << myQueue.front(); myQueue.pop(); } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Popping out queue elements: 1 2 3 4 5
في المثال التالي قمنا بتعريف كائنين من queue
مع تحديد أنه يمكن أن يحتويان على عناصر نوعها int
.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة القيم التي أصبحت موجودة في كلٍّ منهما.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل قيمهما.
#include <iostream> #include <queue> using namespace std; int main() { // int يمكنهما أن يحتويان على قيم نوعها queue هنا قمنا بتعريف كائنين من الكلاس queue<int> queue1; queue<int> queue2; // push() باستخدام الدالة queue1 هنا قمنا بإضافة 4 عناصر في الكائن queue1.push(1); queue1.push(2); queue1.push(3); queue1.push(4); // push() باستخدام الدالة queue2 هنا قمنا بإضافة 4 عناصر في الكائن queue2.push(5); queue2.push(6); queue2.push(7); queue2.push(8); // queue2 مع قيم الكائن queue1 هنا قمنا بتبديل قيم الكائن queue1.swap(queue2); cout << "Popping out queue1 elements:"; // لا يزال يحتوي على عناصر queue1 هنا قمنا بإنشاء حلقة تستمر في تنفيذ الأوامر الموجودة في فيها طالما أن الكائن // بعدها سيتم حذفه مباشرةً ,queue1 في كل دورة من دورات الحلقة سيتم طباعة قيمة العنصر الموجود في أعلى الكائن while (!queue1.empty()) { cout << " " << queue1.front(); queue1.pop(); } cout << "\nPopping out queue2 elements:"; // لا يزال يحتوي على عناصر queue2 هنا قمنا بإنشاء حلقة تستمر في تنفيذ الأوامر الموجودة في فيها طالما أن الكائن // بعدها سيتم حذفه مباشرةً ,queue2 في كل دورة من دورات الحلقة سيتم طباعة قيمة العنصر الموجود في أعلى الكائن while (!queue2.empty()) { cout << " " << queue2.front(); queue2.pop(); } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Popping out queue1 elements: 5 6 7 8 Popping out queue2 elements: 1 2 3 4
الكلاس priority_queue
في C++
تعريف الكلاس priority_queue
في C++
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض و بترتيب معين حيث يتم وضع العنصر الذي يملك القيمة الأكبر في البداية و العنصر الذي يملك القيمة الأصغر في النهاية, بالإضافة إلى أنه يسمح لك بالوصول لأعلى و أدنى قيمة فقط لأنها موجودة على أطراف الحاوية مع إمكانية حذف القيمة الأدنى منها فقط كالتالي.
الآن, عليك معرفة أنه بإمكانك تخصيص الطريقة التي يتم فيها ترتيب العناصر حتى تتناسب مع أنواع العناصر التي ستقوم بتخزينها لأنك على الأغلب لن تتعامل مع عناصر قيمتها int
فقط. كمثال بسيط قد تكون العناصر التي تريد تخزينها عبارة كائنات من كلاس إسمه Product
يمثل منتج, هنا يكون كل منتج يملك عدة معلومات مثل إسمه و سعره و تاريخ إنتاجه. في هذه الحالة يمكنك تخصيص الطريقة التي سيتم فيها ترتيب العناصر فمثلاً يمكنك جعل العناصر (التي تمثل منتجات) يتم ترتيبها على أساس أسعار المنتجات.
لاستخدام الكلاس priority_queue
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<queue>
لأنه موجود فيه.
template < class T, class Alloc = allocator<T> > class priority_queue;
إذاً عند إنشاء كائن من الكلاس priority_queue
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر T
.
دوال الكلاس priority_queue
في C++
الجدول التالي يحتوي على جميع دوال الكلاس priority_queue
.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
reference& top()
تستخدم لتغيير قيمة العنصر الموجود في آخر الكائن الذي قام باستدعائها أو للحصول على قيمته. |
|
void push(T& val)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها.مكان الباراميتر val نمرر العنصر الذي نريد إضافته. |
|
void emplace(T& val)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها تماماً كالدالة push() .مكان الباراميتر val نمرر العنصر الذي نريد إضافته. |
|
void pop()
تستخدم لحذف آخر عنصر موجود في الكائن الذي قام باستدعائها. |
|
void swap(priority_queue& anotherPriorityQueue)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherPriorityQueue نمرر لها كائن من الكلاس priority_queue يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
أمثلة شاملة حول التعامل مع الكلاس priority_queue
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من priority_queue
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة بعض العناصر فيه و من ثم طباعة عدد العناصر التي قمنا بإضافتها.
بعدها قمنا بعرض جميع القيم الموجودة فيه من خلال حلقة تستمر في التنفيذ طالما أن الكائن غير فارغ; في كل دورة في الحلقة كنا نقوم بعرض قيمة العنصر الموجود في الأعلى و من ثم نحذفه حتى نتمكن من الوصول للعنصر الموجود بعده مباشرةً.
ملاحظة: قمنا باستخدام الدالة push()
لإضافة العناصر, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها, الدالة top()
للحصول على قيمة العنصر الموجود في أعلى الكائن في كل مرة, الدالة pop()
لحذف العنصر الموجود في أعلى الكائن و الدالة empty()
لمعرفة ما إن كان الكائن يحتوي على عناصر بعد أم لا.
#include <iostream> #include <queue> using namespace std; int main() { // int يمكنه أن يحتوي على قيم نوعها priority_queue هنا قمنا بتعريف كائن من الكلاس priority_queue<int> pq; // push() باستخدام الدالة pq هنا قمنا بإضافة 5 عناصر في الكائن // {5, 4, 3, 2, 1} العناصر سيتم ترتيبها بشكل تلقائي من الأكبر إلى الأصغر كالتالي pq.push(3); pq.push(1); pq.push(2); pq.push(5); pq.push(4); // size() باستخدام الدالة pq هنا قمنا بطباعة عدد عناصر الكائن cout << "pq size = " << pq.size() << endl; cout << "Popping out pq elements:"; // لا يزال يحتوي على عناصر pq هنا قمنا بإنشاء حلقة تستمر في تنفيذ الأوامر الموجودة فيها طالما أن الكائن // بعدها سيتم حذفه مباشرةً ,pq في كل دورة من دورات الحلقة سيتم طباعة قيمة العنصر الموجود في آخر الكائن while (!pq.empty()) { cout << " " << pq.top(); pq.pop(); } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
pq size = 5 Popping out pq elements: 5 4 3 2 1
في المثال التالي قمنا بتعريف كائن من priority_queue
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها string
.
إذاً في هذا الكائن سيكون كل كائن عبارة عن نص مما يعني أنه سيتم ترتيب أماكن العناصر على حسب عدد الأحرف الموجودة فيها. العنصر الذي يملك عدد أحرف أكبر سيتم وضعه بالأول.
بعدها قمنا بعرض جميع القيم الموجودة فيه بواسطة حلقة.
#include <iostream> #include <queue> using namespace std; int main() { // string يمكنه أن يحتوي على قيم نوعها priority_queue هنا قمنا بتعريف كائن من الكلاس priority_queue<string> pq; // push() باستخدام الدالة pq هنا قمنا بإضافة 5 عناصر في الكائن // {Strawberry, Blueberry, Banana, Apple} العناصر سيتم ترتيبها بشكل تلقائي من الأكبر إلى الأصغر كالتالي pq.push("Apple"); pq.push("Banana"); pq.push("Blueberry"); pq.push("Strawberry"); cout << "Popping out pq elements:"; // لا يزال يحتوي على عناصر pq هنا قمنا بإنشاء حلقة تستمر في تنفيذ الأوامر الموجودة فيها طالما أن الكائن // بعدها سيتم حذفه مباشرةً ,pq في كل دورة من دورات الحلقة سيتم طباعة قيمة العنصر الموجود في آخر الكائن while (!pq.empty()) { cout << " " << pq.top(); pq.pop(); } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Popping out pq elements: Strawberry Blueberry Banana Apple
في المثال التالي قمنا بتعريف كائنين من priority_queue
مع تحديد أنه يمكن أن يحتويان على عناصر نوعها int
.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة القيم التي أصبحت موجودة في كلٍّ منهما.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل قيمهما.
#include <iostream> #include <queue> using namespace std; int main() { // int يمكنهما أن يحتويان على قيم نوعها priority_queue هنا قمنا بتعريف كائنين من الكلاس priority_queue<int> pq1; priority_queue<int> pq2; // push() باستخدام الدالة pq1 هنا قمنا بإضافة 4 عناصر في الكائن // {4, 3, 2, 1} العناصر سيتم ترتيبها بشكل تلقائي من الأكبر إلى الأصغر كالتالي pq1.push(3); pq1.push(1); pq1.push(4); pq1.push(2); // push() باستخدام الدالة pq2 هنا قمنا بإضافة 4 عناصر في الكائن // {8, 7, 6, 5} العناصر سيتم ترتيبها بشكل تلقائي من الأكبر إلى الأصغر كالتالي pq2.push(5); pq2.push(6); pq2.push(8); pq2.push(7); // pq2 مع قيم الكائن pq1 هنا قمنا بتبديل قيم الكائن pq1.swap(pq2); cout << "Popping out pq1 elements:"; // لا يزال يحتوي على عناصر pq1 هنا قمنا بإنشاء حلقة تستمر في تنفيذ الأوامر الموجودة فيها طالما أن الكائن // بعدها سيتم حذفه مباشرةً ,pq1 في كل دورة من دورات الحلقة سيتم طباعة قيمة العنصر الموجود في آخر الكائن while (!pq1.empty()) { cout << " " << pq1.top(); pq1.pop(); } cout << "\nPopping out pq2 elements:"; // لا يزال يحتوي على عناصر pq2 هنا قمنا بإنشاء حلقة تستمر في تنفيذ الأوامر الموجودة فيها طالما أن الكائن // بعدها سيتم حذفه مباشرةً ,pq2 في كل دورة من دورات الحلقة سيتم طباعة قيمة العنصر الموجود في آخر الكائن while (!pq2.empty()) { cout << " " << pq2.top(); pq2.pop(); } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Popping out pq1 elements: 8 7 6 5 Popping out pq2 elements: 4 3 2 1
في المثال التالي قمنا بتخصيص الطريقة التي سيقوم فيها الكائن الذي ننشئه من الكلاس priority_queue
حتى يتناسب مع نوع العناصر التي سنقوم بتخزينها فيه.
في البداية قمنا بتعريف كلاس إسمه Book
يمثل الشكل العام لأي كتاب و هو يحتوي على خاصيّتين و هما إسم الكتاب title
و سعره price
.
بعدها قمنا بإنشاء كلاس إسمه Compare
سنستخدمه لنحدد الطريقة التي سيتم على أساسها ترتيب قيم العناصر.
في هذا الكلاس قمنا بإنشاء عامل ( Operator ) يملك باراميترين نوعهما Book
لأن فكرة هذا العامل أنه يقارن أي عنصر جديد ( عبارة عن كائن من Book
) نقوم بإضافته مع أول عنصر موجود في الكائن. لذا الباراميتر الأول يعتبر العنصر الأول الموجود في الكائن و الباراميتر الثاني يعتبر العنصر الجديد الذي سيتم إضافته.
على هذا الأساس قمنا بتحديد أنه في حال كانت قيمة price
في الباراميتر الأول أكبر من قيمة price
في الباراميتر الثاني سيتم وضع العنصر الذي تم تمريره في الباراميتر الأول في بداية الكائن.
في الأخير قمنا بإنشاء ثلاث كائنات من الكلاس Book
لأنها ستكون بمثابة العناصر التي سنقوم بتخزينها في الحاوية.
و من ثم قمنا بإنشاء كائن من priority_queue
مع تحديد أنه سيتم تخزين عناصر نوعها Book
فيه و أنه سيستخدم العامل الموجود في الكلاس Compare
حتى يرتب العناصر التي نضيفها فيه و من بعدها أضفنا العناصر فيه, ثم قمنا بعرضها بواسطة حلقة.
#include <iostream> #include <queue> using namespace std; // Book هنا قمنا بتعريف الكلاس class Book { public: // هنا قمنا بتعريف خصائص الكلاس string title; double price; // هنا قمنا بتعريف كونستكتور للكلاس حتى نستطيع تمرير قيم للخصائص بشكل مباشر عند إنشاء كائن منه Book(string title, double price) { this->title = title; this->price = price; } }; // priority_queue و الذي سنستخدمه لاحقاً لتحديد كيف ستترتب العناصر في الحاوية التي ننشئها من الكلاس Compare هنا قمنا بتعريف الكلاس class Compare { public: // price حتى يقارن قيمة priority_queue هنا قمنا بتعريف العامل الذي سيستخدمه الكائن الذي ننشئه من الكلاس // الموجودة في أول عنصر فيها price في الكائن الذي سيتم إضافته في الحاوية مع قيمة bool operator() (Book b1, Book b2) { // الموجودة في العنصر الجديد أكبر من price هنا كأننا نعلم المترجم بأنه في حال كانت قيمة // الموجودة في العنصر الأول في الحاوية, فإننا نريد وضعها هي في البداية price قيمة return (b1.price > b2.price); } }; // main() هنا قمنا بتعريف الدالة int main() { // بالإضافة إلى Book يمكنه أن يحتوي على كائنات من الكلاس priority_queue هنا قمنا بتعريف كائن من الكلاس // من أجل تحديد الطريقة التي سيتم فيها ترتيب الكائنات التي نضيفها فيه Compare أنه يعتمد على الكلاس priority_queue<Book, vector<Book>, Compare> pq; // pq لأننا سنضعها كعناصر في الحاوية Book هنا قمنا بإنشاء 3 كائنات من الكلاس Book book1("C++ for beginner", 18); Book book2("HTML5 for dummies", 12); Book book3("Building Android apps", 25); // push() باستخدام الدالة pq في الكائن book3, book2 و book1 هنا قمنا بإضافة الكائنات // {book3, book1, book2} فيها كالتالي price العناصر سيتم ترتيبها من الأكبر إلى الأصغر على حسب قيمة الخاصية pq.push(book1); pq.push(book2); pq.push(book3); cout << "Popping out stored Books:\n"; // لا يزال يحتوي على عناصر pq هنا قمنا بإنشاء حلقة تستمر في تنفيذ الأوامر الموجودة فيها طالما أن الكائن // بعدها سيتم حذفه مباشرةً ,pq في كل دورة من دورات الحلقة سيتم طباعة قيم العنصر الموجود في آخر الكائن while (!pq.empty()) { cout << "- " << pq.top().title << " [" << pq.top().price << "$]\n"; pq.pop(); } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Popping out stored Books: - HTML5 for dummies [12$] - C++ for beginner [18$] - Building Android apps [25$]
الكلاس deque
في C++
تعريف الكلاس deque
في C++
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل مع إعطاء كل عنصر منهم رقم Index مما يجعلك قادر على الوصول إلى جميع عناصرها و إضافة عناصر جديدة في أي مكان فيها, و يميز هذه الحاوية بأنك قادر على التعامل مع العناصر الموجودة على أطرافها بشكل مباشر كالتالي.
لاستخدام الكلاس deque
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<queue>
لأنه موجود فيه.
template < class T, class Alloc = allocator<T> > class deque
إذاً عند إنشاء كائن من الكلاس deque
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر T
.
دوال الكلاس deque
في C++
الجدول التالي يحتوي على دوال الكلاس deque
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الجهة اليسرى في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر في الجهة اليسرى و الوقوف عند آخر عنصر في الجهة اليمنى. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر بالنسبة للجهة اليسرى في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر في الجهة اليسرى و الوقوف عند آخر عنصر في الجهة اليمنى. |
|
iterator rbegin()
ترجع كائن iterator يشير لمكان أول عنصر في الجهة اليمنى في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من أول عنصر في الجهة اليمنى و الوقوف عند آخر عنصر في الجهة اليسرى. |
|
iterator rend()
ترجع كائن iterator يشير لمكان آخر عنصر بالنسبة للجهة اليمنى في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر في الجهة اليمنى و الوقوف عند آخر عنصر في الجهة اليسرى. |
الجدول التالي يحتوي على دوال الكلاس deque
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
|
void resize(size_type n)
تستخدم لحجز مساحة للعناصر التي تنوي تخزينها لاحقاً في الكائن الذي قام باستدعائها.عند تمرير قيمة للبارميتر n يجب أن لا تكون أصغر من عدد العناصر الموجودة في الكائن, لأنك إذا فعلت ذلك سيتم حذف العناصر التي لم يعد الكائن قادر على تخزينها.كما أنها ترمي الإستثناء bad_alloc في حال قمت بتمرير قيمة أكبر من عدد العناصر الأقصى التي يمكن تخزينها في الكائن. معلومة: هذه الدالة قد تكون مفيدة في حال أردت حجز مساحة أوليّة للعناصر قبل البدء بإضافتهم بدل جعل المترجم يفعل ذلك كلما أضفت عنصر جديد. هذه المعلومة غير مذكورة في المرجع الرسمي للغة C++ لذا قد تكون غير دقيقة. |
|
void shrink_to_fit()
تستخدم للتخلي عن أي مساحة زيادة مخصصة في الذاكرة للكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس deque
التي تستخدم للوصول لقيم عناصره.
الدالة مع تعريفها | |
---|---|
T at(size_t n)
تستخدم للوصول لقيمة عنصر محدد في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.مكان الباراميتر n نمرر لها رقم يمثل index العنصر الذي نريد الوصول إليه.ترمي الإستثناء out_of_range في حال كانت قيمة n أصغر من 0 أو أكبر من عدد العناصر الموجودة.معلومة: يمكنك استخدام العامل [] للوصول للعنصر و لكن عليك معرفة أن استخدام هذا العامل لا يرمي إستثناء في حال تمرير index غير موجود في الكائن. |
|
T front()
تستخدم للوصول لقيمة أول عنصر موجود في الجهة اليسرى في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.قد تسبب مشكلة في حال كان الكائن لا يملك أي عنصر, لذلك يفضل التأكد من أن الكائن غير فارغ باستخدام الدالة empty() قبل استخدامها. |
|
T back()
تستخدم للوصول لقيمة أول عنصر موجود في الجهة اليمنى في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.قد تسبب مشكلة في حال كان الكائن لا يملك أي عنصر, لذلك يفضل التأكد من أن الكائن غير فارغ باستخدام الدالة empty() قبل استخدامها. |
|
T* data()
ترجع مؤشر لقيمة أول عنصر موجود في الجهة اليسرى في الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس deque
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
void assign(size_t n, const T& val)
تستخدم لإضافة عدة عناصر في الكائن الذي قام باستدعائها و هي تحذف أي عناصر أخرى موجودة فيه في حال لم يكن فارغاً.مكان الباراميتر n نمرر عدد العناصر التي نريد إضافتها في الكائن الذي قام باستدعائها.مكان الباراميتر val نمرر القيمة التي نريد وضعها للعناصر التي سيتم إضافتها في الكائن الذي قام باستدعائها. |
|
void push_back(T& val)
تستخدم لإضافة عنصر جديد في آخر الكائن الذي قام باستدعائها, أي لإضافته في الجهة اليمنى.مكان الباراميتر val نمرر العنصر الذي نريد إضافته. |
|
void emplace_back(T& val)
تستخدم لإضافة عنصر جديد في آخر الكائن الذي قام باستدعائها تماماً كالدالة push_back() .مكان الباراميتر val نمرر العنصر الذي نريد إضافته. |
|
void push_front(T& val)
تستخدم لإضافة عنصر جديد في أول الكائن الذي قام باستدعائها, أي لإضافته في الجهة اليسرى.مكان الباراميتر val نمرر العنصر الذي نريد إضافته. |
|
void emplace_front(T& val)
تستخدم لإضافة عنصر جديد في أول الكائن الذي قام باستدعائها تماماً كالدالة push_front() .مكان الباراميتر val نمرر العنصر الذي نريد إضافته. |
|
void pop_back()
تستخدم لحذف آخر عنصر موجود في الكائن الذي قام باستدعائها, أي لحذف أول عنصر من الجهة اليمنى. |
|
void pop_front()
تستخدم لحذف أول عنصر موجود في الكائن الذي قام باستدعائها, أي لحذف أول عنصر من الجهة اليسرى. |
|
iterator insert(const_iterator position, T& val)
تستخدم لإضافة عنصر جديد في مكان محدد - أي عند رقم Index محدد - في الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان المكان الذي سيتم إضافة العنصر عنده في الذاكرة.مكان الباراميتر val نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.كما أنها ترجع كائن أصله من Iterator يمثل عنوان العنصر الذي تم إضافته. |
|
void clear()
تستخدم لحذف جميع العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
iterator erase(const_iterator position)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه. |
|
iterator erase(const_iterator first, const_iterator last)
تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها.مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده. |
|
void swap(deque& anotherDeque)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherDeque نمرر لها كائن من الكلاس deque يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
أمثلة شاملة حول التعامل مع الكلاس deque
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من list
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة 7 قيم فيه بطرق مختلفة و من ثم عرض جميع قيمه باستخدام حلقة.
ملاحظة: قمنا باستخدام الدالة assign()
لإضافة مجموعة من العناصر فيه دفعة واحدة, الدالة push_front()
لإضافة عنصر واحد في بدايته و الدالة emplace_front()
لإضافة عنصر واحد في بدايته أيضاً, الدالة push_back()
لإضافة عنصر واحد في آخره و الدالة emplace_back()
لإضافة عنصر واحد في آخره أيضاً.
#include <iostream> #include <queue> using namespace std; int main() { // int يمكنه أن يحتوي على قيم نوعها deque هنا قمنا بتعريف كائن من الكلاس deque<int> myDeque; // assign() باستخدام الدالة myDeque هنا قمنا بإضافة 3 عناصر أولية في الكائن // {3, 4, 5} أصبح فيه القيم التالية myDeque إذاً الكائن myDeque.assign({3, 4, 5}); // push_front() قيمته العدد 2 باستخدام الدالة myDeque هنا قمنا بإضافة عنصر في أول الكائن // {2, 3, 4, 5} أصبح فيه القيم التالية myDeque إذاً الكائن myDeque.push_front(2); // emplace_front() قيمته العدد 1 باستخدام الدالة myDeque هنا قمنا بإضافة عنصر في أول الكائن // {1, 2, 3, 4, 5} أصبح فيه القيم التالية myDeque إذاً الكائن myDeque.emplace_front(1); // push_back() قيمته العدد 6 باستخدام الدالة myDeque هنا قمنا بإضافة عنصر في آخر الكائن // {1, 2, 3, 4, 5, 6} أصبح فيه القيم التالية myDeque إذاً الكائن myDeque.push_back(6); // emplace_back() قيمته العدد 7 باستخدام الدالة myDeque هنا قمنا بإضافة عنصر في آخر الكائن // {1, 2, 3, 4, 5, 6, 7} أصبح فيه القيم التالية myDeque إذاً الكائن myDeque.emplace_back(7); cout << "Deque values = "; // myDeque هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(size_t i=0; i<myDeque.size(); i++) { cout << myDeque[i] << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Deque values = 1 2 3 4 5 6 7
في المثال التالي قمنا بتعريف كائن من deque
أدخلنا فيه 5 عناصر نصية.
بعدها قمنا بإضافة 5 قيم فيه و من ثم عرض عدد جميع عناصره, عدد جميع العناصر التي يمكن إضافتها فيه, بالإضافة لأول و آخر قيمة موجودة فيه.
ملاحظة: قمنا باستخدام الدالة size()
لمعرفة عدد العناصر التي تم إضافتها, الدالة max_size()
لمعرفة أكبر عدد عناصر يمكن إضافتها فيه, الدالة empty()
لمعرفة ما إن كانت المصفوفة فارغة أم لا, الدالة front()
للحصول على قيمة أول عنصر و الدالة back()
للحصول على قيمة آخر عنصر.
#include <iostream> #include <queue> using namespace std; int main() { // string يمكنه أن يحتوي على 5 قيم نوعها deque هنا قمنا بتعريف كائن من الكلاس deque<string> myDeque; // push_back() باستخدام الدالة myDeque هنا قمنا بإضافة 5 عناصر في الكائن myDeque.push_back("One"); myDeque.push_back("Two"); myDeque.push_back("Three"); myDeque.push_back("Four"); myDeque.push_back("Five"); // size() باستخدام الدالة myDeque هنا قمنا بطباعة عدد عناصر الكائن cout << "Deque size = " << myDeque.size() << endl; // max_size() باستخدام الدالة myDeque هنا قمنا بطباعة عدد العناصر الأقصى التي يمكن تخزينها في الكائن cout << "Deque max size = " << myDeque.max_size() << endl; // و إن لم يكن فارغاً سيتم طباعة أول و آخر قيمة فيه empty() باستخدام الدالة myDeque هنا قمنا بالتشييك على عدد عناصر الكائن if (!myDeque.empty()) { cout << "Deque first element value = " << myDeque.front() << endl; cout << "Deque last element value = " << myDeque.back(); } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Deque size = 5 Deque max size = 576460752303423487 Deque first element value = One Deque last element value = Five
في المثال التالي قمنا بتعريف كائن من deque
مخصص لتخزين قيم نوعها int
مع إضافة 9 قيم فيه عند تعريفه.
بعدها قمنا بحذف عدة عناصر منه بطرق مختلفة و من ثم طباعة قيم العناصر المتبقية.
ملاحظة: قمنا باستخدام الدالة pop_back()
لحذف آخر عنصر من الكائن, الدالة erase()
لحذف عنصر واحد, الدالة erase()
مرة ثانية لحذف أكثر من عنصر في وقت واحد و الدالة begin()
للحصول على عدّاد يمكن من خلاله تحديد مكان العناصر التي سيتم حذفها.
#include <iostream> #include <queue> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة 9 قيم فيه int يمكنه أن يحتوي على عناصر نوعها deque هنا قمنا بتعريف كائن من الكلاس deque<int> myDeque = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // myDeque هنا قمنا بحذف آخر عنصر موجود في الكائن // {1, 2, 3, 4, 5, 6, 7, 8} أصبح فيه القيم التالية myDeque إذاً الكائن myDeque.pop_back(); // myDeque يساوي 2 في الكائن index هنا قمنا بحذف العنصر الذي يملك // {1, 2, 4, 5, 6, 7, 8} أصبح فيه القيم التالية myDeque إذاً الكائن myDeque.erase(myDeque.begin() + 2); // يساوي 1 وصولاً إلى index إبتداءاً من العنصر الذي يملك myDeque هنا قمنا بحذف العناصر الموجودة في الكائن // {1, 6, 7, 8} أصبح فيه القيم التالية myDeque يساوي 4. و بالتالي الكائن index ما قبل العنصر الذي يملك myDeque.erase(myDeque.begin() + 1, myDeque.begin() + 4); cout << "Deque values = "; // myDeque هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(size_t i=0; i<myDeque.size(); i++) { cout << myDeque[i] << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Deque values = 1 6 7 8
في المثال التالي قمنا بتعريف كائن من deque
مخصص لتخزين قيم نوعها int
مع إضافة 5 قيم فيه عند تعريفه.
بعدها قمنا بعرض جميع عناصرها مرتين, مرة من أول عنصر لآخر عنصر, و مرة من آخر عنصر لأول عنصر.
ملاحظة: عند البدء من أول عنصر لآخر عنصر, قمنا باستخدام الدالة begin()
للحصول على عدّاد يمكن من خلاله البدئ من العنصر الأول و الدالة end()
للحصول على قيمة العدّاد التي من خلالها نعرف أننا وصلنا لآخر عنصر.
و عند البدء من آخر عنصر لأول عنصر, قمنا باستخدام الدالة rbegin()
للحصول على عدّاد يمكن من خلاله البدئ من آخر عنصر و الدالة rend()
للحصول على قيمة العدّاد التي من خلالها نعرف أننا وصلنا لأول عنصر بدون الحاجة لتغيير شكل الحلقة التي استخدمناها في المرة الأولى.
#include <iostream> #include <queue> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة 5 قيم فيه int يمكنه أن يحتوي على عناصر نوعها deque هنا قمنا بتعريف كائن من الكلاس deque<int> myDeque = {1, 2, 3, 4, 5}; cout << "Deque values from begin to end = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myDeque هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(auto it=myDeque.begin(); it<myDeque.end(); it++) { cout << *it << " "; } cout << "\nDeque values from end to begin = "; // إبتداءاً من آخر عنصر وصولاً لأول عنصر فيه myDeque هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(auto it=myDeque.rbegin(); it<myDeque.rend(); it++) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Deque values from begin to end = 1 2 3 4 5 Deque values from end to begin = 5 4 3 2 1
في المثال التالي قمنا بتعريف كائن من deque
مخصص لتخزين قيم نوعها int
مع إضافة 5 قيم فيه عند تعريفه.
بعدها قمنا بتغيير قيم العناصر الموجودة على أطرافه, أي قيمة العنصر الأول و الأخير.
في الأخير قمنا بعرض جميع قيمه باستخدام حلقة.
ملاحظة: قمنا باستخدام الدالة front()
لتغيير قيمة العنصر الأول و الدالة back()
لتغيير قيمة العنصر الأخير.
#include <iostream> #include <queue> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة 5 قيم فيه int يمكنه أن يحتوي على عناصر نوعها deque هنا قمنا بتعريف كائن من الكلاس deque<int> myDeque = {1, 2, 3, 4, 5}; // إلى 11 myDeque هنا قمنا بتغيير قيمة العنصر الأول في الكائن myDeque.front() = 11; // إلى 55 myDeque هنا قمنا بتغيير قيمة العنصر الأخير في الكائن myDeque.back() = 55; cout << "Deque values = "; // myDeque هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(size_t i=0; i<myDeque.size(); i++) { cout << myDeque[i] << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Deque values = 11 2 3 4 55
في المثال التالي قمنا بتعريف كائن من deque
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة 5 قيم فيه وراء بعضها.
بعدها قمنا بإضافة قيمة في مكان محدد فيه.
في الأخير قمنا بعرض جميع قيمه باستخدام حلقة.
ملاحظة: قمنا باستخدام الدالة insert()
لإضافة القيمة في مكان محدد في الكائن.
#include <iostream> #include <queue> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة 5 قيم فيه int يمكنه أن يحتوي على عناصر نوعها deque هنا قمنا بتعريف كائن من الكلاس deque<int> myDeque = {1, 2, 3, 4, 5}; // myDeque رقم 2 بالنسبة للكائن index هنا قمنا بإضافة القيمة 8 في الـ // {1, 2, 8, 3, 4, 5} أصبح فيه القيم التالية myDeque إذاً الكائن myDeque.insert(myDeque.begin() + 2, 8); cout << "Deque values = "; // myDeque هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for(size_t i=0; i<myDeque.size(); i++) { cout << myDeque[i] << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Deque values = 1 2 8 3 4 5
الكلاس set
في C++
تعريف الكلاس set
في C++
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض و بترتيب معين حيث يتم وضع العنصر الذي يملك القيمة الأصغر في البداية و العنصر الذي يملك القيمة الأكبر في النهاية أو العكس, مع الإشارة إلى أنه لا يمكن تخزين قيم مكررة فيها كالتالي.
الآن, عليك معرفة أن العناصر الموجودة في هذه الحاوية لا يمكن تعديل قيمها لأن ترتيب أماكن عناصرها يتم على أساس قيمها.
في حال أردت تعديل قيمة عنصر, فيجب أن تحذفه من الحاوية و تقوم بإجراء تعديل عليه و من بعدها تقوم بإضافته فيها من جديد.
كما أنك تستطيع تخصيص الطريقة التي يتم فيها ترتيب العناصر حتى تتناسب مع أنواع العناصر التي ستقوم بتخزينها لأنك على الأغلب لن تتعامل مع عناصر قيمتها int
فقط. كمثال بسيط قد تكون العناصر التي تريد تخزينها عبارة كائنات من كلاس إسمه Product
يمثل منتج, هنا يكون كل منتج يملك عدة معلومات مثل إسمه, رقم التعرفة الخاص به, سعره و تاريخ إنتاجه. في هذه الحالة يمكنك تخصيص الطريقة التي سيتم فيها ترتيب العناصر فمثلاً يمكنك جعل العناصر (التي تمثل منتجات) يتم ترتيبها على أساس رقم التعرفة الخاص بكل منتج.
لاستخدام الكلاس set
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<set>
لأنه موجود فيه.
template < class T, // set::key_type/value_type class Compare = less<T>, // set::key_compare/value_compare class Alloc = allocator<T> // set::allocator_type > class set;
إذاً عند إنشاء كائن من الكلاس set
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر T
.
دوال الكلاس set
في C++
الجدول التالي يحتوي على دوال الكلاس set
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator rbegin()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
|
iterator rend()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
الجدول التالي يحتوي على دوال الكلاس set
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس set
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
iterator insert(const_iterator position, T& val)
تستخدم لإضافة عنصر جديد في مكان محدد - أي عند عنوان محدد - في الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان المكان الذي سيتم إضافة العنصر عنده في الذاكرة.مكان الباراميتر val نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.كما أنها ترجع كائن أصله من Iterator يمثل عنوان العنصر الذي تم إضافته. |
|
iterator erase(const_iterator position)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه. |
|
iterator erase(const_iterator first, const_iterator last)
تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها.مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده. |
|
void swap(set& anotherSet)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherSet نمرر لها كائن من الكلاس set يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
|
void emplace(T& val)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس set
التي تستخدم للبحث فيه.
الدالة مع تعريفها | |
---|---|
size_t count(T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن عنصر يملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع القيمة 1 و في حال لم يتم إيجاد عنصر يملك نفس القيمة ترجع القيمة 0 . |
|
iterator find(const T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن عنصر يملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator يشير لعنوان العنصر في الذاكرة.و في حال لم يتم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator قيمته تساوي القيمة التي ترجعها الدالة end() . |
أمثلة شاملة حول التعامل مع الكلاس set
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من set
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة بعض العناصر فيه و من ثم طباعة عدد العناصر التي قمنا بإضافتها.
بعدها قمنا بعرض جميع قيم العناصر الموجودة فيه بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة emplace()
لإضافة العناصر, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير لأننا سنتوقف عنده.
#include <iostream> #include <set> using namespace std; int main() { // int يمكنه أن يحتوي على قيم نوعها set هنا قمنا بتعريف كائن من الكلاس set<int> mySet; // مع الإشارة إلى أننا تعمدنا إدخال نفس القيمة أكثر من مرة emplace() باستخدام الدالة mySet هنا حاولنا إضافة 7 عناصر في الكائن // العناصر التي أضفناها سيتم ترتيبها بشكل تلقائي من الأصغر إلى الأكبر كالتالي {5, 4, 3, 2, 1} و ستلاحظ ذلك لاحقاً عند عرض قيمهم mySet.emplace(3); mySet.emplace(1); mySet.emplace(5); mySet.emplace(2); mySet.emplace(5); // بما أنه يوجد القيمة 5 مسبقاً, لن يتم إضافتها من جديد mySet.emplace(4); mySet.emplace(1); // بما أنه يوجد القيمة 1 مسبقاً, لن يتم إضافتها من جديد // size() باستخدام الدالة mySet هنا قمنا بطباعة عدد عناصر الكائن cout << "mySet size = " << mySet.size() << endl; cout << "mySet values ="; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه mySet هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = mySet.begin(); it != mySet.end(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
mySet size = 5 mySet values = 1 2 3 4 5
في المثال التالي قمنا بتعريف كائن من set
مخصص لتخزين قيم نوعها int
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بعرض القيم الموجودة فيه بواسطة حلقة بشكل عكسي, أي من الآخر إلى الأول.
ملاحظة: قمنا باستخدام الدالة rbegin()
للحصول على مؤشر للعنصر الأخير لأننا سنبدأ من عنده و الدالة rend()
للحصول على مؤشر للعنصر الأول لأننا سنتوقف عنده.
#include <iostream> #include <set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها set هنا قمنا بتعريف كائن من الكلاس // العناصر التي أضفناها سيتم ترتيبها بشكل تلقائي من الأصغر إلى الأكبر كالتالي {5, 4, 3, 2, 1} و ستلاحظ ذلك لاحقاً عند عرض قيمهم set<int> mySet = {1, 4, 2, 4, 5, 3, 1, 5}; cout << "mySet values ="; // إبتداءاً من آخر عنصر وصولاً لأول عنصر فيه mySet هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = mySet.rbegin(); it != mySet.rend(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
mySet values = 5 4 3 2 1
في المثال التالي قمنا بتعريف كائن من set
مخصص لتخزين قيم نوعها int
بشكل تنازلي (أي من الأكبر إلى الأصغر) مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بعرض القيم الموجودة فيه بواسطة حلقة.
المثال الثالث
#include <iostream> #include <set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها set هنا قمنا بتعريف كائن من الكلاس // من أجل ترتيب القيم greater قيم هذا الكائن سيتم ترتيبها من الأكبر إلى الأصغر و سبب ذلك أننا جعلناه يعتمد على الكلاس // العناصر التي أضفناها سيتم ترتيبها بشكل تلقائي كالتالي {5, 4, 3, 2, 1} و ستلاحظ ذلك لاحقاً عند عرض قيمهم set<int, greater<int>> mySet = {1, 4, 2, 4, 5, 3, 1, 5}; cout << "mySet values ="; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه mySet هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = mySet.begin(); it != mySet.end(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
mySet values = 5 4 3 2 1
في المثال التالي قمنا بتعريف كائن من set
مخصص لتخزين قيم نوعها int
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بالبحث عن قيمة محددة فيه لمعرفة ما إن كانت موجودة فيه أم لا.
ملاحظة: قمنا باستخدام الدالة count()
للبحث عن القيمة في الكائن.
#include <iostream> #include <set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها set هنا قمنا بتعريف كائن من الكلاس set<int> mySet = {1, 2, 3, 4, 5}; // يوجد فيه عنصر قيمته تساوي 4 mySet هنا قمنا بطباعة ما إن كان الكائن if (mySet.count(4)) { // إن كان فيه سيتم تنفيذ أمر الطباعة التالي cout << "4 is exist in myset"; } else { // إن لم يكن فيه سيتم تنفيذ أمر الطباعة التالي cout << "4 is not exist in myset"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
4 is exist in myset
في المثال التالي قمنا بتعريف كائن من set
مخصص لتخزين قيم نوعها int
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بالبحث عن قيمة محددة فيه و في حال كانت موجودة سنقوم بحذف العنصر الذي يملكها من الكائن.
ملاحظة: قمنا باستخدام الدالة find()
للبحث عن القيمة في الكائن و الدالة erase()
لحذف العنصر من الكائن.
#include <iostream> #include <set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها set هنا قمنا بتعريف كائن من الكلاس set<int> mySet = {1, 2, 3, 4, 5}; // لتخزين مكان العنصر الذي نجد القيمة التي نبحث عنها فيه set<int>::iterator منا قمنا بتعريف كائن من set<int>::iterator it; // it عن عنصر يملك القيمة 4, و بالتالي في حال وجود عنصر يملك القيمة 4 سيتم تخزين عنوانه في الكائن mySet هنا قمنا بالبحث في الكائن // فيه للإشارة إلى أنه لم يتم إيجاد أي عنصر يملك هذه القيمة mySet.end() في حال عدم وجود عنصر يملك القيمة 4 سيتم تخزين القيمة التي ترجعها it = mySet.find(4); // فهذا يعني أنه تم إيجاد القيمة و بالتالي سيتم تنفيذ الكود الموضوع فيها mySet.end() لا تساوي القيمة التي ترجعها الدالة it في حال كانت قيمة if (it != mySet.end()) { // و من ثم قمنا بحذفه mySet هنا قمنا بطباعة قيمة العنصر الذي تم إيجاده في الكائن cout << "element with value '"<< *it << "' is removed from mySet\n"; mySet.erase(it); } cout << "mySet values ="; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه mySet هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = mySet.begin(); it != mySet.end(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
element with value '4' is removed from mySet mySet values = 1 2 3 5
في المثال التالي قمنا بتعريف كائنين من set
مع تحديد أنه يمكن أن يحتويان على عناصر نوعها int
.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة القيم التي أصبحت موجودة في كلٍّ منهما.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل قيمهما.
#include <iostream> #include <set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيهما int يمكنهما أن يحتويان على قيم نوعها set هنا قمنا بتعريف كائنين من الكلاس set<int> set1 = {1, 2, 3, 4}; set<int> set2 = {5, 6, 7, 8}; // set2 مع قيم الكائن set1 هنا قمنا بتبديل قيم الكائن set1.swap(set2); cout << "set1 values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه set1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = set1.begin(); it != set1.end(); ++it) { cout << *it << " "; } cout << "\nset2 values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه set2 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = set2.begin(); it != set2.end(); ++it) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
set1 values = 5 6 7 8 set2 values = 1 2 3 4
في المثال التالي قمنا بتخصيص الطريقة التي سيقوم فيها الكائن الذي ننشئه من الكلاس set
حتى يتناسب مع نوع العناصر التي سنقوم بتخزينها فيه.
في البداية قمنا بتعريف كلاس إسمه Book
يمثل الشكل العام لأي كتاب و هو يحتوي على خاصيّتين و هما إسم الكتاب title
و رقم التعرفة id
الخاص به.
بعدها قمنا بإنشاء كلاس إسمه Compare
سنستخدمه لنحدد الطريقة التي سيتم على أساسها ترتيب قيم العناصر.
في هذا الكلاس قمنا بإنشاء عامل ( Operator ) يملك باراميترين نوعهما Book
لأن فكرة هذا العامل أنه يقارن أي عنصر جديد ( عبارة عن كائن من Book
) نقوم بإضافته مع أول عنصر موجود في الكائن. لذا الباراميتر الأول يعتبر العنصر الأول الموجود في الكائن و الباراميتر الثاني يعتبر العنصر الجديد الذي سيتم إضافته.
على هذا الأساس قمنا بتحديد أنه في حال كانت قيمة id
في الباراميتر الأول أصغر من قيمة id
في الباراميتر الثاني سيتم وضع العنصر الذي تم تمريره في الباراميتر الأول في بداية الكائن.
في الأخير قمنا بإنشاء ثلاث كائنات من الكلاس Book
لأنها ستكون بمثابة العناصر التي سنقوم بتخزينها في الحاوية.
و من ثم قمنا بإنشاء كائن من set
مع تحديد أنه سيتم تخزين عناصر نوعها Book
فيه و أنه سيستخدم العامل الموجود في الكلاس Compare
حتى يرتب العناصر التي نضيفها فيه و من بعدها أضفنا العناصر فيه, ثم قمنا بعرضها بواسطة حلقة.
ملاحظة: قمنا باستخدام الحلقة Foreach عند عرض قيم العناصر.
#include <iostream> #include <set> using namespace std; // Book هنا قمنا بتعريف الكلاس class Book { public: // هنا قمنا بتعريف خصائص الكلاس int id; string title; // هنا قمنا بتعريف كونستكتور للكلاس حتى نستطيع تمرير قيم للخصائص بشكل مباشر عند إنشاء كائن منه Book(int id, string title) { this->id = id; this->title = title; } }; // set و الذي سنستخدمه لاحقاً لتحديد كيف ستترتب العناصر في الحاوية التي ننشئها من الكلاس Compare هنا قمنا بتعريف الكلاس class Compare { public: // id حتى يقارن قيمة set هنا قمنا بتعريف العامل الذي سيستخدمه الكائن الذي ننشئه من الكلاس // الموجودة في أول عنصر فيها id في الكائن الذي سيتم إضافته في الحاوية مع قيمة bool operator() (Book b1, Book b2) { // الموجودة في العنصر الجديد أصغر من id هنا كأننا نعلم المترجم بأنه في حال كانت قيمة // الموجودة في العنصر الأول في الحاوية, فإننا نريد وضعها هي في البداية id قيمة return (b1.id < b2.id); } }; // main() هنا قمنا بتعريف الدالة int main() { // بالإضافة إلى Book يمكنه أن يحتوي على كائنات من الكلاس set هنا قمنا بتعريف كائن من الكلاس // من أجل تحديد الطريقة التي سيتم فيها ترتيب الكائنات التي نضيفها فيه Compare أنه يعتمد على الكلاس set<Book, Compare> mySet; // mySet لأننا سنضعها كعناصر في الحاوية Book هنا قمنا بإنشاء 3 كائنات من الكلاس Book book1(2, "C++ for beginner"); Book book2(1, "HTML5 for dummies"); Book book3(3, "Building Android apps"); // emplace() باستخدام الدالة mySet في الكائن book3, book2 و book1 هنا قمنا بإضافة الكائنات // {book2, book1, book3} فيها كالتالي id العناصر سيتم ترتيبها من الأسغر إلى الأكبر على حسب قيمة الخاصية mySet.emplace(book1); mySet.emplace(book2); mySet.emplace(book3); cout << "All books in mySet:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه mySet هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto const &e: mySet) { cout << e.id << " - " << e.title << endl; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
All books in mySet: 1 - HTML5 for dummies 2 - C++ for beginner 3 - Building Android apps
الكلاس multiset
في C++
تعريف الكلاس multiset
في C++
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل متسلسل وراء بعضها البعض و بترتيب معين حيث يتم وضع العنصر الذي يملك القيمة الأصغر في البداية و العنصر الذي يملك القيمة الأكبر في النهاية أو العكس, مع الإشارة إلى أنه يمكن تخزين قيم مكررة فيها كالتالي.
الآن, عليك معرفة أن العناصر الموجودة في هذه الحاوية لا يمكن تعديل قيمها لأن ترتيب أماكن عناصرها يتم على أساس قيمها.
في حال أردت تعديل قيمة عنصر, فيجب أن تحذفه من الحاوية و تقوم بإجراء تعديل عليه و من بعدها تقوم بإضافته فيها من جديد.
كما أنك تستطيع تخصيص الطريقة التي يتم فيها ترتيب العناصر حتى تتناسب مع أنواع العناصر التي ستقوم بتخزينها لأنك على الأغلب لن تتعامل مع عناصر قيمتها int
فقط. كمثال بسيط قد تكون العناصر التي تريد تخزينها عبارة كائنات من كلاس إسمه Product
يمثل منتج, هنا يكون كل منتج يملك عدة معلومات مثل إسمه, رقم التعرفة الخاص به, سعره و تاريخ إنتاجه. في هذه الحالة يمكنك تخصيص الطريقة التي سيتم فيها ترتيب العناصر فمثلاً يمكنك جعل العناصر (التي تمثل منتجات) يتم ترتيبها على أساس رقم التعرفة الخاص بكل منتج.
لاستخدام الكلاس multiset
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<set>
لأنه موجود فيه.
template < class T, // multiset::key_type/value_type class Compare = less<T>, // multiset::key_compare/value_compare class Alloc = allocator<T> // multiset::allocator_type > class multiset;
إذاً عند إنشاء كائن من الكلاس multiset
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر T
.
دوال الكلاس multiset
في C++
الجدول التالي يحتوي على دوال الكلاس multiset
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator rbegin()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
|
iterator rend()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
الجدول التالي يحتوي على دوال الكلاس multiset
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس multiset
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
iterator insert(const_iterator position, T& val)
تستخدم لإضافة عنصر جديد في مكان محدد - أي عند عنوان محدد - في الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان المكان الذي سيتم إضافة العنصر عنده في الذاكرة.مكان الباراميتر val نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.كما أنها ترجع كائن أصله من Iterator يمثل عنوان العنصر الذي تم إضافته. |
|
iterator erase(const_iterator position)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه. |
|
iterator erase(const_iterator first, const_iterator last)
تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها.مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده. |
|
void swap(multiset& anotherSet)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherSet نمرر لها كائن من الكلاس multiset يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
|
void emplace(T& val)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس multiset
التي تستخدم للبحث فيه.
الدالة مع تعريفها | |
---|---|
size_t count(T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن عدد العناصر التي تملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها. |
|
iterator find(const T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن أول عنصر يملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator يشير لعنوان العنصر في الذاكرة.و في حال لم يتم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator قيمته تساوي القيمة التي ترجعها الدالة end() . |
أمثلة شاملة حول التعامل مع الكلاس multiset
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من multiset
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها int
.
بعدها قمنا بإضافة بعض العناصر فيه و من ثم طباعة عدد العناصر التي قمنا بإضافتها.
بعدها قمنا بعرض جميع قيم العناصر الموجودة فيه بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة emplace()
لإضافة العناصر, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير لأننا سنتوقف عنده.
#include <iostream> #include <set> using namespace std; int main() { // int يمكنه أن يحتوي على قيم نوعها multiset هنا قمنا بتعريف كائن من الكلاس multiset<int> myMultiset; // مع الإشارة إلى أننا تعمدنا إدخال نفس القيمة أكثر من مرة emplace() باستخدام الدالة myMultiset هنا قمنا بإضافة 7 عناصر في الكائن // العناصر التي أضفناها سيتم ترتيبها بشكل تلقائي من الأصغر إلى الأكبر كالتالي {5, 5, 4, 3, 2, 1, 1} و ستلاحظ ذلك لاحقاً عند عرض قيمهم myMultiset.emplace(3); myMultiset.emplace(1); myMultiset.emplace(5); myMultiset.emplace(2); myMultiset.emplace(5); myMultiset.emplace(4); myMultiset.emplace(1); // size() باستخدام الدالة myMultiset هنا قمنا بطباعة عدد عناصر الكائن cout << "myMultiset size = " << myMultiset.size() << endl; cout << "myMultiset values ="; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMultiset هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMultiset.begin(); it != myMultiset.end(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
myMultiset size = 7 myMultiset values = 1 1 2 3 4 5 5
في المثال التالي قمنا بتعريف كائن من multiset
مخصص لتخزين قيم نوعها int
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بعرض القيم الموجودة فيه بواسطة حلقة بشكل عكسي, أي من الآخر إلى الأول.
ملاحظة: قمنا باستخدام الدالة rbegin()
للحصول على مؤشر للعنصر الأخير لأننا سنبدأ من عنده و الدالة rend()
للحصول على مؤشر للعنصر الأول لأننا سنتوقف عنده.
#include <iostream> #include <set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها multiset هنا قمنا بتعريف كائن من الكلاس // العناصر التي أضفناها سيتم ترتيبها بشكل تلقائي من الأصغر إلى الأكبر كالتالي {5, 4, 3, 2, 1} و ستلاحظ ذلك لاحقاً عند عرض قيمهم multiset<int> myMultiset = {1, 4, 2, 5, 3}; cout << "myMultiset values ="; // إبتداءاً من آخر عنصر وصولاً لأول عنصر فيه myMultiset هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMultiset.rbegin(); it != myMultiset.rend(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
myMultiset values = 5 4 3 2 1
في المثال التالي قمنا بتعريف كائن من multiset
مخصص لتخزين قيم نوعها int
بشكل تنازلي (أي من الأكبر إلى الأصغر) مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بعرض القيم الموجودة فيه بواسطة حلقة.
#include <iostream> #include <set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها multiset هنا قمنا بتعريف كائن من الكلاس // من أجل ترتيب القيم greater قيم هذا الكائن سيتم ترتيبها من الأكبر إلى الأصغر و سبب ذلك أننا جعلناه يعتمد على الكلاس // العناصر التي أضفناها سيتم ترتيبها بشكل تلقائي كالتالي {5, 4, 3, 2, 1} و ستلاحظ ذلك لاحقاً عند عرض قيمهم multiset<int, greater<int>> myMultiset = {1, 4, 2, 5, 3}; cout << "myMultiset values ="; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMultiset هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMultiset.begin(); it != myMultiset.end(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
myMultiset values = 5 4 3 2 1
في المثال التالي قمنا بتعريف كائن من multiset
مخصص لتخزين قيم نوعها int
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بالبحث عن قيم محددة فيه لمعرفة كم عنصر يملك هذه القيم.
ملاحظة: قمنا باستخدام الدالة count()
لمعرفة كم مرة القيم مكررة في الكائن.
#include <iostream> #include <set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها multiset هنا قمنا بتعريف كائن من الكلاس multiset<int> myMultiset = {1, 4, 2, 3, 4, 5, 2, 4, 7}; // التي تملك القيمة 4 myMultiset هنا قمنا بطباعة عدد العناصر الموجودة في الكائن cout << "4 is exist " << myMultiset.count(4) << " time(s)\n"; // التي تملك القيمة 9 myMultiset هنا قمنا بطباعة عدد العناصر الموجودة في الكائن cout << "9 is exist " << myMultiset.count(9) << " time(s)"; return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
4 is exist 3 time(s) 9 is exist 0 time(s)
في المثال التالي قمنا بتعريف كائن من multiset
مخصص لتخزين قيم نوعها int
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بالبحث عن قيمة محددة فيه و في حال كانت موجودة سنقوم بحذف العنصر الذي يملكها من الكائن.
ملاحظة: قمنا باستخدام الدالة find()
للبحث عن القيمة في الكائن و الدالة erase()
لحذف العنصر من الكائن.
#include <iostream> #include <set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه int يمكنه أن يحتوي على عناصر نوعها multiset هنا قمنا بتعريف كائن من الكلاس multiset<int> myMultiset = {1, 2, 3, 4, 5}; // لتخزين مكان العنصر الذي نجد القيمة التي نبحث عنها فيه multiset<int>::iterator منا قمنا بتعريف كائن من multiset<int>::iterator it; // it عن عنصر يملك القيمة 4, و بالتالي في حال وجود عنصر يملك القيمة 4 سيتم تخزين عنوانه في الكائن myMultiset هنا قمنا بالبحث في الكائن // فيه للإشارة إلى أنه لم يتم إيجاد أي عنصر يملك هذه القيمة myMultiset.end() في حال عدم وجود عنصر يملك القيمة 4 سيتم تخزين القيمة التي ترجعها it = myMultiset.find(4); // فهذا يعني أنه تم إيجاد القيمة و بالتالي سيتم تنفيذ الكود الموضوع فيها myMultiset.end() لا تساوي القيمة التي ترجعها الدالة it في حال كانت قيمة if (it != myMultiset.end()) { // و من ثم قمنا بحذفه myMultiset هنا قمنا بطباعة قيمة العنصر الذي تم إيجاده في الكائن cout << "element with value '"<< *it << "' is removed from myMultiset\n"; myMultiset.erase(it); } cout << "myMultiset values ="; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMultiset هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMultiset.begin(); it != myMultiset.end(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
element with value '4' is removed from myMultiset myMultiset values = 1 2 3 5
في المثال التالي قمنا بتعريف كائنين من multiset
مع تحديد أنه يمكن أن يحتويان على عناصر نوعها int
.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة القيم التي أصبحت موجودة في كلٍّ منهما.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل قيمهما.
#include <iostream> #include <set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيهما int يمكنهما أن يحتويان على قيم نوعها multiset هنا قمنا بتعريف كائنين من الكلاس multiset<int> multiset1 = {1, 2, 3, 4}; multiset<int> multiset2 = {5, 6, 7, 8}; // multiset2 مع قيم الكائن multiset1 هنا قمنا بتبديل قيم الكائن multiset1.swap(multiset2); cout << "multiset1 values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه multiset1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = multiset1.begin(); it != multiset1.end(); ++it) { cout << *it << " "; } cout << "\nmultiset2 values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه multiset2 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = multiset2.begin(); it != multiset2.end(); ++it) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
multiset1 values = 5 6 7 8 multiset2 values = 1 2 3 4
في المثال التالي قمنا بتخصيص الطريقة التي سيقوم فيها الكائن الذي ننشئه من الكلاس multiset
حتى يتناسب مع نوع العناصر التي سنقوم بتخزينها فيه.
في البداية قمنا بتعريف كلاس إسمه Book
يمثل الشكل العام لأي كتاب و هو يحتوي على خاصيّتين و هما إسم الكتاب title
و رقم التعرفة id
الخاص به.
بعدها قمنا بإنشاء كلاس إسمه Compare
سنستخدمه لنحدد الطريقة التي سيتم على أساسها ترتيب قيم العناصر.
في هذا الكلاس قمنا بإنشاء عامل ( Operator ) يملك باراميترين نوعهما Book
لأن فكرة هذا العامل أنه يقارن أي عنصر جديد ( عبارة عن كائن من Book
) نقوم بإضافته مع أول عنصر موجود في الكائن. لذا الباراميتر الأول يعتبر العنصر الأول الموجود في الكائن و الباراميتر الثاني يعتبر العنصر الجديد الذي سيتم إضافته.
على هذا الأساس قمنا بتحديد أنه في حال كانت قيمة id
في الباراميتر الأول أصغر من قيمة id
في الباراميتر الثاني سيتم وضع العنصر الذي تم تمريره في الباراميتر الأول في بداية الكائن.
في الأخير قمنا بإنشاء ثلاث كائنات من الكلاس Book
لأنها ستكون بمثابة العناصر التي سنقوم بتخزينها في الحاوية.
و من ثم قمنا بإنشاء كائن من multiset
مع تحديد أنه سيتم تخزين عناصر نوعها Book
فيه و أنه سيستخدم العامل الموجود في الكلاس Compare
حتى يرتب العناصر التي نضيفها فيه و من بعدها أضفنا العناصر فيه, ثم قمنا بعرضها بواسطة حلقة.
ملاحظة: قمنا باستخدام الحلقة Foreach عند عرض قيم العناصر.
#include <iostream> #include <set> using namespace std; // Book هنا قمنا بتعريف الكلاس class Book { public: // هنا قمنا بتعريف خصائص الكلاس int id; string title; // هنا قمنا بتعريف كونستكتور للكلاس حتى نستطيع تمرير قيم للخصائص بشكل مباشر عند إنشاء كائن منه Book(int id, string title) { this->id = id; this->title = title; } }; // multiset و الذي سنستخدمه لاحقاً لتحديد كيف ستترتب العناصر في الحاوية التي ننشئها من الكلاس Compare هنا قمنا بتعريف الكلاس class Compare { public: // id حتى يقارن قيمة multiset هنا قمنا بتعريف العامل الذي سيستخدمه الكائن الذي ننشئه من الكلاس // الموجودة في أول عنصر فيها id في الكائن الذي سيتم إضافته في الحاوية مع قيمة bool operator() (Book b1, Book b2) { // الموجودة في العنصر الجديد أصغر من id هنا كأننا نعلم المترجم بأنه في حال كانت قيمة // الموجودة في العنصر الأول في الحاوية, فإننا نريد وضعها هي في البداية id قيمة return (b1.id < b2.id); } }; // main() هنا قمنا بتعريف الدالة int main() { // بالإضافة إلى Book يمكنه أن يحتوي على كائنات من الكلاس multiset هنا قمنا بتعريف كائن من الكلاس // من أجل تحديد الطريقة التي سيتم فيها ترتيب الكائنات التي نضيفها فيه Compare أنه يعتمد على الكلاس multiset<Book, Compare> myMultiset; // myMultiset لأننا سنضعها كعناصر في الحاوية Book هنا قمنا بإنشاء 3 كائنات من الكلاس Book book1(2, "C++ for beginner"); Book book2(1, "HTML5 for dummies"); Book book3(3, "Building Android apps"); // emplace() باستخدام الدالة myMultiset في الكائن book3, book2 و book1 هنا قمنا بإضافة الكائنات // {book2, book1, book3} فيها كالتالي id العناصر سيتم ترتيبها من الأسغر إلى الأكبر على حسب قيمة الخاصية myMultiset.emplace(book1); myMultiset.emplace(book2); myMultiset.emplace(book3); cout << "All books in myMultiset:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMultiset هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto const &e: myMultiset) { cout << e.id << " - " << e.title << endl; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
All books in myMultiset: 1 - HTML5 for dummies 2 - C++ for beginner 3 - Building Android apps
الكلاس map
في C++
تعريف الكلاس map
في C++
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل جدول يتألف من عمودين حيث يتكون كل عنصر من مفتاح ( Key ) يوضع في العمود الأول و قيمة ( Value ) توضع في العمود الثاني بالإضافة إلى أنها ترتب العناصر بشكل تصاعدي على حسب قيم المفاتيح كالتالي.
القيمة المفتاحية لكل عنصر يمكن أن تكون من أي نوع تريده, و لكن في أغلب الأوقات ستكون المفاتيح عبارة عن أعداد أو كلمات.
لا تستطيع وضع نفس القيمة المفتاحية لأكثر من عنصر و هذا شيء منطقي لأن المفاتيح هي ما يميز العناصر عن بعضها.
لاستخدام الكلاس map
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<map>
لأنه موجود فيه.
template < class Key, // map::key_type class T, // map::mapped_type class Compare = less<Key>, // map::key_compare class Alloc = allocator<pair<const Key,T> > // map::allocator_type > class map;
إذاً عند إنشاء كائن من الكلاس map
يجب أن نمرر له نوع المفاتيح التي نريد تخزينها فيه مكان الباراميتر Key
و نوع القيم التي نريد تخزينها فيه مكان الباراميتر T
.
دوال الكلاس map
في C++
الجدول التالي يحتوي على دوال الكلاس map
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator rbegin()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
|
iterator rend()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
الجدول التالي يحتوي على دوال الكلاس map
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس map
التي تستخدم للوصول لقيم عناصره.
الدالة مع تعريفها | |
---|---|
mapped_type& at(key_type& k)
تستخدم للوصول لقيمة عنصر محدد في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.مكان الباراميتر k نمرر لها مفتاح العنصر الذي نريد الوصول إليه.ترمي الإستثناء out_of_range في حال كانت قيمة k لا تمثل القيمة المفتاحية لأي عنصر موجود في الكائن.معلومة: يمكنك استخدام العامل [] للوصول للعنصر و لكن عليك معرفة أن استخدام هذا العامل لا يرمي إستثناء في حال تمرير قيمة مفتاح غير موجود في الكائن. |
|
operator[] (key_type& k)
يستخدم العامل [] للوصول لقيمة عنصر محدد في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.مكان الباراميتر k نمرر لها مفتاح العنصر الذي نريد الوصول إليه.في حال تمرير قيمة مفتاح غير موجود مكان الباراميتر k سيتم إضافة العنصر كعنصر جديد في الكائن. |
الجدول التالي يحتوي على دوال الكلاس map
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
pair<K, V> insert({key, value})
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها.مكان الباراميتر key نمرر القيمة المفتاحية للعنصر الذي نريد إضافته.مكان الباراميتر value نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.كما أنها ترجع نسخة من العنصر الذي تم إضافته. |
|
pair<K, V> emplace(Args&&... args)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها تماماً كالدالة insert() .مكان الباراميتر Args نمرر القيمة المفتاحية للعنصر الذي نريد إضافته ثم نضع فاصلة و نمرر القيمة التي نريد وضعها فيه.كما أنها ترجع نسخة من العنصر الذي تم إضافته. |
|
size_t erase(key_type& k)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها من خلال المفتاح الخاص به.مكان الباراميتر k نمرر مفتاح العنصر الذي نريد حذفه. |
|
iterator erase(const_iterator position)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها من خلال الإشارة إلى مكانه فيه.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه. |
|
iterator erase(const_iterator first, const_iterator last)
تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها من خلال الإشارة إلى مكان وجود هذه العناصر.مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده. |
|
void swap(map& anotherMap)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherMap نمرر لها كائن من الكلاس map يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس map
التي تستخدم للبحث فيه.
الدالة مع تعريفها | |
---|---|
size_t count(T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن عنصر يملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع القيمة 1 و في حال لم يتم إيجاد عنصر يملك نفس القيمة ترجع القيمة 0 . |
|
iterator find(const T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن عنصر يملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator يشير لعنوان العنصر في الذاكرة.و في حال لم يتم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator قيمته تساوي القيمة التي ترجعها الدالة end() . |
أمثلة شاملة حول التعامل مع الكلاس map
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من map
مع تحديد أن عناصره تتكون من مفاتيح نوعها string
قيم و نوعها string
أيضاً.
بعدها قمنا بإضافة بعض العناصر فيه, كل عنصر عبارة منهم عبارة عن كود الإتصال الخاص بالبلد و إسم البلد.
بعدها قمنا بطباعة عدد العناصر التي قمنا بإضافتها.
في الأخير قمنا بعرض جميع مفاتيح و قيم العناصر الموجودة فيه بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة emplace()
لإضافة العناصر, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير لأننا سنتوقف عنده.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها string يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس map<string, string> myMap; // كل عنصر يحتوي على كود البلد كمفتاح و إسمه كقيمة ,myMap هنا قمنا بإضافة 12 عنصر في الكائن myMap.emplace("+961", "Lebanon"); myMap.emplace("+962", "Jordan"); myMap.emplace("+963", "Syria"); myMap.emplace("+964", "Iraq"); myMap.emplace("+965", "Kuwait"); myMap.emplace("+966", "KSA"); myMap.emplace("+967", "Yaman"); myMap.emplace("+968", "Oman"); myMap.emplace("+970", "Palestine"); myMap.emplace("+212", "Morocco"); myMap.emplace("+281", "Libya"); myMap.emplace("+20", "Egypt"); // size() باستخدام الدالة myMap هنا قمنا بطباعة عدد عناصر الكائن cout << "myMap size = " << myMap.size() << "\n\n"; cout << "myMap keys and values\n"; cout << "---------------------\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMap.begin(); it != myMap.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << "\t | " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
myMap size = 12 myMap keys and values --------------------- +20 | Egypt +212 | Morocco +281 | Libya +961 | Lebanon +962 | Jordan +963 | Syria +964 | Iraq +965 | Kuwait +966 | KSA +967 | Yaman +968 | Oman +970 | Palestine
في المثال التالي قمنا بتعريف كائن من map
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بعرض القيم الموجودة فيه بواسطة حلقة.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس map<int, string> myMap = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"}, }; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMap.begin(); it != myMap.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
1 - One 2 - Two 3 - Three 4 - Four 5 - Five
في المثال التالي قمنا بتعريف كائن من map
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بعرض القيم الموجودة فيه بشكل عكسي بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة rbegin()
للحصول على مؤشر للعنصر الأخير لأننا سنبدأ من عنده و الدالة rend()
للحصول على مؤشر للعنصر الأول لأننا سنتوقف عنده.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس map<int, string> myMap = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"}, }; // إبتداءاً من آخر عنصر وصولاً لأول عنصر فيه myMap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMap.rbegin(); it != myMap.rend(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
5 - Five 4 - Four 3 - Three 2 - Two 1 - One
في المثال التالي قمنا بتعريف كائن من map
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بالبحث عن عنصر يملك مفتاح محدد لمعرفة ما إن كان يوجد عنصر يملك هذا المفتاح أم لا مع الإشارة إلى أنه في حال وجود عنصر يملك هذا المفتاح سيتم طباعة قيمته أيضاً.
ملاحظة: قمنا باستخدام الدالة count()
للبحث عن عنصر يملك مفتاح محدد في الكائن و قمنا باستخدام الدالة at()
لطباعة قيمة العنصر الذي يملك مفتاح محدد.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس map<int, string> myMap = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"}, }; // يوجد فيه عنصر يملك مفتاح يساوي 4 أم لا myMap هنا قمنا بطباعة ما إن كان الكائن if (myMap.count(4)) { // إن كان فيه سيتم تنفيذ أمر الطباعة التالي cout << "Element with key '4' is exist and it's value = " << myMap.at(4); } else { // إن لم يكن فيه سيتم تنفيذ أمر الطباعة التالي cout << "There is no element with key = 4"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Element with key '4' is exist and it's value = Four
في المثال التالي قمنا بتعريف كائن من map
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بحذف عنصر منه بالإعتماد على قيمة مفتاحه و من ثم طباعة قيم جميع العناصر المتبقية بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة erase()
لحذف العنصر.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس map<int, string> myMap = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"} }; // myMap هنا قمنا بحذف العنصر الذي يملك مفتاح يساوي 3 في الكائن myMap.erase(3); // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMap.begin(); it != myMap.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
1 - One 2 - Two 4 - Four 5 - Five
في المثال التالي قمنا بتعريف كائن من map
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بالبحث عن عنصر يملك مفتاح محدد فيه و في حال وجوده سيتم حذف العنصر من الكائن.
في الأخير قمنا بطباعة قيم جميع العناصر المتبقية بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة find()
للبحث عن العنصر الذي يملك المفتاح في الكائن و الدالة erase()
لحذف العنصر من الكائن.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس map<int, string> myMap = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"} }; // لتخزين مكان العنصر الذي نجد القيمة التي نبحث عنها فيه map<int, string>::iterator منا قمنا بتعريف كائن من map<int, string>::iterator it; // it عن عنصر يملك مفتاح يساوي 4, و بالتالي في حال وجود عنصر يملك هذا المفتاح سيتم تخزين عنوانه في الكائن myMap هنا قمنا بالبحث في الكائن // فيه للإشارة إلى أنه لم يتم إيجاد أي عنصر يملك هذا المفتاح myMap.end() في حال عدم وجود عنصر يملك مفتاح يساوي 4 سيتم تخزين القيمة التي ترجعها it = myMap.find(4); // فهذا يعني أنه تم إيجاد العنصر و بالتالي سيتم تنفيذ الكود الموضوع بالداخل myMap.end() لا تساوي القيمة التي ترجعها الدالة it في حال كانت قيمة if (it != myMap.end()) { // و من ثم قمنا بحذفه myMap هنا قمنا بطباعة مفتاح العنصر الذي تم إيجاده في الكائن cout << "Element with key '"<< it->first << "' is removed from myMap\n\n"; myMap.erase(it); } cout << "myMap keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMap.begin(); it != myMap.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Element with key '4' is removed from myMap myMap keys and values: 1 - One 2 - Two 3 - Three 5 - Five
في المثال التالي قمنا بتعريف كائنين من map
مع تحديد أن عناصرهما تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة قيم عناصرهما بواسطة حلقة للتأكد من أن التبديل قد تم بنجاح.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل عناصرهما.
#include <iostream> #include <map> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس map<int, string> map1 = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"} }; // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن آخر من الكلاس map<int, string> map2 = { {5, "Five"}, {6, "Six"}, {7, "Seven"}, {8, "Eight"} }; // map2 مع قيم الكائن map1 هنا قمنا بتبديل قيم الكائن map1.swap(map2); cout << "map1 keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه map1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = map1.begin(); it != map1.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } cout << "\nmap2 keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه map2 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = map2.begin(); it != map2.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
map1 keys and values: 5 - Five 6 - Six 7 - Seven 8 - Eight map2 keys and values: 1 - One 2 - Two 3 - Three 4 - Four
الكلاس multimap
في C++
تعريف الكلاس multimap
في C++
يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل جدول يتألف من عمودين حيث يتكون كل عنصر من مفتاح ( Key ) يوضع في العمود الأول و قيمة ( Value ) توضع في العمود الثاني بالإضافة إلى أنها ترتب العناصر بشكل تصاعدي على حسب قيم المفاتيح مع الإشارة إلى أنه يمكن وضع نفس المفتاح لأكثر من عنصر كالتالي.
القيمة المفتاحية لكل عنصر يمكن أن تكون من أي نوع تريده, و لكن في أغلب الأوقات ستكون المفاتيح عبارة عن أعداد أو كلمات.
الفرق الوحيد بين الحاوية التي تنشئها من الكلاس map
و الحاوية التي تنشئها من الكلاس multimap
هو أن هذا الأخير يمكنه أن يستخدم نفس المفتاح لأكثر من عنصر.
الآن, بما أن مفاتيح العناصر في هذه الحاوية يمكن أن تكون مكررة فهذا يعني أنه لا يمكنك الإعتماد على قيم المفاتيح للتفرقة بين العناصر حيث أن المفتاح الواحد يمكن أن يرمز لعدة عناصر.
لاستخدام الكلاس multimap
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<map>
لأنه موجود فيه.
template < class Key, // multimap::key_type class T, // multimap::multimapped_type class Compare = less<Key>, // multimap::key_compare class Alloc = allocator<pair<const Key,T> > // multimap::allocator_type > class multimap;
إذاً عند إنشاء كائن من الكلاس multimap
يجب أن نمرر له نوع المفاتيح التي نريد تخزينها فيه مكان الباراميتر Key
و نوع القيم التي نريد تخزينها فيه مكان الباراميتر T
.
دوال الكلاس multimap
في C++
الجدول التالي يحتوي على دوال الكلاس multimap
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator rbegin()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
|
iterator rend()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر. |
الجدول التالي يحتوي على دوال الكلاس multimap
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس multimap
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
pair<K, V> insert({key, value})
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها.مكان الباراميتر key نمرر القيمة المفتاحية للعنصر الذي نريد إضافته.مكان الباراميتر value نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.كما أنها ترجع نسخة من العنصر الذي تم إضافته. |
|
pair<K, V> emplace(Args&&... args)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها تماماً كالدالة insert() .مكان الباراميتر Args نمرر القيمة المفتاحية للعنصر الذي نريد إضافته ثم نضع فاصلة و نمرر القيمة التي نريد وضعها فيه.كما أنها ترجع نسخة من العنصر الذي تم إضافته. |
|
size_t erase(key_type& k)
تستخدم لحذف كل عنصر في الكائن الذي قام باستدعائها يملك المفتاح الذي نمرره لها.مكان الباراميتر k نمرر المفتاح الذي نريد حذف كل عنصر يملكه. |
|
iterator erase(const_iterator position)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها من خلال الإشارة إلى مكانه فيه.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه. |
|
iterator erase(const_iterator first, const_iterator last)
تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها من خلال الإشارة إلى مكان وجود هذه العناصر.مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده. |
|
void swap(multimap& anotherMap)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherMap نمرر لها كائن من الكلاس multimap يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس multimap
التي تستخدم للبحث فيه.
الدالة مع تعريفها | |
---|---|
size_t count(const key_type& k)
تستخدم لمعرفة عدد العناصر التي تملك مفتاح محدد في الكائن الذي قام باستدعائها.مكان الباراميتر k نمرر المفتاح الذي نريد معرفة عدد العناصر التي تملكه. |
|
iterator find(const T& k)
تستخدم للبحث في الكائن الذي قام باستدعائها عن مكان أول عنصر يملك مفتاح محدد.مكان الباراميتر k نمرر المفتاح الذي نريد البحث عن أول عنصر يملكه.في حال تم إيجاد عنصر يملك نفس المفتاح الذي تم تمريره لها ترجع كائن من Iterator يشير لعنوان العنصر في الذاكرة.و في حال لم يتم إيجاد عنصر يملك نفس المفتاح الذي تم تمريره لها ترجع كائن من Iterator قيمته تساوي القيمة التي ترجعها الدالة end() . |
أمثلة شاملة حول التعامل مع الكلاس multimap
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها string
قيم و نوعها string
أيضاً.
بعدها قمنا بإضافة بعض العناصر فيه, كل عنصر عبارة منهم عبارة عن كود الإتصال الخاص بالبلد و إسم البلد.
بعدها قمنا بطباعة عدد العناصر التي قمنا بإضافتها.
في الأخير قمنا بعرض جميع مفاتيح و قيم العناصر الموجودة فيه بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة emplace()
لإضافة العناصر, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير لأننا سنتوقف عنده.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها string يمكنه أن يحتوي على مفاتيح نوعها multimap هنا قمنا بتعريف كائن من الكلاس multimap<string, string> myMultimap; // كل عنصر يحتوي على إسم البلد كمفتاح و إحدى مدنه كقيمة ,myMultimap هنا قمنا بإضافة 12 عنصر في الكائن myMultimap.emplace("Egypt", "Giza"); myMultimap.emplace("Lebanon", "Beirut"); myMultimap.emplace("Syria", "Sweida"); myMultimap.emplace("Lebanon", "Tripolie"); myMultimap.emplace("Syria", "Idlib"); myMultimap.emplace("KSA", "Riyadh"); myMultimap.emplace("Egypt", "Cairo"); myMultimap.emplace("Lebanon", "Sidon"); myMultimap.emplace("Syria", "Damascus"); myMultimap.emplace("KSA", "Makkah"); myMultimap.emplace("Syria", "Homs"); myMultimap.emplace("Algeria", "Algiers"); // size() باستخدام الدالة myMultimap هنا قمنا بطباعة عدد عناصر الكائن cout << "myMultimap size = " << myMultimap.size() << "\n\n"; cout << "myMultimap keys and values\n"; cout << "---------------------\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMultimap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMultimap.begin(); it != myMultimap.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << "\t | " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
myMultimap size = 12 myMultimap keys and values --------------------- Algeria | Algiers Egypt | Giza Egypt | Cairo KSA | Riyadh KSA | Makkah Lebanon | Beirut Lebanon | Tripolie Lebanon | Sidon Syria | Sweida Syria | Idlib Syria | Damascus Syria | Homs
في المثال التالي قمنا بتعريف كائن من multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بعرض القيم الموجودة فيه بواسطة حلقة.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها multimap هنا قمنا بتعريف كائن من الكلاس multimap<int, string> myMultimap = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"}, }; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMultimap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMultimap.begin(); it != myMultimap.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
1 - One 2 - Two 3 - Three 4 - Four 5 - Five
في المثال التالي قمنا بتعريف كائن من multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بعرض القيم الموجودة فيه بشكل عكسي بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة rbegin()
للحصول على مؤشر للعنصر الأخير لأننا سنبدأ من عنده و الدالة rend()
للحصول على مؤشر للعنصر الأول لأننا سنتوقف عنده.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها multimap هنا قمنا بتعريف كائن من الكلاس multimap<int, string> myMultimap = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"}, }; // إبتداءاً من آخر عنصر وصولاً لأول عنصر فيه myMultimap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMultimap.rbegin(); it != myMultimap.rend(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
5 - Five 4 - Four 3 - Three 2 - Two 1 - One
في المثال التالي قمنا بتعريف كائن من multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها string
قيم و نوعها string
أيضاً.
بعدها قمنا بالبحث عن عدد العناصر التي تملك مفتاح محدد و طباعة نتيجة البحث.
ملاحظة: قمنا باستخدام الدالة count()
لمعرفة عدد العناصر التي تملك مفتاح محدد في الكائن.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها string يمكنه أن يحتوي على مفاتيح نوعها multimap هنا قمنا بتعريف كائن من الكلاس multimap<string, string> myMultimap; // كل عنصر يحتوي على إسم البلد كمفتاح و إحدى مدنه كقيمة ,myMultimap هنا قمنا بإضافة 12 عنصر في الكائن myMultimap.emplace("Egypt", "Giza"); myMultimap.emplace("Lebanon", "Beirut"); myMultimap.emplace("Syria", "Sweida"); myMultimap.emplace("Lebanon", "Tripolie"); myMultimap.emplace("Syria", "Idlib"); myMultimap.emplace("KSA", "Riyadh"); myMultimap.emplace("Egypt", "Cairo"); myMultimap.emplace("Lebanon", "Sidon"); myMultimap.emplace("Syria", "Damascus"); myMultimap.emplace("KSA", "Makkah"); myMultimap.emplace("Syria", "Homs"); myMultimap.emplace("Algeria", "Algiers"); // myMultimap في الكائن "Syria" هنا قمنا بطباعة عدد العناصر التي تملك قيمة تساوي cout << "Total number of elements with key 'Syria' = " << myMultimap.count("Syria"); return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Total number of elements with key 'Syria' = 4
في المثال التالي قمنا بتعريف كائن من multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها string
قيم و نوعها string
أيضاً.
بعدها قمنا بحذف جميع العناصر التي تملك مفاتيح محددة منه و من ثم طباعة قيم جميع العناصر المتبقية بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة erase()
لحذف جميع العناصر التي تملك مفاتيح محددة.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها string يمكنه أن يحتوي على مفاتيح نوعها multimap هنا قمنا بتعريف كائن من الكلاس multimap<string, string> myMultimap; // كل عنصر يحتوي على إسم البلد كمفتاح و إحدى مدنه كقيمة ,myMultimap هنا قمنا بإضافة 12 عنصر في الكائن myMultimap.emplace("Egypt", "Giza"); myMultimap.emplace("Lebanon", "Beirut"); myMultimap.emplace("Syria", "Sweida"); myMultimap.emplace("Lebanon", "Tripolie"); myMultimap.emplace("Syria", "Idlib"); myMultimap.emplace("KSA", "Riyadh"); myMultimap.emplace("Egypt", "Cairo"); myMultimap.emplace("Lebanon", "Sidon"); myMultimap.emplace("Syria", "Damascus"); myMultimap.emplace("KSA", "Makkah"); myMultimap.emplace("Syria", "Homs"); myMultimap.emplace("Algeria", "Algiers"); // myMultimap من الكائن "Syria" و المتفاح "Lebanon" هنا قمنا بحذف جميع العناصر التي تملك المفتاح myMultimap.erase("Lebanon"); myMultimap.erase("Syria"); // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMultimap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMultimap.begin(); it != myMultimap.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " -> " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Algeria -> Algiers Egypt -> Giza Egypt -> Cairo KSA -> Riyadh KSA -> Makkah
في المثال التالي قمنا بتعريف كائن من multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بالبحث عن أول عنصر يملك مفتاح محدد فيه و من ثم قمنا بحذفه.
في الأخير قمنا بطباعة قيم جميع العناصر المتبقية بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة find()
للبحث عن أول عنصر يملك مفتاح محدد في الكائن و الدالة erase()
لحذف العنصر منه.
#include <iostream> #include <map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها multimap هنا قمنا بتعريف كائن من الكلاس multimap<int, string> myMultimap = { {1, "Un"}, {1, "One"}, {2, "Deux"}, {2, "Two"}, {3, "Trois"}, {3, "Three"} }; // نجده يملك المفتاح الذي سنبحث عنه myMultimap لتخزين مكان أول عنصر في الكائن multimap<int, string>::iterator منا قمنا بتعريف كائن من multimap<int, string>::iterator it; // it عن أول عنصر يملك مفتاح يساوي 2, و بالتالي في حال وجود عنصر يملك هذا المفتاح سيتم تخزين عنوانه في الكائن myMultimap هنا قمنا بالبحث في الكائن // فيه للإشارة إلى أنه لم يتم إيجاد أي عنصر يملك هذا المفتاح myMultimap.end() في حال عدم وجود عنصر يملك مفتاح يساوي 2 سيتم تخزين القيمة التي ترجعها it = myMultimap.find(2); // فهذا يعني أنه تم إيجاد العنصر و بالتالي سيتم تنفيذ الكود الموضوع بالداخل myMultimap.end() لا تساوي القيمة التي ترجعها الدالة it في حال كانت قيمة if (it != myMultimap.end()) { // و من ثم قمنا بحذفه myMultimap هنا قمنا بطباعة مفتاح و قيمة العنصر الذي تم إيجاده في الكائن cout << "Element with key '"<< it->first << "' and value '" << it->second << "' is removed from myMultimap\n\n"; myMultimap.erase(it); } cout << "myMultimap keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMultimap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = myMultimap.begin(); it != myMultimap.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Element with key '2' and value 'Deux' is removed from myMultimap myMultimap keys and values: 1 - Un 1 - One 2 - Two 3 - Trois 3 - Three
في المثال التالي قمنا بتعريف كائنين من multimap
مع تحديد أن عناصرهما تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة قيم عناصرهما بواسطة حلقة للتأكد من أن التبديل قد تم بنجاح.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل عناصرهما.
#include <iostream> #include <map> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها multimap هنا قمنا بتعريف كائن من الكلاس multimap<int, string> multimap1 = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"} }; // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها multimap هنا قمنا بتعريف كائن آخر من الكلاس multimap<int, string> multimap2 = { {5, "Five"}, {6, "Six"}, {7, "Seven"}, {8, "Eight"} }; // multimap2 مع قيم الكائن multimap1 هنا قمنا بتبديل قيم الكائن multimap1.swap(multimap2); cout << "multimap1 keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه multimap1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = multimap1.begin(); it != multimap1.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } cout << "\nmultimap2 keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه multimap2 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = multimap2.begin(); it != multimap2.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
multimap1 keys and values: 5 - Five 6 - Six 7 - Seven 8 - Eight multimap2 keys and values: 1 - One 2 - Two 3 - Three 4 - Four
الكلاس unordered_set
في C++
تعريف الكلاس unordered_set
في C++
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11
و هو يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بترتيب معين يتم تحديده من قبل دالة مخصصة لذلك إسمها Hash()
تقوم بالتشييك على قيم أي عنصر سيتم إدخاله لتحديد المكان الذي يجب وضعه فيه مع الإشارة إلى أنه لا يمكن تخزين قيم مكررة فيها.
بالمبدأ الدالة Hash()
تقوم بإجراء عملية حسابية على قيم أي عنصر يتم إدخاله.
أي ناتج جديد غير مكرر ترجعه الدالة Hash()
يتم تخزينه في الذاكرة في مكان خاص يقال له Bucket.
أي عنصر جديد يتم إضافته تقوم الدالة Hash()
بإجراء العملية الحسابية عليه و مقارنة الناتج النهائي مع قيمة كل Buckets نتجت سابقاً و في حال تطابق الناتج مع قيمة أي Bucket سيتم وضعه في آخرها, أما في حال عدم تطابق الناتج مع قيمة أي Bucket سيتم إضافة Bucket جديد و وضعه فيها كالتالي.
كما أنه بإمكانك تعريف الدالة طريقة عمل الدالة Hash()
بنفسك حتى تحدد الطريقة التي سيتم على أساسها إنشاء Buckets و ترتيب العناصر ضمنهم.
على سبيل المثال إذا كنت تنوي إنشاء حاوية خاصة لتخزين الأعداد, يمكنك جعل الدالة Hash()
تنشئ Buckets على حسب عدد الأرقام التي يتألف منها كل عدد. عندها سيتم ترتيب العناصر كالتالي:
العدد الذي يتألف من رقم واحد مثل
3
-7
سيتم وضعهما في Bucket.العدد الذي يتألف من رقمين واحد مثل
12
-45
سيتم وضعهما في Bucket.العدد الذي يتألف من ثلاثة أرقام مثل
100
-273
سيتم وضعهما في Bucket و هكذا..
لاستخدام الكلاس unordered_set
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<unordered_set>
لأنه موجود فيه.
template < class Key, // unordered_set::key_type/value_type class Hash = hash<Key>, // unordered_set::hasher class Pred = equal_to<Key>, // unordered_set::key_equal class Alloc = allocator<Key> // unordered_set::allocator_type > class unordered_set;
إذاً عند إنشاء كائن من الكلاس unordered_set
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر Key
.
دوال الكلاس unordered_set
في C++
الجدول التالي يحتوي على دوال الكلاس unordered_set
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
local_iterator begin(size_t n)
ترجع كائن iterator يشير لمكان أول عنصر بداخل Bucket محدد في الكائن الذي قام باستدعائها.مكان الباراميتر n نمرر رقم الـ Bucket الذي نريد البدأ من أول عنصر موجود فيه. |
|
local_iterator end(size_t n)
ترجع كائن iterator يشير لمكان آخر عنصر بداخل Bucket محدد في الكائن الذي قام باستدعائها.مكان الباراميتر n نمرر رقم الـ Bucket الذي نريد الوقوف عند آخر عنصر موجود فيه. |
الجدول التالي يحتوي على دوال الكلاس unordered_set
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
|
size_t bucket_count()
تستخدم للحصول على عدد الـ Buckets الموجودين في الكائن الذي قام باستدعائها. |
|
size_t bucket_size(size_t n)
تستخدم للحصول على عدد العناصر الموجودة في Bucket محددة في الكائن الذي قام باستدعائها.مكان الباراميتر n نمرر عدد يمثل Index الـ Bucket التي سيتم إرجاع عدد العناصر الموجودة فيه. |
|
size_t max_bucket_count()
تستخدم للحصول على أكبر عدد Buckets يمكن تخزينها في الكائن الذي قام باستدعائها. |
|
size_t bucket(key_type& k)
تستخدم للحصول على رقم Bucket محددة في الكائن الذي قام باستدعائها بالإعتماد على قيمة موجودة فيها.مكان الباراميتر k نمرر قيمة العنصر الذي نريد معرفة في Bucket موجود. |
الجدول التالي يحتوي على دوال الكلاس unordered_set
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
void emplace(T& val)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها. |
|
iterator erase(const_iterator position)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه. |
|
iterator erase(const_iterator first, const_iterator last)
تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها.مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده. |
|
void swap(unordered_set& anotherSet)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherSet نمرر لها كائن من الكلاس unordered_set يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس unordered_set
التي تستخدم للبحث فيه.
الدالة مع تعريفها | |
---|---|
size_t count(T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن عنصر يملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع القيمة 1 و في حال لم يتم إيجاد عنصر يملك نفس القيمة ترجع القيمة 0 . |
|
iterator find(const T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن عنصر يملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator يشير لعنوان العنصر في الذاكرة.و في حال لم يتم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator قيمته تساوي القيمة التي ترجعها الدالة end() . |
|
pair<iterator,iterator> equal_range(const T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن قائمة العناصر المكررة التي تملك نفس القيم التي تحددها لها.مكان الباراميتر val نمرر القيمة التي نريد البحث عن كل العناصر التي تملكها.ترجع كائن من الكلاس pair يحتوي على كل العناصر المكررة التي تم إيجادها. |
أمثلة شاملة حول التعامل مع الكلاس unordered_set
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من unordered_set
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها string
.
بعدها قمنا بإضافة بعض العناصر فيه و من ثم طباعة كم Bucket تم إنشاؤها و إجمالي عدد العناصر التي قمنا بإضافتها.
بعدها قمنا بعرض جميع قيم العناصر الموجودة فيه بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة emplace()
لإضافة العناصر, الدالة bucket_count()
لمعرفة كم Bucket تم إنشاؤها بشكل تلقائي, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير لأننا سنتوقف عنده.
#include <iostream> #include <unordered_set> using namespace std; int main() { // string يمكنه أن يحتوي على قيم نوعها unordered_set هنا قمنا بتعريف كائن من الكلاس unordered_set<string> us; // emplace() باستخدام الدالة us هنا قمنا بإضافة 7 عناصر في الكائن us.emplace("Mon"); us.emplace("Tue"); us.emplace("Wed"); us.emplace("Thu"); us.emplace("Fri"); us.emplace("Sat"); us.emplace("Sun"); // bucket_count() باستخدام الدالة us تم إنشاؤها في الكائن Bucket هنا قمنا بطباعة كم cout << "us total buckets = " << us.bucket_count() << endl; // size() باستخدام الدالة us هنا قمنا بطباعة عدد عناصر الكائن cout << "us total elements = " << us.size() << endl; cout << "us values ="; // us هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن // Bucket وصولاً لآخر عنصر موجود في آخر Bucket إبتداءاً من أول عنصر موجود في أول for (auto it = us.begin(); it != us.end(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
us total buckets = 17 us total elements = 7 us values = Sun Tue Wed Thu Fri Mon Sat
في المثال التالي قمنا بتعريف كائن من unordered_set
مخصص لتخزين قيم نوعها string
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بعرض القيم الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
ملاحظة: قمنا باستخدام الدالة bucket_count()
لمعرفة كم Bucket تم إنشاؤها بشكل تلقائي و الدالة bucket_size()
لمعرفة عدد العناصر الموجودة في كل Bucket.
#include <iostream> #include <unordered_set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string يمكنه أن يحتوي على عناصر نوعها unordered_set هنا قمنا بتعريف كائن من الكلاس unordered_set<string> us = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = us.bucket_count(); // us الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] elements:"; // و من ثم طباعة القيم الموجودة فيها بواسطة الحلقة التالية for(auto it=us.begin(i); it!=us.end(i); ++it) { cout << " " << *it; } cout << endl; } }
•سنحصل على النتيجة التالية عند التشغيل.
bucket[0] elements: Fri bucket[1] elements: bucket[2] elements: Sat Mon bucket[3] elements: bucket[4] elements: Sun Wed bucket[5] elements: bucket[6] elements: bucket[7] elements: Tue bucket[8] elements: bucket[9] elements: bucket[10] elements: Thu
في المثال التالي قمنا بتعريف كائن من unordered_set
مخصص لتخزين قيم نوعها string
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بعرض القيم الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
ملاحظة: قمنا باستخدام الدالة bucket_count()
لمعرفة كم Bucket تم إنشاؤها بشكل تلقائي, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها. عند عرض قيم العناصر الموجودة في كل Bucket قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول فيها لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير فيها لأننا سنتوقف عنده.
#include <iostream> #include <unordered_set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string يمكنه أن يحتوي على عناصر نوعها unordered_set هنا قمنا بتعريف كائن من الكلاس unordered_set<string> us = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = us.bucket_count(); // us الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // و عدد العناصر الموجودة فيها Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] total elements = " << us.bucket_size(i); cout << endl; } }
•سنحصل على النتيجة التالية عند التشغيل.
bucket[0] total elements = 1 bucket[1] total elements = 0 bucket[2] total elements = 2 bucket[3] total elements = 0 bucket[4] total elements = 2 bucket[5] total elements = 0 bucket[6] total elements = 0 bucket[7] total elements = 1 bucket[8] total elements = 0 bucket[9] total elements = 0 bucket[10] total elements = 1
في المثال التالي قمنا بتعريف كائن من unordered_set
مخصص لتخزين قيم نوعها string
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بالبحث عن قيمة محددة فيه لمعرفة ما إن كانت موجودة فيه أم لا.
ملاحظة: قمنا باستخدام الدالة count()
للبحث عن القيمة في الكائن.
#include <iostream> #include <unordered_set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string يمكنه أن يحتوي على عناصر نوعها unordered_set هنا قمنا بتعريف كائن من الكلاس unordered_set<string> us = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; // يوجد فيه عنصر قيمته تساوي 4 us هنا قمنا بطباعة ما إن كان الكائن if (us.count("Wed")) { // إن كان فيه سيتم تنفيذ أمر الطباعة التالي cout << "'Wed' is exist in us"; } else { // إن لم يكن فيه سيتم تنفيذ أمر الطباعة التالي cout << "'Wed' is not exist in us"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
'Wed' is exist in us
في المثال التالي قمنا بتعريف كائن من unordered_set
مخصص لتخزين قيم نوعها string
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بالبحث عن قيمة محددة فيه و في حال كانت موجودة سنقوم بحذف العنصر الذي يملكها من الكائن.
ملاحظة: قمنا باستخدام الدالة find()
للبحث عن القيمة في الكائن و الدالة erase()
لحذف العنصر من الكائن.
#include <iostream> #include <unordered_set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string يمكنه أن يحتوي على عناصر نوعها unordered_set هنا قمنا بتعريف كائن من الكلاس unordered_set<string> us = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; // لتخزين مكان العنصر الذي نجد القيمة التي نبحث عنها فيه unordered_set<string>::iterator منا قمنا بتعريف كائن من unordered_set<string>::iterator it; // it عن عنصر يملك القيمة 4, و بالتالي في حال وجود عنصر يملك القيمة 4 سيتم تخزين عنوانه في الكائن us هنا قمنا بالبحث في الكائن // فيه للإشارة إلى أنه لم يتم إيجاد أي عنصر يملك هذه القيمة us.end() في حال عدم وجود عنصر يملك القيمة 4 سيتم تخزين القيمة التي ترجعها it = us.find("Wed"); // فهذا يعني أنه تم إيجاد القيمة و بالتالي سيتم تنفيذ الكود الموضوع فيها us.end() لا تساوي القيمة التي ترجعها الدالة it في حال كانت قيمة if (it != us.end()) { // و من ثم قمنا بحذفه us هنا قمنا بطباعة قيمة العنصر الذي تم إيجاده في الكائن cout << "Element with value '"<< *it << "' is removed from us\n"; us.erase(it); } cout << "us values ="; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه us هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = us.begin(); it != us.end(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Element with value 'Wed' is removed from us us values = Fri Thu Sun Tue Sat Mon
في المثال التالي قمنا بتعريف كائنين من unordered_set
مع تحديد أنه يمكن أن يحتويان على عناصر نوعها int
.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة القيم التي أصبحت موجودة في كلٍّ منهما.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل قيمهما.
#include <iostream> #include <unordered_set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيهما int يمكنهما أن يحتويان على قيم نوعها unordered_set هنا قمنا بتعريف كائنين من الكلاس unordered_set<int> us1 = {1, 2, 3, 4}; unordered_set<int> us2 = {5, 6, 7, 8}; // us2 مع قيم الكائن us1 هنا قمنا بتبديل قيم الكائن us1.swap(us2); cout << "us1 values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه us1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = us1.begin(); it != us1.end(); ++it) { cout << *it << " "; } cout << "\nus2 values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه us2 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = us2.begin(); it != us2.end(); ++it) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
us1 values = 8 7 6 5 us2 values = 4 3 2 1
في المثال التالي قمنا بتعريف كائن من unordered_set
مخصص لتخزين قيم نوعها int
مع تحديد الطريقة التي سيتم على أساسها توزيع القيم في Buckets و إضافة عدة قيم فيه عند تعريفه.
لتحديد الطريقة التي سيتم على أساسها توزيع القيم في Buckets قمنا بإنشاء كلاس إسمه Hash
و إعادة تعريف العامل ()
حتى يقارن قيمة أي عنصر نريد إضافته نسبةً لعدد الأحرف الموجودة فيه, عندها يتم وضع الأعداد التي تتألف من رقم واحد في Bucket, و الأعداد التي تتألف من رقم رقمين في Bucket, و الأعداد التي تتألف من ثلاثة أعداد في Bucket و هكذا..
في النهاية قمنا بعرض القيم الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
#include <iostream> #include <unordered_set> using namespace std; // unordered_set سنستخدمه لاحقاً لتحديد كيف ستترتب العناصر في الحاوية التي ننشئها من الكلاس Hash هنا قمنا بتعريف كلاس إسمه class Hash { public: // Bucket حتى يقرر في أي unordered_set هنا قمنا بتعريف العامل الذي سيستخدمه الكائن الذي ننشئه من الكلاس // val سيتم وضع العنصر الذي نضيفه فيه مع الإشارة إلى أن القيمة التي يملكها العنصر سيتم تمريرها مكان الباراميتر size_t operator() (const int &val) const { // بشكل مؤقت لأننا نحتاج إجراء تعديل عليها val سيتم وضع قيمة num المتغير // val سنستخدمه لحساب عدد الأرقام الموجودة في المتغير digits المتغير int num = val; int digits = 1; // num و من ثم حذف أول رقم في المتغير digits هنا قمنا بإنشاء حلقة تقوم في كل دورة بإضافة واحد على قيمة المتغيرد // num تمثل عدد الأرقام الموجودة في العدد الذي كان يحتويه المتغير digits عندما تتوقف هذه الحلقة ستكون قيمة المتغير while (num != 0) { digits++; num = num / 10; } // سيتم إضافة العنصر Bucket لأنها التي ستحدد في أي digits في النهاية سيتم إرجاع قيمة المتغير return digits; } }; int main() { // مع تحديد أنه يعتمد على الكلاس string يمكنه أن يحتوي على عناصر نوعها unordered_set هنا قمنا بتعريف كائن من الكلاس // من أجل تحديد الطريقة التي سيتم فيها ترتيب العناصر التي نضيفها فيه, بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه Hash unordered_set<int, Hash> us = {6, 34, 72, 3, 1, 123, 55, 100, 2020}; // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = us.bucket_count(); // us الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] elements:"; // و من ثم طباعة القيم الموجودة فيها بواسطة الحلقة التالية for(auto it=us.begin(i); it!=us.end(i); ++it) { cout << " " << *it; } cout << endl; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل, و لاحظ كيف تم ترتيب العناصر على أساس عدد الأرقام التي يتألف منها كل عنصر.
bucket[0] elements: bucket[1] elements: 1 3 6 bucket[2] elements: 55 72 34 bucket[3] elements: 100 123 bucket[4] elements: 2020 bucket[5] elements: bucket[6] elements: bucket[7] elements: bucket[8] elements: bucket[9] elements: bucket[10] elements:
الكلاس unordered_multiset
في C++
تعريف الكلاس unordered_multiset
في C++
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11
و هو يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بترتيب معين يتم تحديده من قبل دالة مخصصة لذلك إسمها Hash()
تقوم بالتشييك على قيم أي عنصر سيتم إدخاله لتحديد المكان الذي يجب وضعه فيه مع الإشارة إلى أنه يمكن تخزين قيم مكررة فيها.
بالمبدأ الدالة Hash()
تقوم بإجراء عملية حسابية على قيم أي عنصر يتم إدخاله.
أي ناتج جديد غير مكرر ترجعه الدالة Hash()
يتم تخزينه في الذاكرة في مكان خاص يقال له Bucket.
أي عنصر جديد يتم إضافته تقوم الدالة Hash()
بإجراء العملية الحسابية عليه و مقارنة الناتج النهائي مع قيمة كل Buckets نتجت سابقاً و في حال تطابق الناتج مع قيمة أي Bucket سيتم وضعه في آخرها, أما في حال عدم تطابق الناتج مع قيمة أي Bucket سيتم إضافة Bucket جديد و وضعه فيها كالتالي.
كما أنه بإمكانك تعريف الدالة طريقة عمل الدالة Hash()
بنفسك حتى تحدد الطريقة التي سيتم على أساسها إنشاء Buckets و ترتيب العناصر ضمنهم.
على سبيل المثال إذا كنت تنوي إنشاء حاوية خاصة لتخزين الأعداد, يمكنك جعل الدالة Hash()
تنشئ Buckets على حسب عدد الأرقام التي يتألف منها كل عدد. عندها سيتم ترتيب العناصر كالتالي:
العدد الذي يتألف من رقم واحد مثل
3
-7
سيتم وضعهما في Bucket.العدد الذي يتألف من رقمين واحد مثل
12
-45
سيتم وضعهما في Bucket.العدد الذي يتألف من ثلاثة أرقام مثل
100
-273
سيتم وضعهما في Bucket و هكذا..
معلومة تقنية
الفرق الوحيد بين الحاوية التي تنشئها من الكلاس unordered_set
و الحاوية التي تنشئها من الكلاس unordered_multiset
هو أن هذا الأخير يمكنه أن يحتوي على أكثر من عنصر عندهم نفس القيمة.
الآن, بما أن مفاتيح العناصر في هذه الحاوية يمكن أن تكون مكررة فهذا يعني أنه لا يمكنك الإعتماد على قيم المفاتيح للتفرقة بين العناصر حيث أن المفتاح الواحد يمكن أن يرمز لعدة عناصر.
لاستخدام الكلاس unordered_multiset
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<unordered_set>
لأنه موجود فيه.
بناء الكلاس
template < class Key, // unordered_multiset::key_type/value_type class Hash = hash<Key>, // unordered_multiset::hasher class Pred = equal_to<Key>, // unordered_multiset::key_equal class Alloc = allocator<Key> // unordered_multiset::allocator_type > class unordered_multiset;
إذاً عند إنشاء كائن من الكلاس unordered_multiset
يجب أن نمرر له نوع البيانات الذي نريد تخزينه فيه مكان الباراميتر Key
.
دوال الكلاس unordered_multiset
في C++
الجدول التالي يحتوي على دوال الكلاس unordered_multiset
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
local_iterator begin(size_t n)
ترجع كائن iterator يشير لمكان أول عنصر بداخل Bucket محدد في الكائن الذي قام باستدعائها.مكان الباراميتر n نمرر رقم الـ Bucket الذي نريد البدأ من أول عنصر موجود فيه. |
|
local_iterator end(size_t n)
ترجع كائن iterator يشير لمكان آخر عنصر بداخل Bucket محدد في الكائن الذي قام باستدعائها.مكان الباراميتر n نمرر رقم الـ Bucket الذي نريد الوقوف عند آخر عنصر موجود فيه. |
الجدول التالي يحتوي على دوال الكلاس unordered_multiset
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
|
size_t bucket_count()
تستخدم للحصول على عدد الـ Buckets الموجودين في الكائن الذي قام باستدعائها. |
|
size_t bucket_size(size_t n)
تستخدم للحصول على عدد العناصر الموجودة في Bucket محددة في الكائن الذي قام باستدعائها.مكان الباراميتر n نمرر عدد يمثل Index الـ Bucket التي سيتم إرجاع عدد العناصر الموجودة فيه. |
|
size_t max_bucket_count()
تستخدم للحصول على أكبر عدد Buckets يمكن تخزينها في الكائن الذي قام باستدعائها. |
|
size_t bucket(key_type& k)
تستخدم للحصول على رقم Bucket محددة في الكائن الذي قام باستدعائها بالإعتماد على قيمة موجودة فيها.مكان الباراميتر k نمرر قيمة العنصر الذي نريد معرفة في Bucket موجود. |
الجدول التالي يحتوي على دوال الكلاس unordered_multiset
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
void emplace(T& val)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها. |
|
iterator erase(const_iterator position)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه. |
|
iterator erase(const_iterator first, const_iterator last)
تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها.مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده. |
|
void swap(unordered_multiset& anotherSet)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherSet نمرر لها كائن من الكلاس unordered_multiset يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس unordered_multiset
التي تستخدم للبحث فيه.
الدالة مع تعريفها | |
---|---|
size_t count(T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن عدد العناصر التي تملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها. |
|
iterator find(const T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن أول عنصر يملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator يشير لعنوان العنصر في الذاكرة.و في حال لم يتم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator قيمته تساوي القيمة التي ترجعها الدالة end() . |
أمثلة شاملة حول التعامل مع الكلاس unordered_multiset
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من unordered_multiset
مع تحديد أنه يمكن أن يحتوي على عناصر نوعها string
.
بعدها قمنا بإضافة بعض العناصر فيه و من ثم طباعة كم Bucket تم إنشاؤها و إجمالي عدد العناصر التي قمنا بإضافتها.
بعدها قمنا بعرض جميع قيم العناصر الموجودة فيه بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة emplace()
لإضافة العناصر, الدالة bucket_count()
لمعرفة كم Bucket تم إنشاؤها بشكل تلقائي, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير لأننا سنتوقف عنده.
المثال الأول
#include <iostream> #include <unordered_set> using namespace std; int main() { // string يمكنه أن يحتوي على قيم نوعها unordered_multiset هنا قمنا بتعريف كائن من الكلاس unordered_multiset<string> ums; // emplace() باستخدام الدالة ums هنا قمنا بإضافة 9 عناصر في الكائن ums.emplace("Mon"); ums.emplace("Tue"); ums.emplace("Wed"); ums.emplace("Thu"); ums.emplace("Fri"); ums.emplace("Sat"); ums.emplace("Sun"); ums.emplace("Thu"); // تعمدنا إعادة إدخال هذه القيمة مرة ثانية حتى تلاحظ أنه يمكن إدخال قيم مكررة ums.emplace("Fri"); // تعمدنا إعادة إدخال هذه القيمة مرة ثانية حتى تلاحظ أنه يمكن إدخال قيم مكررة // bucket_count() باستخدام الدالة ums تم إنشاؤها في الكائن Bucket هنا قمنا بطباعة كم cout << "ums total buckets = " << ums.bucket_count() << endl; // size() باستخدام الدالة ums هنا قمنا بطباعة عدد عناصر الكائن cout << "ums total elements = " << ums.size() << endl; cout << "ums values ="; // ums هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن // Bucket وصولاً لآخر عنصر موجود في آخر Bucket إبتداءاً من أول عنصر موجود في أول for (auto it = ums.begin(); it != ums.end(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
ums total buckets = 17 ums total elements = 9 ums values = Sun Tue Wed Thu Thu Fri Fri Mon Sat
في المثال التالي قمنا بتعريف كائن من unordered_multiset
مخصص لتخزين قيم نوعها string
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بعرض القيم الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
ملاحظة: قمنا باستخدام الدالة bucket_count()
لمعرفة كم Bucket تم إنشاؤها بشكل تلقائي و الدالة bucket_size()
لمعرفة عدد العناصر الموجودة في كل Bucket.
المثال الثاني
#include <iostream> #include <unordered_set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string يمكنه أن يحتوي على عناصر نوعها unordered_multiset هنا قمنا بتعريف كائن من الكلاس unordered_multiset<string> ums = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = ums.bucket_count(); // ums الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] elements:"; // و من ثم طباعة القيم الموجودة فيها بواسطة الحلقة التالية for(auto it=ums.begin(i); it!=ums.end(i); ++it) { cout << " " << *it; } cout << endl; } }
•سنحصل على النتيجة التالية عند التشغيل.
bucket[0] elements: Fri bucket[1] elements: bucket[2] elements: Sat Mon bucket[3] elements: bucket[4] elements: Sun Wed bucket[5] elements: bucket[6] elements: bucket[7] elements: Tue bucket[8] elements: bucket[9] elements: bucket[10] elements: Thu
في المثال التالي قمنا بتعريف كائن من unordered_multiset
مخصص لتخزين قيم نوعها string
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بعرض القيم الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
ملاحظة: قمنا باستخدام الدالة bucket_count()
لمعرفة كم Bucket تم إنشاؤها بشكل تلقائي, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها. عند عرض قيم العناصر الموجودة في كل Bucket قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول فيها لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير فيها لأننا سنتوقف عنده.
المثال الثالث
#include <iostream> #include <unordered_set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string يمكنه أن يحتوي على عناصر نوعها unordered_multiset هنا قمنا بتعريف كائن من الكلاس unordered_multiset<string> ums = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = ums.bucket_count(); // ums الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // و عدد العناصر الموجودة فيها Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] total elements = " << ums.bucket_size(i); cout << endl; } }
•سنحصل على النتيجة التالية عند التشغيل.
bucket[0] total elements = 1 bucket[1] total elements = 0 bucket[2] total elements = 2 bucket[3] total elements = 0 bucket[4] total elements = 2 bucket[5] total elements = 0 bucket[6] total elements = 0 bucket[7] total elements = 1 bucket[8] total elements = 0 bucket[9] total elements = 0 bucket[10] total elements = 1
في المثال التالي قمنا بتعريف كائن من unordered_multiset
مخصص لتخزين قيم نوعها string
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بالبحث عن قيم محددة فيه لمعرفة كم عنصر يملك هذه القيم.
ملاحظة: قمنا باستخدام الدالة count()
لمعرفة كم مرة القيم مكررة في الكائن.
المثال الرابع
#include <iostream> #include <unordered_set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string يمكنه أن يحتوي على عناصر نوعها unordered_multiset هنا قمنا بتعريف كائن من الكلاس unordered_multiset<string> ums = {"Apple", "Orange", "Apple", "Tomato", "Banana", "Pineapple", "Blueberry"}; // "Apple" التي تملك القيمة ums هنا قمنا بطباعة عدد العناصر الموجودة في الكائن cout << "'Apple' is exist " << ums.count("Apple") << " time(s)\n"; // "Carrot" التي تملك القيمة ums هنا قمنا بطباعة عدد العناصر الموجودة في الكائن cout << "'Carrot' is exist " << ums.count("Carrot") << " time(s)"; return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
'Apple' is exist 2 time(s) 'Carrot' is exist 0 time(s)
في المثال التالي قمنا بتعريف كائن من unordered_multiset
مخصص لتخزين قيم نوعها string
مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بالبحث عن أول عنصر يملك قيمة محددة فيه و في حال كانت موجودة سنقوم بحذف العنصر الذي يملكها من الكائن.
ملاحظة: قمنا باستخدام الدالة find()
للبحث عن القيمة في الكائن و الدالة erase()
لحذف العنصر من الكائن.
#include <iostream> #include <unordered_set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string يمكنه أن يحتوي على عناصر نوعها unordered_multiset هنا قمنا بتعريف كائن من الكلاس unordered_multiset<string> ums = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; // لتخزين مكان العنصر الذي نجد القيمة التي نبحث عنها فيه unordered_multiset<string>::iterator منا قمنا بتعريف كائن من unordered_multiset<string>::iterator it; // it عن عنصر يملك القيمة 4, و بالتالي في حال وجود عنصر يملك القيمة 4 سيتم تخزين عنوانه في الكائن ums هنا قمنا بالبحث في الكائن // فيه للإشارة إلى أنه لم يتم إيجاد أي عنصر يملك هذه القيمة ums.end() في حال عدم وجود عنصر يملك القيمة 4 سيتم تخزين القيمة التي ترجعها it = ums.find("Wed"); // فهذا يعني أنه تم إيجاد القيمة و بالتالي سيتم تنفيذ الكود الموضوع فيها ums.end() لا تساوي القيمة التي ترجعها الدالة it في حال كانت قيمة if (it != ums.end()) { // و من ثم قمنا بحذفه ums هنا قمنا بطباعة قيمة العنصر الذي تم إيجاده في الكائن cout << "First element with value '"<< *it << "' is removed from ums\n"; ums.erase(it); } cout << "ums values ="; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه ums هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = ums.begin(); it != ums.end(); ++it) { cout << " " << *it; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
First element with value 'Wed' is removed from ums ums values = Fri Thu Sun Tue Sat Mon
في المثال التالي قمنا بتعريف كائنين من unordered_multiset
مع تحديد أنه يمكن أن يحتويان على عناصر نوعها int
.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة القيم التي أصبحت موجودة في كلٍّ منهما.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل قيمهما.
المثال السادس
#include <iostream> #include <unordered_set> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيهما int يمكنهما أن يحتويان على قيم نوعها unordered_multiset هنا قمنا بتعريف كائنين من الكلاس unordered_multiset<int> ums1 = {1, 2, 3, 4}; unordered_multiset<int> ums2 = {5, 6, 7, 8}; // ums2 مع قيم الكائن ums1 هنا قمنا بتبديل قيم الكائن ums1.swap(ums2); cout << "ums1 values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه ums1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = ums1.begin(); it != ums1.end(); ++it) { cout << *it << " "; } cout << "\nums2 values = "; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه ums2 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيمة عنصر جديد من العناصر الموجودة في الكائن for (auto it = ums2.begin(); it != ums2.end(); ++it) { cout << *it << " "; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
ums1 values = 8 7 6 5 ums2 values = 4 3 2 1
في المثال التالي قمنا بتعريف كائن من unordered_multiset
مخصص لتخزين قيم نوعها int
مع تحديد الطريقة التي سيتم على أساسها توزيع القيم في Buckets و إضافة عدة قيم فيه عند تعريفه.
لتحديد الطريقة التي سيتم على أساسها توزيع القيم في Buckets قمنا بإنشاء كلاس إسمه Hash
و إعادة تعريف العامل ()
حتى يقارن قيمة أي عنصر نريد إضافته نسبةً لعدد الأحرف الموجودة فيه, عندها يتم وضع الأعداد التي تتألف من رقم واحد في Bucket, و الأعداد التي تتألف من رقم رقمين في Bucket, و الأعداد التي تتألف من ثلاثة أعداد في Bucket و هكذا..
في النهاية قمنا بعرض القيم الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
المثال السابع
#include <iostream> #include <unordered_set> using namespace std; // unordered_multiset سنستخدمه لاحقاً لتحديد كيف ستترتب العناصر في الحاوية التي ننشئها من الكلاس Hash هنا قمنا بتعريف كلاس إسمه class Hash { public: // Bucket حتى يقرر في أي unordered_multiset هنا قمنا بتعريف العامل الذي سيستخدمه الكائن الذي ننشئه من الكلاس // val سيتم وضع العنصر الذي نضيفه فيه مع الإشارة إلى أن القيمة التي يملكها العنصر سيتم تمريرها مكان الباراميتر size_t operator() (const int &val) const { // بشكل مؤقت لأننا نحتاج إجراء تعديل عليها val سيتم وضع قيمة num المتغير // val سنستخدمه لحساب عدد الأرقام الموجودة في المتغير digits المتغير int num = val; int digits = 1; // num و من ثم حذف أول رقم في المتغير digits هنا قمنا بإنشاء حلقة تقوم في كل دورة بإضافة واحد على قيمة المتغيرد // num تمثل عدد الأرقام الموجودة في العدد الذي كان يحتويه المتغير digits عندما تتوقف هذه الحلقة ستكون قيمة المتغير while (num != 0) { digits++; num = num / 10; } // سيتم إضافة العنصر Bucket لأنها التي ستحدد في digits في النهاية سيتم إرجاع قيمة المتغير return digits; } }; int main() { // مع تحديد أنه يعتمد على الكلاس string يمكنه أن يحتوي على عناصر نوعها unordered_multiset هنا قمنا بتعريف كائن من الكلاس // من أجل تحديد الطريقة التي سيتم فيها ترتيب العناصر التي نضيفها فيه, بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه Hash unordered_multiset<int, Hash> ums = {6, 34, 72, 3, 1, 123, 55, 100, 2020}; // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = ums.bucket_count(); // ums الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] elements:"; // و من ثم طباعة القيم الموجودة فيها بواسطة الحلقة التالية for(auto it=ums.begin(i); it!=ums.end(i); ++it) { cout << " " << *it; } cout << endl; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل, و لاحظ كيف تم ترتيب العناصر على أساس عدد الأرقام التي يتألف منها كل عنصر.
bucket[0] elements: bucket[1] elements: 1 3 6 bucket[2] elements: 55 72 34 bucket[3] elements: 100 123 bucket[4] elements: 2020 bucket[5] elements: bucket[6] elements: bucket[7] elements: bucket[8] elements: bucket[9] elements: bucket[10] elements:
الكلاس unordered_map
تعريف الكلاس unordered_map
في C++
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11
و هو يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل جدول يتألف من عمودين حيث يتكون كل عنصر من مفتاح ( Key ) يوضع في العمود الأول و قيمة ( Value ) توضع في العمود الثاني بالإضافة إلى أنها ترتب العناصر بالإعتماد على دالة مخصصة لذلك إسمها Hash()
تقوم بالتشييك على مفتاح أي عنصر سيتم إدخاله لتحديد المكان الذي يجب وضعه فيها.
بالمبدأ الدالة Hash()
تقوم بإجراء عملية حسابية على مفتاح أي عنصر يتم إدخاله.
أي ناتج ترجعه الدالة Hash()
يتم تخزينه في الذاكرة في مكان خاص يقال له Bucket.
أي عنصر جديد يتم إضافته تقوم الدالة Hash()
بإجراء العملية الحسابية عليه و مقارنة الناتج النهائي مع قيمة كل Buckets نتجت سابقاً و في حال تطابق الناتج مع قيمة أي Bucket سيتم وضعه في آخرها, أما في حال عدم تطابق الناتج مع قيمة أي Bucket سيتم إضافة Bucket جديد و وضعه فيها كالتالي.
القيمة المفتاحية لكل عنصر يمكن أن تكون من أي نوع تريده, و لكن في أغلب الأوقات ستكون المفاتيح عبارة عن أعداد أو كلمات.
لا تستطيع وضع نفس القيمة المفتاحية لأكثر من عنصر و هذا شيء منطقي لأن المفاتيح هي ما يميز العناصر عن بعضها.
لاستخدام الكلاس unordered_map
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<unordered_map>
لأنه موجود فيه.
بناء الكلاس
template < class Key, // unordered_map::key_type class T, // unordered_map::mapped_type class Hash = hash<Key>, // unordered_map::hasher class Pred = equal_to<Key>, // unordered_map::key_equal class Alloc = allocator< pair<const Key,T> > // unordered_map::allocator_type > class unordered_map;
إذاً عند إنشاء كائن من الكلاس unordered_map
يجب أن نمرر له نوع المفاتيح التي نريد تخزينها فيه مكان الباراميتر Key
و نوع القيم التي نريد تخزينها فيه مكان الباراميتر T
.
دوال الكلاس unordered_map
في C++
الجدول التالي يحتوي على دوال الكلاس unordered_map
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
local_iterator begin(size_t n)
ترجع كائن iterator يشير لمكان أول عنصر بداخل Bucket محدد في الكائن الذي قام باستدعائها.مكان الباراميتر n نمرر رقم الـ Bucket الذي نريد البدأ من أول عنصر موجود فيه. |
|
local_iterator end(size_t n)
ترجع كائن iterator يشير لمكان آخر عنصر بداخل Bucket محدد في الكائن الذي قام باستدعائها.مكان الباراميتر n نمرر رقم الـ Bucket الذي نريد الوقوف عند آخر عنصر موجود فيه. |
الجدول التالي يحتوي على دوال الكلاس unordered_map
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس unordered_map
التي تستخدم للوصول لقيم عناصره.
الدالة مع تعريفها | |
---|---|
unordered_mapped_type& at(key_type& k)
تستخدم للوصول لقيمة عنصر محدد في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.مكان الباراميتر k نمرر لها مفتاح العنصر الذي نريد الوصول إليه.ترمي الإستثناء out_of_range في حال كانت قيمة k لا تمثل القيمة المفتاحية لأي عنصر موجود في الكائن.معلومة: يمكنك استخدام العامل [] للوصول للعنصر و لكن عليك معرفة أن استخدام هذا العامل لا يرمي إستثناء في حال تمرير قيمة مفتاح غير موجود في الكائن. |
|
operator[] (key_type& k)
يستخدم العامل [] للوصول لقيمة عنصر محدد في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.مكان الباراميتر k نمرر لها مفتاح العنصر الذي نريد الوصول إليه.في حال تمرير قيمة مفتاح غير موجود مكان الباراميتر k سيتم إضافة العنصر كعنصر جديد في الكائن. |
الجدول التالي يحتوي على دوال الكلاس unordered_map
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
pair<K, V> insert({key, value})
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها.مكان الباراميتر key نمرر القيمة المفتاحية للعنصر الذي نريد إضافته.مكان الباراميتر value نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.كما أنها ترجع نسخة من العنصر الذي تم إضافته. |
|
pair<K, V> emplace(Args&&... args)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها تماماً كالدالة insert() .مكان الباراميتر Args نمرر القيمة المفتاحية للعنصر الذي نريد إضافته ثم نضع فاصلة و نمرر القيمة التي نريد وضعها فيه.كما أنها ترجع نسخة من العنصر الذي تم إضافته. |
|
size_t erase(key_type& k)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها من خلال المفتاح الخاص به.مكان الباراميتر k نمرر مفتاح العنصر الذي نريد حذفه. |
|
iterator erase(const_iterator position)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها من خلال الإشارة إلى مكانه فيه.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه. |
|
iterator erase(const_iterator first, const_iterator last)
تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها من خلال الإشارة إلى مكان وجود هذه العناصر.مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده. |
|
void swap(unordered_map& anotherMap)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherMap نمرر لها كائن من الكلاس unordered_map يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس unordered_map
التي تستخدم للبحث فيه.
الدالة مع تعريفها | |
---|---|
size_t count(T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن عنصر يملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع القيمة 1 و في حال لم يتم إيجاد عنصر يملك نفس القيمة ترجع القيمة 0 . |
|
iterator find(const T& val)
تستخدم للبحث في الكائن الذي قام باستدعائها عن عنصر يملك قيمة محددة.مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator يشير لعنوان العنصر في الذاكرة.و في حال لم يتم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator قيمته تساوي القيمة التي ترجعها الدالة end() . |
أمثلة شاملة حول التعامل مع الكلاس unordered_map
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من unordered_map
مع تحديد أن عناصره تتكون من مفاتيح نوعها string
قيم و نوعها string
أيضاً.
بعدها قمنا بإضافة بعض العناصر فيه, كل عنصر عبارة منهم عبارة عن كود الإتصال الخاص بالبلد و إسم البلد.
بعدها قمنا بطباعة عدد العناصر التي قمنا بإضافتها.
في الأخير قمنا بعرض جميع مفاتيح و قيم العناصر الموجودة فيه بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة emplace()
لإضافة العناصر, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير لأننا سنتوقف عنده.
المثال الأول
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها string يمكنه أن يحتوي على مفاتيح نوعها unordered_map هنا قمنا بتعريف كائن من الكلاس unordered_map<string, string> um; // كل عنصر يحتوي على كود البلد كمفتاح و إسمه كقيمة ,um هنا قمنا بإضافة 12 عنصر في الكائن um.emplace("+961", "Lebanon"); um.emplace("+962", "Jordan"); um.emplace("+963", "Syria"); um.emplace("+964", "Iraq"); um.emplace("+965", "Kuwait"); um.emplace("+966", "KSA"); um.emplace("+967", "Yaman"); um.emplace("+968", "Oman"); um.emplace("+970", "Palestine"); um.emplace("+212", "Morocco"); um.emplace("+281", "Libya"); um.emplace("+20", "Egypt"); // size() باستخدام الدالة um هنا قمنا بطباعة عدد عناصر الكائن cout << "um size = " << um.size() << "\n\n"; cout << "um keys and values\n"; cout << "---------------------\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه um هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = um.begin(); it != um.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << "\t | " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
um size = 12 um keys and values --------------------- +20 | Egypt +281 | Libya +212 | Morocco +967 | Yaman +970 | Palestine +962 | Jordan +968 | Oman +961 | Lebanon +963 | Syria +966 | KSA +965 | Kuwait +964 | Iraq
في المثال التالي قمنا بتعريف كائن من unordered_map
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بعرض القيم الموجودة فيه بواسطة حلقة.
المثال الثاني
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها unordered_map هنا قمنا بتعريف كائن من الكلاس unordered_map<int, string> um = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"}, }; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه um هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = um.begin(); it != um.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
5 - Five 4 - Four 3 - Three 2 - Two 1 - One
في المثال التالي قمنا بتعريف كائن من unordered_map
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بالبحث عن عنصر يملك مفتاح محدد لمعرفة ما إن كان يوجد عنصر يملك هذا المفتاح أم لا مع الإشارة إلى أنه في حال وجود عنصر يملك هذا المفتاح سيتم طباعة قيمته أيضاً.
ملاحظة: قمنا باستخدام الدالة count()
للبحث عن عنصر يملك مفتاح محدد في الكائن و قمنا باستخدام الدالة at()
لطباعة قيمة العنصر الذي يملك مفتاح محدد.
المثال الثالث
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها unordered_map هنا قمنا بتعريف كائن من الكلاس unordered_map<int, string> um = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"}, }; // يوجد فيه عنصر يملك مفتاح يساوي 4 أم لا um هنا قمنا بطباعة ما إن كان الكائن if (um.count(4)) { // إن كان فيه سيتم تنفيذ أمر الطباعة التالي cout << "Element with key '4' is exist and it's value = " << um.at(4); } else { // إن لم يكن فيه سيتم تنفيذ أمر الطباعة التالي cout << "There is no element with key = 4"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Element with key '4' is exist and it's value = Four
في المثال التالي قمنا بتعريف كائن من unordered_map
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بحذف عنصر منه بالإعتماد على قيمة مفتاحه و من ثم طباعة قيم جميع العناصر المتبقية بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة erase()
لحذف العنصر.
المثال الرابع
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها unordered_map هنا قمنا بتعريف كائن من الكلاس unordered_map<int, string> um = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"} }; // um هنا قمنا بحذف العنصر الذي يملك مفتاح يساوي 3 في الكائن um.erase(3); // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه um هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = um.begin(); it != um.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Element with key '4' is removed from um um keys and values: 5 - Five 3 - Three 2 - Two 1 - One
في المثال التالي قمنا بتعريف كائن من unordered_map
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بالبحث عن عنصر يملك مفتاح محدد فيه و في حال وجوده سيتم حذف العنصر من الكائن.
في الأخير قمنا بطباعة قيم جميع العناصر المتبقية بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة find()
للبحث عن العنصر الذي يملك المفتاح في الكائن و الدالة erase()
لحذف العنصر من الكائن.
المثال الخامس
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها unordered_map هنا قمنا بتعريف كائن من الكلاس unordered_map<int, string> um = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"} }; // لتخزين مكان العنصر الذي نجد القيمة التي نبحث عنها فيه unordered_map<int, string>::iterator منا قمنا بتعريف كائن من unordered_map<int, string>::iterator it; // it عن عنصر يملك مفتاح يساوي 4, و بالتالي في حال وجود عنصر يملك هذا المفتاح سيتم تخزين عنوانه في الكائن um هنا قمنا بالبحث في الكائن // فيه للإشارة إلى أنه لم يتم إيجاد أي عنصر يملك هذا المفتاح um.end() في حال عدم وجود عنصر يملك مفتاح يساوي 4 سيتم تخزين القيمة التي ترجعها it = um.find(4); // فهذا يعني أنه تم إيجاد العنصر و بالتالي سيتم تنفيذ الكود الموضوع بالداخل um.end() لا تساوي القيمة التي ترجعها الدالة it في حال كانت قيمة if (it != um.end()) { // و من ثم قمنا بحذفه um هنا قمنا بطباعة مفتاح العنصر الذي تم إيجاده في الكائن cout << "Element with key '"<< it->first << "' is removed from um\n\n"; um.erase(it); } cout << "um keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه um هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = um.begin(); it != um.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Element with key '4' is removed from um um keys and values: 1 - One 2 - Two 3 - Three 5 - Five
في المثال التالي قمنا بتعريف كائنين من unordered_map
مع تحديد أن عناصرهما تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة قيم عناصرهما بواسطة حلقة للتأكد من أن التبديل قد تم بنجاح.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل عناصرهما.
المثال السادس
#include <iostream> #include <unordered_map> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها unordered_map هنا قمنا بتعريف كائن من الكلاس unordered_map<int, string> um1 = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"} }; // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها unordered_map هنا قمنا بتعريف كائن آخر من الكلاس unordered_map<int, string> um2 = { {5, "Five"}, {6, "Six"}, {7, "Seven"}, {8, "Eight"} }; // um2 مع قيم الكائن um1 هنا قمنا بتبديل قيم الكائن um1.swap(um2); cout << "um1 keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه um1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = um1.begin(); it != um1.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } cout << "\num2 keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه um2 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = um2.begin(); it != um2.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
um1 keys and values: 8 - Eight 7 - Seven 6 - Six 5 - Five um2 keys and values: 4 - Four 3 - Three 2 - Two 1 - One
في المثال التالي قمنا بتعريف كائن من unordered_map
مع تحديد أن عناصره تتكون من مفاتيح نوعها string
قيم و نوعها string
أيضاً.
بعدها قمنا بإضافة بعض العناصر فيه, كل عنصر عبارة منهم عبارة عن كود الإتصال الخاص بالبلد و إسم البلد.
في الأخير قمنا بعرض مفاتيح و قيم العناصر الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
ملاحظة: قمنا باستخدام الدالة bucket_count()
لمعرفة كم Bucket تم إنشاؤها بشكل تلقائي و الدالة bucket_size()
لمعرفة عدد العناصر الموجودة في كل Bucket.
المثال السابع
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها string يمكنه أن يحتوي على مفاتيح نوعها unordered_map هنا قمنا بتعريف كائن من الكلاس unordered_map<string, string> um; // كل عنصر يحتوي على كود البلد كمفتاح و إسمه كقيمة ,um هنا قمنا بإضافة 12 عنصر في الكائن um.emplace("+961", "Lebanon"); um.emplace("+962", "Jordan"); um.emplace("+963", "Syria"); um.emplace("+964", "Iraq"); um.emplace("+965", "Kuwait"); um.emplace("+966", "KSA"); um.emplace("+967", "Yaman"); um.emplace("+968", "Oman"); um.emplace("+970", "Palestine"); um.emplace("+212", "Morocco"); um.emplace("+281", "Libya"); um.emplace("+20", "Egypt"); // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = um.bucket_count(); // um الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] elements:"; // و من ثم طباعة مفتاح و قيمة كل عصنر موجود فيها الحلقة التالية for(auto it=um.begin(i); it!=um.end(i); ++it) { cout << " [" << it->first << " : " << it->second << "]"; } cout << endl; } }
•سنحصل على النتيجة التالية عند التشغيل.
bucket[0] elements: bucket[1] elements: bucket[2] elements: bucket[3] elements: bucket[4] elements: [+963 : Syria] bucket[5] elements: [+967 : Yaman] bucket[6] elements: [+966 : KSA] [+965 : Kuwait] bucket[7] elements: [+968 : Oman] [+961 : Lebanon] bucket[8] elements: bucket[9] elements: bucket[10] elements: [+281 : Libya] [+212 : Morocco] bucket[11] elements: [+970 : Palestine] [+962 : Jordan] bucket[12] elements: bucket[13] elements: [+20 : Egypt] bucket[14] elements: bucket[15] elements: [+964 : Iraq] bucket[16] elements:
في المثال التالي قمنا بتعريف كائن من unordered_map
مخصص لتخزين عناصر تتكون من مفاتيح نوعها string
و قيم نوعها string
أيضاً مع إضافة عدة قيم فيه عند تعريفه.
بعدها قمنا بعرض عدد العناصر الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
ملاحظة: قمنا باستخدام الدالة bucket_count()
لمعرفة كم Bucket تم إنشاؤها بشكل تلقائي.
المثال الثامن
#include <iostream> #include <unordered_map> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string يمكنه أن يحتوي على عناصر نوعها unordered_map هنا قمنا بتعريف كائن من الكلاس unordered_map<string, string> um = { {"+961", "Lebanon"}, {"+962", "Jordan"}, {"+963", "Syria"}, {"+964", "Iraq"}, {"+965", "Kuwait"}, {"+966", "KSA"}, {"+967", "Yaman"}, {"+968", "Oman"}, {"+970", "Palestine"}, {"+212", "Morocco"}, {"+281", "Libya"}, {"+20", "Egypt"} }; // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = um.bucket_count(); // um الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // و عدد العناصر الموجودة فيها Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] total elements = " << um.bucket_size(i); cout << endl; } }
•سنحصل على النتيجة التالية عند التشغيل.
bucket[0] total elements = 1 bucket[1] total elements = 0 bucket[2] total elements = 1 bucket[3] total elements = 2 bucket[4] total elements = 0 bucket[5] total elements = 0 bucket[6] total elements = 3 bucket[7] total elements = 1 bucket[8] total elements = 0 bucket[9] total elements = 1 bucket[10] total elements = 1 bucket[11] total elements = 0 bucket[12] total elements = 2
في المثال التالي قمنا بتعريف كائن من unordered_map
مخصص لتخزين مفاتيح نوعها string
و قيم نوعها string
أيضاً مع تحديد الطريقة التي سيتم على أساسها توزيع العناصر في Buckets و إضافة عدة عناصر فيه عند تعريفه.
لتحديد الطريقة التي سيتم على أساسها توزيع العناصر في Buckets قمنا بإنشاء كلاس إسمه Hash
و إعادة تعريف العامل ()
حتى يقارن مفتاح أي عنصر نريد إضافته نسبةً لعدد الأحرف الموجودة فيه, عندها يتم وضع العناصر التي تملك مفتاح يتألف من حرف واحد في Bucket, و العناصر التي تملك مفتاح يتألف من حرفين في Bucket, و العناصر التي تملك مفتاح يتألف من ثلاثة أحرف في Bucket و هكذا..
في النهاية قمنا بعرض المفاتيح الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
المثال التاسع
#include <iostream> #include <unordered_map> using namespace std; // unordered_map سنستخدمه لاحقاً لتحديد كيف ستترتب العناصر في الحاوية التي ننشئها من الكلاس Hash هنا قمنا بتعريف كلاس إسمه class Hash { public: // Bucket حتى يقرر في أي unordered_map هنا قمنا بتعريف العامل الذي سيستخدمه الكائن الذي ننشئه من الكلاس // key سيتم وضع العنصر الذي نضيفه فيه مع الإشارة إلى أن المفتاح الذي يملكه العنصر سيتم تمريره مكان الباراميتر size_t operator() (const string &key) const { // سيتم إضافة العنصر Bucket في النهاية سيتم إرجاع عدد أحرف مفتاح العنصر لأنها التي ستحدد في أي return key.length(); } }; int main() { // مع تحديد أنه يعتمد string يمكنه أن يحتوي على عناصر مفاتيحها و قيمها نوعها unordered_map هنا قمنا بتعريف كائن من الكلاس // من أجل تحديد الطريقة التي سيتم فيها ترتيب العناصر التي نضيفها فيه, بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه Hash على الكلاس unordered_map<string, string, Hash> um = { {"HTML", "Hyper Text Markup Language"}, {"CSS", "Cascading Style Sheet"}, {"CS", "Computer Science"}, {"Algo", "Algorithms"}, {"OOP", "Object Oriented Programming"}, {"DB", "Database"}, {"SQL", "Structured Query Language"} }; // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = um.bucket_count(); // um الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] elements:"; // و من ثم طباعة مفاتيح العناصر الموجودة فيها بواسطة الحلقة التالية for(auto it=um.begin(i); it!=um.end(i); ++it) { cout << " " << it->first; } cout << endl; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل, و لاحظ كيف تم ترتيب العناصر على أساس عدد الأحرف التي يتألف منها كل عنصر.
bucket[0] elements: bucket[1] elements: bucket[2] elements: DB CS bucket[3] elements: SQL OOP CSS bucket[4] elements: Algo HTML bucket[5] elements: bucket[6] elements: bucket[7] elements: bucket[8] elements: bucket[9] elements: bucket[10] elements:
الكلاس unordered_multimap
تعريف الكلاس unordered_multimap
في C++
تم إضافة هذا الكلاس إبتداءاً من الإصدر c++11
و هو يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل جدول يتألف من عمودين حيث يتكون كل عنصر من مفتاح ( Key ) يوضع في العمود الأول و قيمة ( Value ) توضع في العمود الثاني بالإضافة إلى أنها ترتب العناصر بالإعتماد على دالة مخصصة لذلك إسمها Hash()
تقوم بالتشييك على مفتاح أي عنصر سيتم إدخاله لتحديد المكان الذي يجب وضعه فيها مع الإشارة إلى أنه يمكن وضع نفس المفتاح لأكثر من عنصر.
بالمبدأ الدالة Hash()
تقوم بإجراء عملية حسابية على مفتاح أي عنصر يتم إدخاله.
أي ناتج ترجعه الدالة Hash()
يتم تخزينه في الذاكرة في مكان خاص يقال له Bucket.
أي عنصر جديد يتم إضافته تقوم الدالة Hash()
بإجراء العملية الحسابية عليه و مقارنة الناتج النهائي مع قيمة كل Buckets نتجت سابقاً و في حال تطابق الناتج مع قيمة أي Bucket سيتم وضعه في آخرها, أما في حال عدم تطابق الناتج مع قيمة أي Bucket سيتم إضافة Bucket جديد و وضعه فيها كالتالي.
القيمة المفتاحية لكل عنصر يمكن أن تكون من أي نوع تريده, و لكن في أغلب الأوقات ستكون المفاتيح عبارة عن أعداد أو كلمات.
معلومة تقنية
الفرق الوحيد بين الحاوية التي تنشئها من الكلاس unordered_map
و الحاوية التي تنشئها من الكلاس unordered_multimap
هو أن هذا الأخير يمكنه أن يستخدم نفس المفتاح لأكثر من عنصر.
الآن, بما أن مفاتيح العناصر في هذه الحاوية يمكن أن تكون مكررة فهذا يعني أنه لا يمكنك الإعتماد على قيم المفاتيح للتفرقة بين العناصر حيث أن المفتاح الواحد يمكن أن يرمز لعدة عناصر.
لاستخدام الكلاس unordered_multimap
- أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<unordered_multimap>
لأنه موجود فيه.
بناء الكلاس
template < class Key, // unordered_multimap::key_type class T, // unordered_multimap::mapped_type class Hash = hash<Key>, // unordered_multimap::hasher class Pred = equal_to<Key>, // unordered_multimap::key_equal class Alloc = allocator< pair<const Key,T> > // unordered_multimap::allocator_type > class unordered_multimap;
إذاً عند إنشاء كائن من الكلاس unordered_multimap
يجب أن نمرر له نوع المفاتيح التي نريد تخزينها فيه مكان الباراميتر Key
و نوع القيم التي نريد تخزينها فيه مكان الباراميتر T
.
دوال الكلاس unordered_multimap
في C++
الجدول التالي يحتوي على دوال الكلاس unordered_multimap
التي تستخدم للحصول على عداد يتيح المرور على عناصره.
الدالة مع تعريفها | |
---|---|
iterator begin()
ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
iterator end()
ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر. |
|
local_iterator begin(size_t n)
ترجع كائن iterator يشير لمكان أول عنصر بداخل Bucket محدد في الكائن الذي قام باستدعائها.مكان الباراميتر n نمرر رقم الـ Bucket الذي نريد البدأ من أول عنصر موجود فيه. |
|
local_iterator end(size_t n)
ترجع كائن iterator يشير لمكان آخر عنصر بداخل Bucket محدد في الكائن الذي قام باستدعائها.مكان الباراميتر n نمرر رقم الـ Bucket الذي نريد الوقوف عند آخر عنصر موجود فيه. |
الجدول التالي يحتوي على دوال الكلاس unordered_multimap
التي تستخدم للحصول على عدد عناصره.
الدالة مع تعريفها | |
---|---|
bool empty()
تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك. |
|
size_t size()
تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها. |
|
size_t max_size()
تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس unordered_multimap
التي تستخدم للوصول لقيم عناصره.
الدالة مع تعريفها | |
---|---|
unordered_multimapped_type& at(key_type& k)
تستخدم للوصول لقيمة عنصر محدد في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.مكان الباراميتر k نمرر لها مفتاح العنصر الذي نريد الوصول إليه.ترمي الإستثناء out_of_range في حال كانت قيمة k لا تمثل القيمة المفتاحية لأي عنصر موجود في الكائن.معلومة: يمكنك استخدام العامل [] للوصول للعنصر و لكن عليك معرفة أن استخدام هذا العامل لا يرمي إستثناء في حال تمرير قيمة مفتاح غير موجود في الكائن. |
|
operator[] (key_type& k)
يستخدم العامل [] للوصول لقيمة عنصر محدد في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.مكان الباراميتر k نمرر لها مفتاح العنصر الذي نريد الوصول إليه.في حال تمرير قيمة مفتاح غير موجود مكان الباراميتر k سيتم إضافة العنصر كعنصر جديد في الكائن. |
الجدول التالي يحتوي على دوال الكلاس unordered_multimap
التي تستخدم للتحكم بعناصره.
الدالة مع تعريفها | |
---|---|
pair<K, V> insert({key, value})
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها.مكان الباراميتر key نمرر القيمة المفتاحية للعنصر الذي نريد إضافته.مكان الباراميتر value نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.كما أنها ترجع نسخة من العنصر الذي تم إضافته. |
|
pair<K, V> emplace(Args&&... args)
تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها تماماً كالدالة insert() .مكان الباراميتر Args نمرر القيمة المفتاحية للعنصر الذي نريد إضافته ثم نضع فاصلة و نمرر القيمة التي نريد وضعها فيه.كما أنها ترجع نسخة من العنصر الذي تم إضافته. |
|
size_t erase(key_type& k)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها من خلال المفتاح الخاص به.مكان الباراميتر k نمرر مفتاح العنصر الذي نريد حذفه. |
|
iterator erase(const_iterator position)
تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها من خلال الإشارة إلى مكانه فيه.مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه. |
|
iterator erase(const_iterator first, const_iterator last)
تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها من خلال الإشارة إلى مكان وجود هذه العناصر.مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده. |
|
void swap(unordered_multimap& anotherMap)
تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.مكان الباراميتر anotherMap نمرر لها كائن من الكلاس unordered_multimap يملك نفس نوع عناصر الكائن الذي قام باستدعائها. |
الجدول التالي يحتوي على دوال الكلاس unordered_multimap
التي تستخدم للبحث فيه.
الدالة مع تعريفها | |
---|---|
size_t count(const key_type& k)
تستخدم لمعرفة عدد العناصر التي تملك مفتاح محدد في الكائن الذي قام باستدعائها.مكان الباراميتر k نمرر المفتاح الذي نريد معرفة عدد العناصر التي تملكه. |
|
iterator find(const T& k)
تستخدم للبحث في الكائن الذي قام باستدعائها عن مكان أول عنصر يملك مفتاح محدد.مكان الباراميتر k نمرر المفتاح الذي نريد البحث عن أول عنصر يملكه.في حال تم إيجاد عنصر يملك نفس المفتاح الذي تم تمريره لها ترجع كائن من Iterator يشير لعنوان العنصر في الذاكرة.و في حال لم يتم إيجاد عنصر يملك نفس المفتاح الذي تم تمريره لها ترجع كائن من Iterator قيمته تساوي القيمة التي ترجعها الدالة end() . |
أمثلة شاملة حول التعامل مع الكلاس unordered_unordered_multimap
في C++
في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.
في المثال التالي قمنا بتعريف كائن من unordered_multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها string
قيم و نوعها string
أيضاً.
بعدها قمنا بإضافة بعض العناصر فيه, كل عنصر عبارة منهم عبارة عن إسم البلد كمفتاح و إسم مدينة موجودة فيه كقيمة.
بعدها قمنا بطباعة عدد العناصر التي قمنا بإضافتها.
في الأخير قمنا بعرض جميع مفاتيح و قيم العناصر الموجودة فيه بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة emplace()
لإضافة العناصر, الدالة size()
لمعرفة عدد العناصر التي تم إضافتها. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة begin()
للحصول على مؤشر للعنصر الأول لأننا سنبدأ من عنده و الدالة end()
للحصول على مؤشر للعنصر الأخير لأننا سنتوقف عنده.
المثال الأول
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها string يمكنه أن يحتوي على مفاتيح نوعها unordered_multimap هنا قمنا بتعريف كائن من الكلاس unordered_multimap<string, string> um; // كل عنصر يحتوي على إسم البلد كمفتاح و إحدى مدنه كقيمة ,um هنا قمنا بإضافة 12 عنصر في الكائن um.emplace("Egypt", "Giza"); um.emplace("Lebanon", "Beirut"); um.emplace("Syria", "Sweida"); um.emplace("Lebanon", "Tripolie"); um.emplace("Syria", "Idlib"); um.emplace("KSA", "Riyadh"); um.emplace("Egypt", "Cairo"); um.emplace("Lebanon", "Sidon"); um.emplace("Syria", "Damascus"); um.emplace("KSA", "Makkah"); um.emplace("Syria", "Homs"); um.emplace("Algeria", "Algiers"); // size() باستخدام الدالة um هنا قمنا بطباعة عدد عناصر الكائن cout << "um size = " << um.size() << "\n\n"; cout << "um keys and values\n"; cout << "---------------------\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه um هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = um.begin(); it != um.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << "\t | " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
um size = 12 um keys and values --------------------- Algeria | Algiers Lebanon | Sidon Lebanon | Tripolie Lebanon | Beirut KSA | Makkah KSA | Riyadh Egypt | Cairo Egypt | Giza Syria | Homs Syria | Damascus Syria | Idlib Syria | Sweida
في المثال التالي قمنا بتعريف كائن من unordered_multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بإضافة بعض العناصر فيه, كل عنصر عبارة منهم عبارة عن عدد و كمفتاح و إسمه باللغة الإنجليزية أو الفرنسية كقيمة.
بعدها قمنا بعرض القيم الموجودة فيه بواسطة حلقة.
المثال الثاني
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها unordered_multimap هنا قمنا بتعريف كائن من الكلاس unordered_multimap<int, string> um = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {5, "Five"}, }; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه um هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = um.begin(); it != um.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
5 - Five 4 - Four 3 - Three 2 - Two 1 - One
في المثال التالي قمنا بتعريف كائن من unordered_multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها string
قيم و نوعها string
أيضاً.
بعدها قمنا بإضافة بعض العناصر فيه, كل عنصر عبارة منهم عبارة عن إسم البلد كمفتاح و إسم مدينة موجودة فيه كقيمة.
في الأخير قمنا بالبحث عن عدد العناصر التي تملك مفتاح محدد و طباعة نتيجة البحث.
ملاحظة: قمنا باستخدام الدالة count()
لمعرفة عدد العناصر التي تملك مفتاح محدد في الكائن.
المثال الثالث
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها string يمكنه أن يحتوي على مفاتيح نوعها unordered_multimap هنا قمنا بتعريف كائن من الكلاس unordered_multimap<string, string> um; // كل عنصر يحتوي على إسم البلد كمفتاح و إحدى مدنه كقيمة ,um هنا قمنا بإضافة 12 عنصر في الكائن um.emplace("Egypt", "Giza"); um.emplace("Lebanon", "Beirut"); um.emplace("Syria", "Sweida"); um.emplace("Lebanon", "Tripolie"); um.emplace("Syria", "Idlib"); um.emplace("KSA", "Riyadh"); um.emplace("Egypt", "Cairo"); um.emplace("Lebanon", "Sidon"); um.emplace("Syria", "Damascus"); um.emplace("KSA", "Makkah"); um.emplace("Syria", "Homs"); um.emplace("Algeria", "Algiers"); // um في الكائن "Syria" هنا قمنا بطباعة عدد العناصر التي تملك قيمة تساوي cout << "Total number of elements with key 'Syria' = " << um.count("Syria"); return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Total number of elements with key 'Syria' = 4
في المثال التالي قمنا بتعريف كائن من unordered_multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها string
قيم و نوعها string
أيضاً.
بعدها قمنا بإضافة بعض العناصر فيه, كل عنصر عبارة منهم عبارة عن إسم البلد كمفتاح و إسم مدينة موجودة فيه كقيمة.
بعدها قمنا بحذف جميع العناصر التي تملك مفاتيح محددة منه و من ثم طباعة قيم جميع العناصر المتبقية بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة erase()
لحذف جميع العناصر التي تملك مفاتيح محددة.
المثال الرابع
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها string يمكنه أن يحتوي على مفاتيح نوعها unordered_multimap هنا قمنا بتعريف كائن من الكلاس unordered_multimap<string, string> um; // كل عنصر يحتوي على إسم البلد كمفتاح و إحدى مدنه كقيمة ,um هنا قمنا بإضافة 12 عنصر في الكائن um.emplace("Egypt", "Giza"); um.emplace("Lebanon", "Beirut"); um.emplace("Syria", "Sweida"); um.emplace("Lebanon", "Tripolie"); um.emplace("Syria", "Idlib"); um.emplace("KSA", "Riyadh"); um.emplace("Egypt", "Cairo"); um.emplace("Lebanon", "Sidon"); um.emplace("Syria", "Damascus"); um.emplace("KSA", "Makkah"); um.emplace("Syria", "Homs"); um.emplace("Algeria", "Algiers"); // um من الكائن "Syria" و المتفاح "Lebanon" هنا قمنا بحذف جميع العناصر التي تملك المفتاح um.erase("Lebanon"); um.erase("Syria"); // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه um هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = um.begin(); it != um.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " -> " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Algeria -> Algiers KSA -> Makkah KSA -> Riyadh Egypt -> Cairo Egypt -> Giza
في المثال التالي قمنا بتعريف كائن من unordered_multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها int
قيم و نوعها string
.
بعدها قمنا بإضافة بعض العناصر فيه, كل عنصر عبارة منهم عبارة عن عدد و كمفتاح و إسمه باللغة الإنجليزية أو الفرنسية كقيمة.
بعدها قمنا بالبحث عن أول عنصر يملك مفتاح محدد فيه و من ثم قمنا بحذفه.
في الأخير قمنا بطباعة قيم جميع العناصر المتبقية بواسطة حلقة.
ملاحظة: قمنا باستخدام الدالة find()
للبحث عن أول عنصر يملك مفتاح محدد في الكائن و الدالة erase()
لحذف العنصر منه.
المثال الخامس
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها unordered_multimap هنا قمنا بتعريف كائن من الكلاس unordered_multimap<int, string> um = { {1, "Un"}, {1, "One"}, {2, "Deux"}, {2, "Two"}, {3, "Trois"}, {3, "Three"} }; // نجده يملك المفتاح الذي سنبحث عنه um لتخزين مكان أول عنصر في الكائن unordered_multimap<int, string>::iterator منا قمنا بتعريف كائن من unordered_multimap<int, string>::iterator it; // it عن أول عنصر يملك مفتاح يساوي 2, و بالتالي في حال وجود عنصر يملك هذا المفتاح سيتم تخزين عنوانه في الكائن um هنا قمنا بالبحث في الكائن // فيه للإشارة إلى أنه لم يتم إيجاد أي عنصر يملك هذا المفتاح um.end() في حال عدم وجود عنصر يملك مفتاح يساوي 2 سيتم تخزين القيمة التي ترجعها it = um.find(2); // فهذا يعني أنه تم إيجاد العنصر و بالتالي سيتم تنفيذ الكود الموضوع بالداخل um.end() لا تساوي القيمة التي ترجعها الدالة it في حال كانت قيمة if (it != um.end()) { // و من ثم قمنا بحذفه um هنا قمنا بطباعة مفتاح و قيمة العنصر الذي تم إيجاده في الكائن cout << "Element with key '"<< it->first << "' and value '" << it->second << "' is removed from um\n\n"; um.erase(it); } cout << "um keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه um هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = um.begin(); it != um.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
Element with key '2' and value 'Two' is removed from um um keys and values: 3 - Three 3 - Trois 2 - Deux 1 - One 1 - Un
في المثال التالي قمنا بتعريف كائنين من unordered_multimap
مع تحديد أن عناصرهما تتكون من مفاتيح نوعها int
قيم و نوعها string
مع إضافة عدة عناصر فيهما عند تعريفهم.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة مفاتيح و قيم عناصرهما بواسطة حلقة للتأكد من أن التبديل قد تم بنجاح.
ملاحظة: قمنا باستخدام الدالة swap()
لتبديل عناصرهما.
المثال السادس
#include <iostream> #include <unordered_map> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها unordered_multimap هنا قمنا بتعريف كائن من الكلاس unordered_multimap<int, string> unordered_multimap1 = { {1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"} }; // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها unordered_multimap هنا قمنا بتعريف كائن آخر من الكلاس unordered_multimap<int, string> unordered_multimap2 = { {5, "Five"}, {6, "Six"}, {7, "Seven"}, {8, "Eight"} }; // unordered_multimap2 مع قيم الكائن unordered_multimap1 هنا قمنا بتبديل قيم الكائن unordered_multimap1.swap(unordered_multimap2); cout << "unordered_multimap1 keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه unordered_multimap1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = unordered_multimap1.begin(); it != unordered_multimap1.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } cout << "\nunordered_multimap2 keys and values:\n"; // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه unordered_multimap2 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن for (auto it = unordered_multimap2.begin(); it != unordered_multimap2.end(); ++it) { // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية cout << it->first << " - " << it->second << "\n"; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل.
unordered_multimap1 keys and values: 8 - Eight 7 - Seven 6 - Six 5 - Five unordered_multimap2 keys and values: 4 - Four 3 - Three 2 - Two 1 - One
في المثال التالي قمنا بتعريف كائن من unordered_multimap
مع تحديد أن عناصره تتكون من مفاتيح نوعها string
قيم و نوعها string
أيضاً.
بعدها قمنا بإضافة بعض العناصر فيه, كل عنصر عبارة منهم عبارة عن إسم البلد كمفتاح و إسم مدينة موجودة فيه كقيمة.
في الأخير قمنا بعرض مفاتيح و قيم العناصر الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
ملاحظة: قمنا باستخدام الدالة bucket_count()
لمعرفة كم Bucket تم إنشاؤها بشكل تلقائي و الدالة bucket_size()
لمعرفة عدد العناصر الموجودة في كل Bucket.
المثال السابع
#include <iostream> #include <unordered_map> using namespace std; int main() { // string و قيم نوعها string يمكنه أن يحتوي على مفاتيح نوعها unordered_multimap هنا قمنا بتعريف كائن من الكلاس unordered_multimap<string, string> um; // كل عنصر يحتوي على إسم البلد كمفتاح و إحدى مدنه كقيمة ,um هنا قمنا بإضافة 12 عنصر في الكائن um.emplace("Egypt", "Giza"); um.emplace("Lebanon", "Beirut"); um.emplace("Syria", "Sweida"); um.emplace("Lebanon", "Tripolie"); um.emplace("Syria", "Idlib"); um.emplace("KSA", "Riyadh"); um.emplace("Egypt", "Cairo"); um.emplace("Lebanon", "Sidon"); um.emplace("Syria", "Damascus"); um.emplace("KSA", "Makkah"); um.emplace("Syria", "Homs"); um.emplace("Algeria", "Algiers"); // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = um.bucket_count(); // um الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] elements:"; // و من ثم طباعة مفتاح و قيمة كل عصنر موجود فيها الحلقة التالية for(auto it=um.begin(i); it!=um.end(i); ++it) { cout << " [" << it->first << " : " << it->second << "]"; } cout << endl; } }
•سنحصل على النتيجة التالية عند التشغيل.
bucket[0] elements: [KSA : Makkah] [KSA : Riyadh] bucket[1] elements: bucket[2] elements: bucket[3] elements: [Syria : Homs] [Syria : Damascus] [Syria : Idlib] [Syria : Sweida] bucket[4] elements: bucket[5] elements: bucket[6] elements: bucket[7] elements: [Lebanon : Sidon] [Lebanon : Tripolie] [Lebanon : Beirut] bucket[8] elements: bucket[9] elements: bucket[10] elements: bucket[11] elements: [Egypt : Cairo] [Egypt : Giza] bucket[12] elements: bucket[13] elements: bucket[14] elements: bucket[15] elements: [Algeria : Algiers] bucket[16] elements:
في المثال التالي قمنا بتعريف كائن من unordered_multimap
مخصص لتخزين عناصر تتكون من مفاتيح نوعها string
و قيم نوعها string
أيضاً مع إضافة عدة عناصر فيه عند تعريفه.
بعدها قمنا بعرض عدد العناصر الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
ملاحظة: قمنا باستخدام الدالة bucket_count()
لمعرفة كم Bucket تم إنشاؤها بشكل تلقائي.
المثال الثامن
#include <iostream> #include <unordered_map> using namespace std; int main() { // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string يمكنه أن يحتوي على عناصر نوعها unordered_multimap هنا قمنا بتعريف كائن من الكلاس // كل عنصر يحتوي على إسم البلد كمفتاح و إحدى مدنه كقيمة ,um هنا قمنا بإضافة 12 عنصر في الكائن unordered_multimap<string, string> um = { {"Egypt", "Giza"}, {"Lebanon", "Beirut"}, {"Syria", "Sweida"}, {"Lebanon", "Tripolie"}, {"Syria", "Idlib"}, {"KSA", "Riyadh"}, {"Egypt", "Cairo"}, {"Lebanon", "Sidon"}, {"Syria", "Damascus"}, {"KSA", "Makkah"}, {"Syria", "Homs"}, {"Algeria", "Algiers"} }; // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = um.bucket_count(); // um الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // و عدد العناصر الموجودة فيها Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] total elements = " << um.bucket_size(i); cout << endl; } }
•سنحصل على النتيجة التالية عند التشغيل.
bucket[0] total elements = 0 bucket[1] total elements = 0 bucket[2] total elements = 3 bucket[3] total elements = 0 bucket[4] total elements = 0 bucket[5] total elements = 6 bucket[6] total elements = 1 bucket[7] total elements = 0 bucket[8] total elements = 0 bucket[9] total elements = 0 bucket[10] total elements = 2 bucket[11] total elements = 0 bucket[12] total elements = 0
في المثال التالي قمنا بتعريف كائن من unordered_multimap
مخصص لتخزين مفاتيح نوعها string
و قيم نوعها string
أيضاً مع تحديد الطريقة التي سيتم على أساسها توزيع العناصر في Buckets و إضافة عدة عناصر فيه عند تعريفه.
لتحديد الطريقة التي سيتم على أساسها توزيع العناصر في Buckets قمنا بإنشاء كلاس إسمه Hash
و إعادة تعريف العامل ()
حتى يقارن مفتاح أي عنصر نريد إضافته نسبةً لعدد الأحرف الموجودة فيه, عندها يتم وضع العناصر التي تملك مفتاح يتألف من حرف واحد في Bucket, و العناصر التي تملك مفتاح يتألف من حرفين في Bucket, و العناصر التي تملك مفتاح يتألف من ثلاثة أحرف في Bucket و هكذا..
في النهاية قمنا بعرض مفاتيح و قيم العناصر الموجودة في كل Bucket فيه بواسطة حلقتين متداخلتين.
المثال التاسع
#include <iostream> #include <unordered_map> using namespace std; // unordered_multimap سنستخدمه لاحقاً لتحديد كيف ستترتب العناصر في الحاوية التي ننشئها من الكلاس Hash هنا قمنا بتعريف كلاس إسمه class Hash { public: // Bucket حتى يقرر في أي unordered_multimap هنا قمنا بتعريف العامل الذي سيستخدمه الكائن الذي ننشئه من الكلاس // key سيتم وضع العنصر الذي نضيفه فيه مع الإشارة إلى أن المفتاح الذي يملكه العنصر سيتم تمريره مكان الباراميتر size_t operator() (const string &key) const { // سيتم إضافة العنصر Bucket في النهاية سيتم إرجاع عدد أحرف مفتاح العنصر لأنها التي ستحدد في أي return key.length(); } }; int main() { // مع تحديد أنه يعتمد string يمكنه أن يحتوي على عناصر مفاتيحها و قيمها نوعها unordered_multimap هنا قمنا بتعريف كائن من الكلاس // من أجل تحديد الطريقة التي سيتم فيها ترتيب العناصر التي نضيفها فيه, بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه Hash على الكلاس unordered_multimap<string, string, Hash> um = { {"Egypt", "Giza"}, {"Lebanon", "Beirut"}, {"Syria", "Sweida"}, {"Lebanon", "Tripolie"}, {"Syria", "Idlib"}, {"KSA", "Riyadh"}, {"Egypt", "Cairo"}, {"Lebanon", "Sidon"}, {"Syria", "Damascus"}, {"KSA", "Makkah"}, {"Syria", "Homs"}, {"Algeria", "Algiers"} }; // totalBuckets التي تم إنشاؤها في المتغير Buckets هنا قمنا بتخزين عدد جميع الـ int totalBuckets = um.bucket_count(); // um الموجودين في الكائن Buckets هنا قمنا بإنشاء حلقة تمر على جميع الـ for(int i=0; i<totalBuckets; i++) { // Bucket في كل دورة سيتم طباعة رقم الـ cout << "bucket[" << i << "] elements:"; // و من ثم طباعة مفتاح و قيمة كل عصنر موجود فيها الحلقة التالية for(auto it=um.begin(i); it!=um.end(i); ++it) { cout << " [" << it->first << " : " << it->second << "]"; } cout << endl; } return 0; }
•سنحصل على النتيجة التالية عند التشغيل, و لاحظ كيف تم ترتيب العناصر على أساس عدد الأحرف التي يتألف منها كل عنصر.
bucket[0] elements: bucket[1] elements: bucket[2] elements: bucket[3] elements: [KSA : Makkah] [KSA : Riyadh] bucket[4] elements: bucket[5] elements: [Syria : Homs] [Syria : Damascus] [Syria : Idlib] [Syria : Sweida] [Egypt : Cairo] [Egypt : Giza] bucket[6] elements: bucket[7] elements: [Algeria : Algiers] [Lebanon : Sidon] [Lebanon : Tripolie] [Lebanon : Beirut] bucket[8] elements: bucket[9] elements: bucket[10] elements: bucket[11] elements: bucket[12] elements: