الخوارزميات وهياكل البيانات بلغة Go: دليل عملي

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

الخوارزميات وهياكل البيانات بلغة Go: دليل عملي

\n\n

Go (Golang) هي لغة مترجمة، ثابتة الأنواع، تم إنشاؤها في Google. بساطتها، أداؤها العالي، ودعمها المدمج للتوازي يجعلها خيارًا ممتازًا لتطوير الواجهات الخلفية، الخدمات المصغرة، والبرمجة النظامية. ومع ذلك، لكتابة كود فعال بلغة Go، لا يكفي معرفة بناء الجملة - بل يجب فهم كيفية عمل الخوارزميات وهياكل البيانات. في هذه المقالة، سنشرح هياكل البيانات والخوارزميات الرئيسية بلغة Go، مع تزويد كل قسم بأمثلة عملية.

\n\n

1. المكدس (Stack) بلغة Go

\n\n

المكدس هو هيكل بيانات يعمل وفق مبدأ LIFO (آخر دخول أول خروج). لا يوجد في Go نوع مدمج "مكدس"، ولكن يمكن تنفيذه بسهولة باستخدام الشريحة (slice).

\n\n

مثال على تنفيذ المكدس:

\n\n
package main\n\nimport "fmt"\n\ntype Stack struct {\n    items []int\n}\n\n// Push يضيف عنصرًا إلى قمة المكدس\nfunc (s *Stack) Push(item int) {\n    s.items = append(s.items, item)\n}\n\n// Pop يزيل ويعيد العنصر من قمة المكدس\nfunc (s *Stack) Pop() (int, bool) {\n    if len(s.items) == 0 {\n        return 0, false\n    }\n    lastIndex := len(s.items) - 1\n    item := s.items[lastIndex]\n    s.items = s.items[:lastIndex]\n    return item, true\n}\n\n// Peek يعيد العنصر من القمة دون إزالته\nfunc (s *Stack) Peek() (int, bool) {\n    if len(s.items) == 0 {\n        return 0, false\n    }\n    return s.items[len(s.items)-1], true\n}\n\nfunc main() {\n    stack := Stack{}\n    stack.Push(10)\n    stack.Push(20)\n    stack.Push(30)\n\n    item, ok := stack.Pop()\n    if ok {\n        fmt.Println("تم الاستخراج:", item) // 30\n    }\n    fmt.Println("قمة المكدس:", stack.Peek()) // 20\n}
\n\n

المكدس بلغة Go فعال بفضل تعقيده المطفأ O(1) لعمليات Push و Pop. استخدمه في مهام مثل التحقق من تسلسل الأقواس أو التراجع عن الإجراءات (undo).

\n\n

2. الطابور (Queue) بلغة Go

\n\n

الطابور يعمل وفق مبدأ FIFO (أول دخول أول خروج). سنقوم بتنفيذه باستخدام شريحة مع مؤشرات للبداية والنهاية.

\n\n

مثال على تنفيذ الطابور:

\n\n
package main\n\nimport "fmt"\n\ntype Queue struct {\n    items []int\n}\n\n// Enqueue يضيف عنصرًا إلى نهاية الطابور\nfunc (q *Queue) Enqueue(item int) {\n    q.items = append(q.items, item)\n}\n\n// Dequeue يزيل ويعيد العنصر من بداية الطابور\nfunc (q *Queue) Dequeue() (int, bool) {\n    if len(q.items) == 0 {\n        return 0, false\n    }\n    item := q.items[0]\n    q.items = q.items[1:]\n    return item, true\n}\n\n// Front يعيد العنصر الأول دون إزالته\nfunc (q *Queue) Front() (int, bool) {\n    if len(q.items) == 0 {\n        return 0, false\n    }\n    return q.items[0], true\n}\n\nfunc main() {\n    queue := Queue{}\n    queue.Enqueue(1)\n    queue.Enqueue(2)\n    queue.Enqueue(3)\n\n    item, ok := queue.Dequeue()\n    if ok {\n        fmt.Println("تم الاستخراج:", item) // 1\n    }\n    fmt.Println("الأول في الطابور:", queue.Front()) // 2\n}
\n\n

تنبيه: عملية Dequeue في هذا التنفيذ لها تعقيد O(n)، لأن إزالة العنصر الأول يؤدي إلى إزاحة الشريحة بأكملها. للكود الإنتاجي، استخدم المخزن المؤقت الحلقي (ring buffer) أو القائمة المزدوجة الارتباط (container/list).

\n\n

3. فرز الفقاعات (Bubble Sort) بلغة Go

\n\n

فرز الفقاعات هو أحد أبسط الخوارزميات، ولكنه غير فعال. ومع ذلك، فهو ممتاز للتعلم. التعقيد: O(n²).

\n\n
package main\n\nimport "fmt"\n\nfunc bubbleSort(arr []int) {\n    n := len(arr)\n    for i := 0; i < n-1; i++ {\n        swapped := false\n        for j := 0; j < n-i-1; j++ {\n            if arr[j] > arr[j+1] {\n                arr[j], arr[j+1] = arr[j+1], arr[j]\n                swapped = true\n            }\n        }\n        // إذا لم تكن هناك عمليات تبادل - المصفوفة مرتبة بالفعل\n        if !swap                

المدونات

توصيات الكتب