حذف
الدرس 11 من 16 في دورة شجرة AVL - سلسلة هياكل البيانات #10 على Coddy.
الحذف هو حذف في شجرة البحث الثنائية (BST) مع نفس أسلوب إعادة التوازن المتبع عند الإدراج. هناك ثلاث حالات يجب التعامل معها للعقدة المراد إزالتها: لا توجد أبناء (فقط قم بإزالتها)، ابن واحد (استبدلها بهذا الابن)، أو ابنان، وهي الحالة الصعبة، حيث تستبدل قيمة العقدة بـ الخلف المباشر (in-order successor) (أصغر قيمة في شجرتها الفرعية اليمنى) ثم تحذف ذلك الخلف من الشجرة الفرعية اليمنى بدلاً من ذلك.
تماماً مثل عملية الإدراج، يقوم كل سلف في طريق العودة للأعلى بإعادة حساب ارتفاعه ومعامل التوازن الخاص به، مع تطبيق حالة التدوير المناسبة إذا أصبح غير متوازن. منطق إعادة التوازن هو نفسه المتبع في الإدراج، إلا أن شرط اختيار الحالة المناسبة ينظر الآن إلى معامل التوازن للابن الأثقل بدلاً من المكان الذي استقرت فيه القيمة الجديدة.
التحدي
متوسطاكتب طريقة delete(value) في AVLTree (استخدام دالة مساعدة تعاودية يعمل بشكل جيد). قم بإزالة value باستخدام حذف BST القياسي: بالنسبة لعقدة لها طفلان، استبدل قيمتها بأصغر قيمة في شجرتها الفرعية اليمنى، ثم احذف تلك القيمة من الشجرة الفرعية اليمنى. لا تفعل شيئًا إذا لم يتم العثور على value. أثناء العودة للأعلى، أعد حساب الارتفاعات وأعد التوازن تمامًا كما تفعل عملية insert.
جرّب بنفسك
#include <stdio.h>
#include <string.h>
#include "avltree.h"
static void preorderValues(Node* node, int* vals, int* count) {
if (node == NULL) {
return;
}
vals[(*count)++] = node->value;
preorderValues(node->left, vals, count);
preorderValues(node->right, vals, count);
}
int main(void) {
AVLTree* tree = AVLTree_create();
char line[256];
while (fgets(line, sizeof(line), stdin) != NULL) {
line[strcspn(line, "\r\n")] = '\0';
char cmd[32];
int arg;
int parsed = sscanf(line, "%31s %d", cmd, &arg);
if (parsed >= 1 && strcmp(cmd, "insert") == 0) {
AVLTree_insert(tree, arg);
}
if (parsed >= 1 && strcmp(cmd, "delete") == 0) {
AVLTree_delete(tree, arg);
}
if (parsed >= 1 && strcmp(cmd, "search") == 0) {
if (AVLTree_search(tree, arg)) {
printf("true\n");
}
if (!AVLTree_search(tree, arg)) {
printf("false\n");
}
}
if (parsed >= 1 && strcmp(cmd, "preorder") == 0) {
int vals[10000];
int count = 0;
preorderValues(tree->root, vals, &count);
for (int i = 0; i < count; i++) {
if (i > 0) {
printf(" ");
}
printf("%d", vals[i]);
}
printf("\n");
}
}
return 0;
}