عُقد الشجرة وبنيتها
نمذج عقدة باستخدام المؤشرات
عُقد الشجرة وبنيتها درس مجاني في C Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C Academy 4 دروس في المجموع.
ما الشجرة الثنائية
الشجرة الثنائية بنية هرمية تحتوي فيها كل عقدة على قيمة وروابط تصلها بما يصل إلى ابنين: ابن أيسر وابن أيمن.
العقدة العلوية هي الجذر. والعقد التي لا أبناء لها هي الأوراق. ويجعل هذا الشكل الأشجار الثنائية مناسبة للبحث والفرز والمعالجة التكرارية السريعة.
بنية العقدة
نمذْج العقدة في لغة C باستخدام بنية تخزّن البيانات بالإضافة إلى مؤشرين يشيران إلى النوع نفسه.
يشير كل مؤشر إلى Node أخرى، أو إلى NULL عند عدم وجود ابن في ذلك الجانب.
struct Node {
int value;
struct Node *left;
struct Node *right;
};لماذا نستخدم مؤشرات تشير إلى النوع نفسه
لا يمكن للعقدة أن تحتوي على عقدة كاملة أخرى بالقيمة، لأن ذلك سيتطلب مساحة تخزين لا نهائية. وبدلًا من ذلك، تحتوي على مؤشرات إلى أبنائها.
المؤشرات ثابتة الحجم، لذلك تظل البنية ذات حجم معروف، مع استمرار قدرتها على الربط بعقد أخرى في الكومة.
struct Node {
int value;
struct Node *left; /* 8 bytes on 64-bit */
struct Node *right; /* 8 bytes on 64-bit */
};typedef لتسهيل الاستخدام
تكرار كتابة struct Node في كل موضع أمر ممل. ويتيح لنا typedef كتابة Node فقط.
ولا يزال اسم البنية مطلوبًا داخلها، لأن النوع لم يُعرّف بالكامل بعد في تلك النقطة.
typedef struct Node {
int value;
struct Node *left;
struct Node *right;
} Node;تخصيص عقدة
توجد العقد في الكومة، ويُنشئها malloc. نضبط القيمة ونهيّئ مؤشري الابنين على NULL.
تحقّق دائمًا من أن malloc لم تُعد NULL قبل استخدام الذاكرة.
Node *create_node(int value) {
Node *n = malloc(sizeof(Node));
if (n == NULL) return NULL;
n->value = value;
n->left = NULL;
n->right = NULL;
return n;
}بناء شجرة صغيرة يدويًا
لفهم الروابط، لنوصل ثلاث عقد يدويًا: جذرًا له ابنان.
ينشئ هذا البرنامج الشجرة ويطبع القيم، ثم نحررها عادةً بعد ذلك (وهو موضوع سنتناوله لاحقًا).
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node *left;
struct Node *right;
} Node;
Node *create_node(int v) {
Node *n = malloc(sizeof(Node));
n->value = v; n->left = NULL; n->right = NULL;
return n;
}
int main(void) {
Node *root = create_node(10);
root->left = create_node(5);
root->right = create_node(15);
printf("%d %d %d\n", root->left->value, root->value, root->right->value);
return 0;
}الوصول إلى الأحفاد
تتنقل في الشجرة عبر تسلسل استخدام معامل السهم. ينتقل root->left->right إلى الابن الأيسر، ثم إلى ابنه الأيمن.
تأكّد من أن المؤشر ليس NULL قبل اتباعه، وإلا فسيتعطل البرنامج.
/* root
* \
* right (15)
* \
* right->right (20)
*/
if (root->right != NULL && root->right->right != NULL)
printf("%d\n", root->right->right->value);عدّ العقد تكراريًا
يناسب التكرار الأشجار بصورة طبيعية. ولعدّ العقد، تحتوي الشجرة الفرعية الفارغة على صفر من العقد؛ وإلا فنعدّ هذه العقدة بالإضافة إلى الشجرتين الفرعيتين.
يُعد التحقق من NULL حالة الأساس التي توقف التكرار.
int count_nodes(Node *root) {
if (root == NULL) return 0;
return 1 + count_nodes(root->left)
+ count_nodes(root->right);
}قياس الارتفاع
ارتفاع الشجرة هو أطول مسار من الجذر نزولًا إلى ورقة، ويُقاس بعدد الحواف.
نأخذ الارتفاع الأكبر من ارتفاعي الشجرتين الفرعيتين ونضيف واحدًا. ونمنح الشجرة الفارغة الارتفاع -1 حتى يكون ارتفاع العقدة المفردة 0.
int height(Node *root) {
if (root == NULL) return -1;
int l = height(root->left);
int r = height(root->right);
return 1 + (l > r ? l : r);
}التعرّف على الأوراق
الورقة عقدة لا أبناء لها: يكون كل من left وright مساويًا لـ NULL.
وتفيد هذه الدالة المساعدة الصغيرة في العديد من إجراءات الاجتياز والعد.
int is_leaf(Node *n) {
return n != NULL && n->left == NULL && n->right == NULL;
}توظيف البنية
تُبنى هنا شجرة صغيرة، ثم نعرض عدد عقدها وارتفاعها باستخدام الدوال المساعدة التكرارية.
لاحظ أن الدوال المساعدة لا تفترض شكلًا ثابتًا؛ فهي تعمل مع أي شجرة لأن التكرار يتبع المؤشرات الفعلية.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node { int value; struct Node *left, *right; } Node;
Node *nn(int v){ Node *n=malloc(sizeof(Node)); n->value=v; n->left=n->right=NULL; return n; }
int count(Node *r){ return r? 1+count(r->left)+count(r->right):0; }
int height(Node *r){ if(!r) return -1; int l=height(r->left),x=height(r->right); return 1+(l>x?l:x); }
int main(void){
Node *root = nn(10);
root->left = nn(5); root->right = nn(15);
root->left->left = nn(2);
printf("nodes=%d height=%d\n", count(root), height(root));
return 0;
}تحقّق سريع
اختبر مدى فهمك لبنية العقدة.
مراجعة
تحتوي عقدة الشجرة الثنائية على قيمة ومؤشرين يشيران إلى النوع نفسه (left وright)، ويُضبطان على NULL عند غيابهما.
نخصّص العقد باستخدام malloc، ونربطها يدويًا، ونعالجها تكراريًا. ويكون التحقق من NULL دائمًا حالة الأساس في عمليات العد وحساب الارتفاع واختبار الأوراق.
الأسئلة الشائعة
هل درس «عُقد الشجرة وبنيتها» مجاني؟
نعم — نص درس «عُقد الشجرة وبنيتها» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C Academy 4 دروس في المجموع.
ماذا ستتعلم في «عُقد الشجرة وبنيتها»؟
نمذج عقدة باستخدام المؤشرات تتمرن على C Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C Academy؟
لا تُشترط خبرة سابقة. C Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «عُقد الشجرة وبنيتها»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C Academy هذا؟
نعم. كل درس في C Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- عُقد الشجرة وبنيتها
- الإدراج في BST
- عمليات الاجتياز
- البحث والتحرير