الخريطة في C++ مكتبة النماذج القياسية (STL)

⚡ ملخص ذكي

الخريطة في C++ هو حاوية ترابطية من مكتبة القوالب القياسية تقوم بتخزين العناصر كأزواج مفتاح-قيمة مرتبة، حيث يرتبط كل مفتاح فريد بقيمة واحدة ويتيح البحث السريع والإدراج والتنقل المرتب.

  • 🗺️ الحاوية الترابطية: A C++ تخزن الخريطة العناصر على شكل أزواج مفتاح-قيمة بمفاتيح فريدة ومرتبة تلقائيًا.
  • 🧩 العنوان والصيغة: قم بتضمين رأس الخريطة، ثم قم بتعريف std::map اسم لتخزين الأزواج المكتوبة.
  • 🛠️ الوظائف المضمنة: تقوم الدوال begin() و size() و empty() و insert() و find() و erase() و clear() بإدارة محتويات الخريطة.
  • 🔄 تكرار: يقوم مُكرِّر ثنائي الاتجاه بمسح عناصر الخريطة بترتيب المفاتيح المُرتَّبة للقراءة أو الحذف.
  • 🔑 مفاتيح فريدة: لا يمكن لعنصرين أن يشتركا في مفتاح واحد، مما يجعل الخريطة مثالية كمصفوفة ترابطية.
  • 🤖 مساعدة الذكاء الاصطناعي: يقوم برنامج GitHub Copilot والمساعدون المشابهون للذكاء الاصطناعي بإنشاء هياكل لإعلانات الخرائط والحلقات من تعليق قصير.

الخريطة في C++ المحكمة الخاصة بلبنان

ما هي الخريطة في C++?

In C++الخريطة (MAP) هي حاوية ترابطية تخزن العناصر في شكل مُرتبط. يتكون كل عنصر في الخريطة من قيمة مفتاح وقيمة مرتبطة. لا يمكن لقيمتين مرتبطتين أن تشتركا في نفس قيمة المفتاح.

تُفيد القيم الرئيسية في فرز العناصر وتحديدها بشكلٍ فريد، بينما تخزن القيم المُرتبطة المحتوى المُصاحب لكل مفتاح. قد يختلف النوعان، لكن نوع العنصر يجمعهما في زوجٍ واحدٍ يضم كليهما.

قبل كتابة أي كود، من المفيد معرفة سبب كون الخريطة في كثير من الأحيان هي الحاوية المناسبة التي يجب اللجوء إليها.

لماذا استخدام std::map؟

فيما يلي أسباب استخدام الخريطة:

  • تقوم std::map بتخزين المفاتيح الفريدة فقط، بترتيب تصاعدي بناءً على معايير الفرز المختارة.
  • من السهل والسريع البحث عن العناصر باستخدام المفتاح.
  • يتم إرفاق عنصر واحد فقط بكل مفتاح.
  • يمكن استخدام std::map كمصفوفة ترابطية.
  • يمكن تنفيذ std::map باستخدام الأشجار الثنائية المتوازنة.

للاستفادة من هذه المزايا، ابدأ بصيغة الإعلان.

بناء الجملة

للإعلان عن std::map، استخدم بناء الجملة هذا:

std::map<key_datatype, value_datatype>map_name; 
  • استخدم نوع البيانات الرئيسية يشير إلى نوع بيانات مفاتيح الخريطة.
  • استخدم نوع البيانات القيمة يشير إلى نوع بيانات القيم المقابلة لمفاتيح الخريطة.
  • استخدم اسم_الخريطة هو اسم الخريطة.

فمثلا:

map<string, int> my_map; 

لقد قمنا بتعريف خريطة باسم my_map. ستحتوي الخريطة على سلسلة نصية كنوع بيانات المفتاح وعدد صحيح كنوع بيانات القيم.

أنواع الأعضاء

يمكن للدوال الأعضاء استخدام أنواع الأعضاء التالية كمعاملات أو كنوع إرجاع:

  • نوع المفتاح: المفتاح (المعامل الأول في القالب)
  • Mapped_type: T (المعامل الثاني في القالب)
  • مقارنة المفاتيح: قارن (المعامل الثالث في القالب)
  • نوع_المخصص: Alloc (المعامل الرابع في القالب)
  • نوع_القيمة: زوج
  • قيمة_المقارنة: فئة دالة متداخلة لمقارنة العناصر
  • مرجع: allocator_type::reference
  • const_reference: allocator_type::const_reference
  • مؤشر: allocator_type::pointer
  • const_pointer: allocator_type::const_pointer
  • مكرر: مكرر ثنائي الاتجاه إلى value_type
  • const_iterator: مكرر ثنائي الاتجاه إلى const value_type
  • مكرر عكسي: مكرر عكسي
  • const_reverse_iterator: مكرر عكسي ثابت
  • نوع_الاختلاف: ptrdiff_t
  • نوع الحجم: size_t

وظائف مدمجة في std::map

std::map يأتي مع وظائف يحمل في ثناياه عوامل. بعض هذه تشمل:

  • يبدأ () – تقوم هذه الدالة بإرجاع المؤشر إلى العنصر الأول في الخريطة.
  • بحجم() – تقوم هذه الدالة بإرجاع عدد العناصر في الخريطة.
  • فارغ() – تُرجع هذه الدالة قيمة منطقية تشير إلى ما إذا كانت الخريطة فارغة أم لا.
  • إدراج(زوج(مفتاح، قيمة)) – تقوم هذه الوظيفة بإدراج زوج جديد من المفتاح والقيمة في الخريطة.
  • ابحث عن (القيمة) – تُعيد هذه الدالة مؤشرًا إلى عنصر val إذا تم العثور عليه. وإلا، فإنها تُعيد m.end().
  • امسح (موضع المُكرِّر) – تقوم هذه الدالة بحذف العنصر الموجود في الموضع الذي يشير إليه المؤشر.
  • محو (ثابت ز) – تقوم هذه الوظيفة بحذف المفتاح والقيمة g من الخريطة.
  • واضح() – تقوم هذه الوظيفة بحذف جميع العناصر من الخريطة.

بعد تعريف الوظائف، تقوم الأمثلة التالية بتطبيقها عملياً، بدءاً من التكرار.

التكرار على عناصر الخريطة

يمكنك المرور على عناصر الخريطة. كل ما نحتاجه هو إنشاء مُكرِّر واستخدامه لهذا الغرض. على سبيل المثال:

مثال 1

#include <iostream>
#include <string>
#include <map> 

using namespace std;
int main() {

	map<int, string> Students;

	Students.insert(std::pair<int, string>(200, "Alice"));

	Students.insert(std::pair<int, string>(201, "John"));

	cout << "Map size is: " << Students.size() << endl;

	cout << endl << "Default map Order is: " << endl;

	for (map<int, string>::iterator it = Students.begin(); it != Students.end(); ++it) {

		cout << (*it).first << ": " << (*it).second << endl;
	}
}

الإخراج:

C++ مثال على مخرجات تكرار الخريطة (المثال 1)

فيما يلي لقطة شاشة للكود:

C++ مثال 1 لتكرار الخريطة

Code التفسير:

  1. قم بتضمين ملف رأس iostream في الكود الخاص بنا لاستخدام وظائفه.
  2. قم بتضمين ملف رأس السلسلة في الكود الخاص بنا لاستخدام وظائفه.
  3. قم بتضمين ملف رأس الخريطة في الكود الخاص بنا لاستخدام وظائفه.
  4. قم بتضمين مساحة الاسم std في الكود الخاص بنا لاستخدام فئاتها دون استدعائها.
  5. استدعاء الدالة الرئيسية (). يمثل { بداية نص الوظيفة.
  6. قم بإنشاء خريطة باسم الطلاب حيث ستكون المفاتيح عبارة عن أعداد صحيحة، وستكون القيم عبارة عن سلاسل.
  7. إدراج القيم في الخريطة الطلاب. سيتم إدراج مفتاح 200 وقيمة Alice في الخريطة.
  8. إدراج القيم في الخريطة الطلاب. سيتم إدراج مفتاح 201 وقيمة جون في الخريطة.
  9. استخدم الدالة size() للحصول على حجم الخريطة المسماة Students. يجب أن تُرجع هذه الدالة القيمة 2.
  10. طباعة بعض النص على وحدة التحكم.
  11. استخدم حلقة for لإنشاء مكرر اسمه للتكرار على عناصر الخريطة المسماة الطلاب.
  12. طباعة قيم خريطة الطلاب على وحدة التحكم.
  13. نهاية جسم الحلقة.
  14. نهاية نص الدالة main().

إدخال البيانات في std::map

يمكنك إدخال عناصر في std::map باستخدام الدالة insert(). تذكر أن مفاتيح std::map يجب أن تكون فريدة.

لذا، يتحقق البرنامج أولاً مما إذا كان كل مفتاح موجودًا في الخريطة. إذا كان موجودًا، فلن يتم إدراج المدخل، ولكنه يُعيد مُكرِّر المدخل الموجود. أما إذا لم يكن موجودًا، فسيتم إدراج المدخل.

تحتوي الوظيفة على الاختلافات التالية:

  • إدراج (زوج) – مع هذا التغيير، يتم إدخال زوج من المفتاح والقيمة في الخريطة.
  • insert(start_itr, end_itr) – مع هذا التغيير، سيتم إدراج الإدخالات ضمن النطاق المحدد بواسطة start_itr و end_itr من خريطة أخرى.

تعمل الدالة insert_or_assign() بنفس طريقة عمل الدالة insert()، ولكن إذا كان المفتاح المحدد موجودًا بالفعل في الخريطة، فسيتم تعديل قيمته.

مثال 2

#include <map>
#include <iostream>

using namespace std;

int main() {

	map<int, int> m{ {1,3} , {2,4} , {3,5} };

	m.insert({ 5, 6 });
	m.insert({ 1, 8 });

	m.insert_or_assign(1, 6);  
	
	cout << "Key\tElement\n";
	for (auto itr = m.begin(); itr != m.end(); ++itr) {
		cout << itr->first << '\t' << itr->second << '\n';
	}
	return 0;
}

الإخراج:

C++ مثال على إدخال الخريطة 2

فيما يلي لقطة شاشة للكود:

C++ مثال 2 لإدراج الخريطة

Code التفسير:

  1. قم بتضمين ملف رأس الخريطة في الكود الخاص بنا لاستخدام وظائفه.
  2. قم بتضمين ملف رأس iostream في الكود الخاص بنا لاستخدام وظائفه.
  3. قم بتضمين مساحة الاسم std في الكود الخاص بنا لاستخدام فئاتها دون استدعائها.
  4. استدعاء الدالة الرئيسية (). يمثل { بداية نص الوظيفة.
  5. قم بإنشاء خريطة باسم m حيث ستكون المفاتيح عبارة عن أعداد صحيحة، وستكون القيم أعدادًا صحيحة. تم إدخال ثلاثة إدخالات في الخريطة.
  6. أدخل إدخالاً جديدًا في الخريطة م. سيتم إدراج مفتاح 5 وقيمة 6 في الخريطة.
  7. محاولة إجراء إدخال إلى مفتاح موجود بالفعل. نظرًا لأن المفتاح 1 موجود بالفعل في الخريطة، فلن يتم الإدخال.
  8. استخدام الدالة insert_or_assign() لإضافة أو تعديل إدخال موجود. بما أن المفتاح 1 موجود بالفعل، فسيتم تغيير قيمته إلى 6.
  9. طباعة بعض النص على وحدة التحكم. يقوم الحرف "\t" بإنشاء مسافة أفقية بينما يقوم الحرف "\n" بتحريك مؤشر الماوس إلى السطر التالي.
  10. إستخدم لحلقة لإنشاء مكرر اسمه itr للتكرار على عناصر الخريطة المسماة m.
  11. اطبع قيم الخريطة m على وحدة التحكم. يقوم الحرف "\t" بإنشاء مسافة أفقية بين كل مفتاح وقيمته المقابلة. في المقابل، يقوم الحرف "\n" بتحريك مؤشر الماوس إلى السطر التالي بعد كل تكرار.
  12. نهاية جسم الحلقة.
  13. يجب أن يقوم البرنامج بإرجاع قيمة عند اكتماله بنجاح.
  14. نهاية نص الدالة main().

البحث في الخريطة

يمكننا استخدام الدالة `find()` للبحث عن عناصر في خريطة باستخدام مفاتيحها. إذا لم يتم العثور على المفتاح، تُرجع الدالة `std::map::end`. وإلا، فسيتم إرجاع مُكرِّر للعنصر الذي تم البحث عنه.

مثال 3

#include <iostream>
#include <string>
#include <map> 
using namespace std;
int main() {
	map<int, string> Students;
	Students.insert(std::pair<int, string>(200, "Alice"));
	Students.insert(std::pair<int, string>(201, "John"));
	std::map<int, string>::iterator it = Students.find(201);
	if (it != Students.end()) {
		std::cout << endl << "Key 201 has the value: => "<< Students.find(201)->second << '\n';
	}
}

الإخراج:

C++ مثال 3: البحث عن الخريطة، البحث، المخرجات

فيما يلي لقطة شاشة للكود:

C++ مثال 3: البحث عن الخريطة

Code التفسير:

  1. قم بتضمين ملف رأس iostream في الكود الخاص بنا لاستخدام وظائفه دون حدوث أخطاء.
  2. قم بتضمين ملف رأس السلسلة في الكود الخاص بنا لاستخدام وظائفه دون حدوث أخطاء.
  3. قم بتضمين ملف رأس الخريطة في الكود الخاص بنا لاستخدام وظائفه دون حدوث أخطاء.
  4. قم بتضمين مساحة الاسم std في الكود الخاص بنا لاستخدام فئاتها دون استدعائها.
  5. استدعِ الدالة الرئيسية main(). يشير الرمز { إلى بداية جسم الدالة الرئيسية main().
  6. قم بإنشاء خريطة باسم الطلاب والتي ستكون مفاتيحها عبارة عن أعداد صحيحة وسلاسل قيم.
  7. إدراج القيم في الخريطة الطلاب. سيتم إدراج مفتاح 200 وقيمة Alice في الخريطة.
  8. إدراج القيم في الخريطة الطلاب. سيتم إدراج مفتاح 201 وقيمة جون في الخريطة.
  9. ابحث عن القيمة المرتبطة بمفتاح 201.
  10. استخدم عبارة if للتحقق من العثور على قيمة المفتاح.
  11. اطبع قيمة المفتاح إلى جانب بعض النصوص الموجودة على وحدة التحكم.
  12. نهاية نص عبارة if.
  13. نهاية نص الدالة main().

حذف البيانات من الخريطة

يمكننا استخدام الدالة erase() لحذف قيمة من الخريطة. ببساطة، نقوم بإنشاء مُكرِّر يشير إلى العنصر المراد حذفه، ثم نمرر هذا المُكرِّر إلى الدالة erase().

مثال 4

#include <iostream>
#include <string>
#include <map>

using namespace std;
int main() {

	map<std::string, int> my_map;

	my_map.insert(std::make_pair("cow", 1));

	my_map.insert(std::make_pair("cat", 2));

	my_map["lion"] = 3;

	map<std::string, int>::iterator it = my_map.find("cat");

	my_map.erase(it);

	for (map<string, int>::iterator it = my_map.begin(); it != my_map.end(); ++it)

		cout << (*it).first << ": " << (*it).second << endl;

  return 0;
}

الإخراج:

C++ مثال 4: مسح الخريطة وحذفها

فيما يلي لقطة شاشة للكود:

C++ مثال 4: مسح الخريطة وحذفها

Code التفسير:

  1. قم بتضمين ملف رأس iostream في الكود الخاص بنا لاستخدام وظائفه.
  2. قم بتضمين ملف رأس السلسلة في الكود الخاص بنا لاستخدام وظائفه.
  3. قم بتضمين ملف رأس الخريطة في الكود الخاص بنا لاستخدام وظائفه.
  4. قم بتضمين مساحة الاسم std في الكود الخاص بنا لاستخدام فئاتها دون استدعائها.
  5. استدعِ الدالة الرئيسية main(). يشير الرمز { إلى بداية جسم الدالة الرئيسية main().
  6. قم بإنشاء خريطة باسم my_map والتي ستكون مفاتيحها عبارة عن سلاسل وقيم أعداد صحيحة.
  7. أدخل القيم في الخريطة my_map. سيتم إدراج مفتاح البقرة وقيمة 1 في الخريطة.
  8. أدخل القيم في الخريطة my_map. سيتم إدراج مفتاح Cat وقيمة 2 في الخريطة.
  9. أضف القيمة 3 إلى الخريطة my_map باستخدام مفتاح الأسد.
  10. قم بإنشاء مكرر للتكرار على الخريطة my_map للبحث عن القطة الرئيسية.
  11. احذف العنصر الذي أشار إليه المكرر.
  12. استخدم أداة التكرار للتكرار على عناصر الخريطة my_map من البداية إلى النهاية.
  13. اطبع محتويات الخريطة my_map على وحدة التحكم.
  14. يجب أن يعود البرنامج الإخراج عند الانتهاء بنجاح.
  15. نهاية نص الدالة main().

الأسئلة الشائعة

تُحافظ دالة std::map على ترتيب المفاتيح باستخدام شجرة بحث ثنائية ذاتية التوازن، مما يُتيح عددًا من العمليات يُقدّر بـ O(log n). أما دالة std::unordered_map فتستخدم جدول تجزئة يُتيح عددًا من عمليات البحث يُقدّر بـ O(1)، ولكنها تُخزّن المفاتيح دون ترتيب مُحدد. اختر الدالة التي تُناسب احتياجاتك في ترتيب المفاتيح.

تُنفذ دالة std::map عادةً على شكل شجرة بحث ثنائية متوازنة ذاتيًا، وغالبًا ما تكون شجرة حمراء-سوداء. يحافظ هذا على ترتيب المفاتيح ويضمن زمنًا لوغاريتميًا لعمليات الإضافة والحذف والبحث.

لا. لا يحتوي std::map إلا على مفاتيح فريدة، لذا فإن إدخال مفتاح موجود لا يستبدله. عند الحاجة إلى مفاتيح مكررة، استخدم std::multimap، الذي يسمح لعناصر متعددة بمشاركة نفس قيمة المفتاح.

استخدم map_name[key] لقراءة قيمة أو تعيينها؛ يُدرج عامل الفهرسة إدخالًا افتراضيًا إذا كان المفتاح مفقودًا. يُطلق العضو at() استثناءً في حالة المفاتيح غير الموجودة، مما يجعله خيارًا أكثر أمانًا.

قم بتمرير دالة مقارنة مخصصة كوسيط ثالث للقالب، مثل std::map >. يقوم عامل المقارنة الأكبر بترتيب المفاتيح من الأعلى إلى الأدنى بدلاً من الترتيب التصاعدي الافتراضي.

تُخزّن std::map أزواج المفاتيح والقيم وتبحث عن القيم باستخدام المفتاح، بينما تُخزّن std::set المفاتيح الفريدة فقط دون أي قيمة مرتبطة بها. يحافظ كلا النوعين على ترتيب العناصر، لكن الخريطة تربط البيانات بكل مفتاح.

نعم. تقوم برامج الذكاء الاصطناعي المساعدة في البرمجة بتحويل أي طلب أو تعليق قصير إلى كود std::map يعمل بكفاءة، بما في ذلك التصريحات، واستدعاءات الإدراج، وحلقات التكرار. يُرجى مراجعة أنواع المفاتيح المُولّدة، وترتيبها، والحالات الاستثنائية قبل التجميع.

نعم. مساعد الطيار جيثب يقترح تعريفات الخرائط، واستدعاءات الإدراج والبحث، وحلقات التكرار أثناء الكتابة. يتعامل مع التعليمات البرمجية المتكررة بكفاءة، مع ذلك، يُنصح بالتحقق من تفرد المفاتيح والمنطق قبل البناء.

تلخيص هذه التدوينة بـ: