search 2分探索木におけるデータの探索 insert 2分探索木におけるノードの挿入 delete 2分探索木におけるノードの削除
2分探索木におけるデータの探索
NODE *search(int key);
2分探索木におけるノードの挿入
NODE *insert(int key);
2分探索木におけるノードの削除
int delete(int key);
typedef struct _node {
int key; /* 比較のキーとなるフィールド */
int info; /* その他のフィールド */
struct _node *left; /* 左側の子を指す */
struct _node *right; /* 右側の子を指す */
} NODE;
2分探索木におけるデータの探索関数において
key 探索目標とするキーの値
2分探索木におけるノードの挿入関数において
key 追加したいキーの値
2分探索木におけるノードの削除関数において
key 削除したいキーの値
2分探索木におけるデータの探索関数について
探索が成功したときは見つかったノードへのポインタ。
失敗のときは NULL。
2分探索木におけるデータの挿入関数について
挿入が成功したときは挿入したノードへのポインタ。
挿入失敗のときや挿入しようとするキーが既にあったときは NULL。
2分探索木におけるデータの削除関数について
削除が成功したときは 0。
削除しようとするキーが存在していないときは -1。
static NODE *root = NULL;
NODE *search(int key){
NODE *node = root;
while (node != NULL) {
if (key == node->key)
return node;
if (key < node->key)
node = node->left;
else
node = node->right;
}
return NULL;
}
NODE *insert(int key){
NODE **node = &root;
while (*node != NULL) {
if (key == (*node)->key) return NULL;
if (key < (*node)->key) node = &((*node)->left);
else node = &((*node)->right);
}
if ((*node = (NODE *)malloc(sizeof(NODE))) == NULL) return NULL;
(*node)->key = key;
(*node)->left = (*node)->right = NULL;
return (*node);
}
int delete(int key){
NODE **node = &root;
NODE *next, **leftmax, *tmp;
for (;;) {
if (*node == NULL) return -1;
if (key == (*node)->key) break;
if (key < (*node)->key) node = &((*node)->left);
else node = &((*node)->right);
}
if ((*node)->left == NULL)
next = (*node)->right;
else {
leftmax = &((*node)->left);
while ((*leftmax)->right != NULL)
leftmax = &((*leftmax)->right);
next = *leftmax;
*leftmax = (*leftmax)->left;
next->left = (*node)->left;
next->right = (*node)->right;
}
tmp = *node;
*node = next;
free(tmp);
return 0;
}
2分探索木による探索は、ルートから始め、探索キーの値がそのノードの データより小さいか大きいかによって、左側または右側の子ノードをたど っていく。
完全につりのとれば2分探索木なら、n 個のものを調べるのに必要な比較回数 は O(log n) である。しかし、左右のバランスの悪い木では探索時間がか かり、最悪場合の計算量は O(n) である。
また、削除のプログラムがかなり複雑になってしまうことは、2分探索木 の特徴である。考えるべきケースとして、削除しようとするノードが
なお、2分探索木の性質上、同じ探索キーをもつノードは一つしかないの で、同じ探索キーに複数のデータをもつ場合はデータ構造中のinfoを工夫 する必要がある。