عندما تكتب p->left = p->right = p;
تعني أن كل من p->left
و p->right
يشيران إلى نفس العنصر الذي يشير إليه p
. بمعنى آخر، جميعها تشير إلى نفس العنصر في الذاكرة، وهو العنصر الذي تم إنشاؤه باستخدام new node(0, NULL, NULL)
والذي له القيمة الافتراضية count = 0
و left
و right
تشيران إلى NULL
.
لكن السؤال هو: كيف يتصرف البرنامج عندما تقوم بتحديث p->left
و p->right
ليشيران إلى p
نفسه؟
عندما تفعل ذلك، يصبح لديك شجرة ثنائية مكونة من عقدة واحدة فقط، حيث تشير كل من الجذور اليسرى واليمنى إلى نفس العقدة. هذا يعني أن أي تغيير تقوم به في p->left
سيؤدي أيضًا إلى تغيير في p->right
والعكس صحيح.
عند استدعاء الدالة update(0, 9, 0)
مع l=0
، r=9
و v=0
، فإن الدالة تقوم بتحديث القيم في النطاق المحدد من الشجرة ثنائية. ونظرًا لأن كلا p->left
و p->right
تشيران إلى نفس العقدة التي تشير إليها p
، فإنها تعمل على العقدة الوحيدة الموجودة في الشجرة. هذا هو السبب في أنها تعمل بشكل صحيح عندما تقوم بتحديث p->left
و p->right
ليشيران إلى p
، لأنها تحدث على العقدة الوحيدة الموجودة في الشجرة.
ومع ذلك، إذا قمت بتعليق p->left = p->right = p;
، فإن p->left
و p->right
سيشيران إلى NULL
بدلاً من العقدة نفسها. وعندما تحاول استدعاء update(0, 9, 0)
، فإن البرنامج سيحاول الوصول إلى NULL
pointers مما قد يؤدي إلى فشل التشغيل.
باختصار، عندما تعين p->left
و p->right
لتشير إلى p
، فإنهم يشيران إلى نفس العقدة والتغيير في أي منهما سيؤدي إلى تغيير في الآخر. وعندما تعينهما لتشير إلى NULL
، سيحاول البرنامج الوصول إلى NULL
pointers مما قد يسبب فشل التشغيل.
المزيد من المعلومات
بالطبع، دعني أوضح المزيد من المعلومات لتفسير سلوك الكود.
عندما تكون p->left = p->right = p;
نقوم بتعيين كل من p->left
و p->right
ليشيران إلى نفس العقدة التي يشير إليها p
. هذا يعني أنهم يشيران إلى نفس الذاكرة التي تحتوي على العقدة التي تم إنشاؤها باستخدام new node(0, NULL, NULL)
.
عند تعيين p->left
و p->right
ليكونان مساويين لـ p
، فإن أي تعديل يتم على أي منهما سيؤثر على العقدة نفسها. فمثلاً، إذا قمت بتغيير قيمة count
في p->left
، فإنها ستتغير أيضًا في p->right
والعكس صحيح.
عند استدعاء الدالة update(0, 9, 0)
، يقوم البرنامج بتحديث القيم في النطاق المحدد من الشجرة ثنائية، ولكن نظرًا لأن كلا p->left
و p->right
يشيران إلى نفس العقدة، فإنهما يشيران إلى الجذر الوحيد في الشجرة. وبما أن الجذر الوحيد هو العقدة الوحيدة الموجودة، فإن التحديثات ستطبق عليها فقط.
بالنسبة لسؤالك عن سبب فشل التشغيل عندما تعلق p->left = p->right = p;
، فالسبب يعود إلى محاولة البرنامج الوصول إلى NULL
pointers عندما تكون p->left
و p->right
يشيران إلى NULL
بدلاً من العقدة الفعلية. وعندما يحاول البرنامج الوصول إلى NULL
pointers، فإن ذلك يؤدي إلى فشل التشغيل.
بشكل عام، تعيين p->left
و p->right
ليشيران إلى p
يعني أنك تقوم بإنشاء قائمة متصلة بدلاً من شجرة ثنائية، حيث يشير كل من p->left
و p->right
إلى نفس العقدة التي يشير إليها p
.