الخوارزميات وهياكل البيانات في C++: من الأساسيات إلى التطبيق العملي
إتقان الخوارزميات وهياكل البيانات هو مرحلة أساسية في تكوين أي مبرمج. في هذه المقالة، سنشرح المفاهيم الأساسية باستخدام لغة C++. ستتعلم كيفية تنظيم البيانات بكفاءة وكتابة خوارزميات سريعة ستكون أساس مشاريعك. المادة موجهة للمبتدئين والمطورين من المستوى المتوسط.
ما هي الخوارزميات وهياكل البيانات؟
الخوارزمية هي تسلسل واضح من الإجراءات لحل مشكلة. هيكل البيانات هو طريقة لتنظيم وتخزين البيانات تضمن الوصول الفعال والتعديل. في C++، يرتبط المفهومان ارتباطًا وثيقًا: اختيار هيكل البيانات الصحيح يمكن أن يسرع الخوارزمية بعشرات المرات.
هياكل البيانات الأساسية في C++:
- المصفوفات — مجموعة ثابتة من العناصر من نفس النوع
- القوائم المرتبطة — تسلسلات ديناميكية
- الأكوام والطوابير — هياكل ذات وصول محدود
- الأشجار — هياكل هرمية
- جداول التجزئة — بحث سريع بالمفتاح
المصفوفات والعمل معها
المصفوفة هي أبسط هيكل بيانات، حيث تُخزَّن العناصر في منطقة ذاكرة متصلة. في C++، تكون المصفوفات إما ثابتة أو ديناميكية.
#include <iostream>using namespace std;
int main() { // مصفوفة ثابتة int arr[5] = {10, 20, 30, 40, 50}; // مصفوفة ديناميكية (باستخدام new) int* dynArr = new int[3]; dynArr[0] = 1; dynArr[1] = 2; dynArr[2] = 3; // طباعة العناصر for (int i = 0; i < 5; i++) { cout << arr[i] << " "; } delete[] dynArr; // تحرير الذاكرة return 0;}خوارزمية البحث الخطي في المصفوفة:
int linearSearch(int arr[], int n, int x) { for (int i = 0; i < n; i++) { if (arr[i] == x) return i; // إرجاع الفهرس } return -1; // غير موجود}التعقيد: O(n). للتسريع، استخدم std::vector من STL — فهو يدير الذاكرة تلقائيًا.
القوائم المرتبطة: أحادية الارتباط وثنائية الارتباط
تتكون القائمة المرتبطة من عُقد، تحتوي كل منها على بيانات ومؤشر للعنصر التالي (أو السابق). في C++، يُستخدم عادةً std::forward_list (أحادية الارتباط) و std::list (ثنائية الارتباط).
تنفيذ قائمة مرتبطة أحادية بسيطة:
struct Node { int data; Node* next;};
class LinkedList {private: Node* head;public: LinkedList() : head(nullptr) {} void insert(int val) { Node* newNode = new Node{val, nullptr}; if (!head) { head = newNode; return; } Node* temp = head; while (temp->next) temp = temp->next; temp->next = newNode; } void display() { Node* temp = head; while (temp) { cout << temp->data << " -> "; temp = temp->next; } cout << "nullptr" << endl; }};مزايا القوائم:
- حجم ديناميكي
- إدراج وحذف سريع في المنتصف (O(1) إذا كان هناك مؤشر)
العيوب:
- وصول بطيء حسب الفهرس (O(n))
- ذاكرة إضافية للمؤشرات
الكومة والطابور: مبدأا LIFO و FIFO
الكومة (Stack) تعمل بمبدأ "آخر من يدخل هو أول من يخرج" (LIFO). الطابور (Queue) — "أول من يدخل هو أول من يخرج" (FIFO). في C++، تم تنفيذهما في STL.
مثال على استخدام الكومة:
#include <stack>#include