私は、(理論的には) 3 つのすべてのケースを処理する必要があるバイナリ ツリー内のノードを削除する関数を C で実装しようとしています。
- ノードは葉です
- ノードには子が 1 つあります
- ノードには 2 つの子があります
ケースごとに個別にチェックせずに、削除機能全体を処理する方法はありますか? 以下のコメンターが指摘したように、私は多くのケースをチェックしており、1 つの基本的なケースをチェックすることで、問題全体を再帰的に解決できる可能性があります。
親を持つツリー内のノードを削除し、それ自体が 2 つの子ノードの親である場合に特に興味があります。
以下の両方の回答は役に立ちましたが、問題全体に対処しているとは思いません。
ここに私が持っているものがあります:
typedef struct Node
{
int key;
int data;
struct Node *left;
struct Node *right;
struct Node *parent;
} Node;
/* functions that take care of inserting and finding a node and also traversing and freeing the tree */
...
void delete(Node *root, int key)
{
Node *target = find(root, key); // find will return the node to be deleted
Node *parent = target->parent; // parent of node to be deleted
// no children
if (target->left == NULL && target->right == NULL)
{
// is it a right child
if (target->key > parent->key)
parent->right = NULL;
// must be a left child
else
parent->left = NULL;
free(target);
}
// one child
else if ((target->left == NULL && target->right != NULL) || (target->left != NULL && target->right == NULL))
{
// here we swap the target and the child of that target, then delete the target
Node *child = (target->left == NULL) ? target->right : target->left;
child->parent = parent;
if (parent->left == target) parent->left = child;
else if (parent->right == target) parent->right = child;
free(target);
}
// two children
else
{
// find the largest node in the left subtree, this will be the node
// that will take the place of the node to be deleted
Node *toBeRepl = max(target->left);
// assign the data of the second largest node
target->key = toBeRepl->key;
target->data = toBeRepl->data;
// if new node immediately to the left of target
if (toBeRepl == target->left)
{
target->left = toBeRepl->left;
Node *newLeft = target->left;
if (newLeft != NULL) newLeft->parent = target;
}
else
{
delete(target->left, toBeRepl->key);
// Node *replParent = toBeRepl->parent;
// replParent->right = NULL;
}
}
フィードバックをいただければ幸いです。
編集:明確にするために、サブツリーに触れずに特定のノードを削除しようとしています(存在する場合)。それらはそのままにしておく必要があります(削除するノードの値と(場合によっては)そのサブツリーのノードの1つを交換することで処理しました)。
編集: 次のウィキペディアの記事を参考にしました
: http://en.wikipedia.org/wiki/Binary_search_tree#Deletion
:
削除するノードを N と呼びます。N を削除しないでください。代わりに、順序どおりの後続ノードまたは順序どおりの先行ノード R を選択します。N の値を R の値に置き換えてから、R を削除します。
上記の場合、C++ には興味深いコードがいくつかありますが、スワップが正確にどのように発生するかはわかりません。
else //2 children
{
temp = ptr->RightChild;
Node<T> *parent = nullptr;
while(temp->LeftChild!=nullptr)
{
parent = temp;
temp = temp->LeftChild;
}
ptr->data = temp->data;
if (parent!=nullptr)
Delete(temp,temp->data);
else
Delete(ptr->rightChild,ptr->RightChild->data);
}
誰かがそのセクションで何が起こっているのか説明してもらえますか? 再帰は、ここでのユーザーのコメントと同様のアプローチであると想定しています。