C言語のアルゴリズムトレーニングキャンプ 第4週:二分探索木の操作

235. 二分探索木の最近共通先祖

二分探索木(BST)の根ノードと二つの指定ノードが与えられた場合、その二つのノードの最近共通先祖を返す関数を作成します。

struct TreeNode* findCommonAncestor(struct TreeNode* tree, struct TreeNode* n1, struct TreeNode* n2) {
    if (tree == NULL) {
        return NULL;
    }
    if (tree->val > n1->val && tree->val > n2->val) {
        struct TreeNode* left = findCommonAncestor(tree->left, n1, n2);
        return left != NULL ? left : NULL;
    }
    if (tree->val < n1->val && tree->val < n2->val) {
        struct TreeNode* right = findCommonAncestor(tree->right, n1, n2);
        return right != NULL ? right : NULL;
    }
    return tree;
}

このアルゴリズムは、BSTの性質を利用します。根ノードから下に向かって探索し、最初にn1とn2の値の範囲内に位置するノードが最近共通先祖となります。

701. 二分探索木へのノード挿入

指定された値をBSTに挿入し、挿入後のBSTのルートを返します。

struct TreeNode* insertIntoBST(struct TreeNode* root, int value) {
    if (root == NULL) {
        struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
        newNode->val = value;
        newNode->left = NULL;
        newNode->right = NULL;
        return newNode;
    }
    if (root->val > value) {
        root->left = insertIntoBST(root->left, value);
    } else {
        root->right = insertIntoBST(root->right, value);
    }
    return root;
}

ルートがNULLの場合、新規ノードを作成します。値が現在のノードの値よりも小さい場合は左部分木、大きい場合は右部分木に再帰的に挿入します。

450. 二分探索木からのノード削除

BSTから指定された値のノードを削除し、BSTの性質を維持します。

struct TreeNode* deleteNode(struct TreeNode* node, int deleteVal) {
    if (node == NULL) {
        return NULL;
    }
    if (node->val == deleteVal) {
        if (node->left == NULL && node->right == NULL) {
            return NULL;
        } else if (node->left != NULL && node->right == NULL) {
            return node->left;
        } else if (node->right != NULL && node->left == NULL) {
            return node->right;
        } else {
            struct TreeNode* successor = node->right;
            while (successor->left != NULL) {
                successor = successor->left;
            }
            successor->left = node->left;
            return node->right;
        }
    }
    if (node->val > deleteVal) {
        node->left = deleteNode(node->left, deleteVal);
    } else {
        node->right = deleteNode(node->right, deleteVal);
    }
    return node;
}

削除対象のノードが見つかった場合、以下の五つの状況を考慮します:

  • 削除ノードが葉ノードである場合
  • 削除ノードが左の子ノードのみを持つ場合
  • 削除ノードが右の子ノードのみを持つ場合
  • 削除ノードが両方の子ノードを持つ場合

タグ: 二分探索木 C言語 アルゴリズムトレーニング

7月26日 02:58 投稿