はじめての C
splay木を 用いて tree の root を 変更させてみる。 その前に、ポインタを どう渡すか、ちょっと チェック ...
struct Node **tree;
int value;if (*tree == NULL)
new_node(tree, value);
if ((*tree)->left == NULL)
new_node(&(*tree)->left, value);
これで よかったかな ?
/* t_splay.c */
#include
#include
#include "t_splay.h"struct Node {
int data;
struct Node *left;
struct Node *right;
};
struct Tree {
struct Node *root;
};
int new_node();
int splay_insert();
int splay_search();
void rotate_right();
void rotate_left();
void btree_walk();
int tree_height();
main()
{
int value;
struct Tree *root;
root = NULL;
while (fscanf(stdin, "%d", &value) != EOF)
splay_insert(&root, value);
btree_walk(root);
putchar('\n');
printf("%d\n", tree_height(root));
printf("splay search > %d\n", ROOT);
splay_search(&root, ROOT);
printf("%d\n", tree_height(root));
return 0;
}
int new_node(struct Node **node, int value)
{
*node = malloc(sizeof(**node));
if (*node == NULL)
return 0;
(*node)->data = value;
(*node)->left = NULL;
(*node)->right = NULL;
return 1;
}
int splay_insert(struct Node **tree, int key)
{
int rc;
if (*tree == NULL) {
new_node(tree, key);
rc = (*tree == NULL) ? 0 : 1;
}
else if (key < (*tree)->data) {
if ((*tree)->left == NULL) {
new_node(&(*tree)->left, key);
rc = ((*tree)->left == NULL) ? 0 : 1;
}
else if (key < (*tree)->left->data) {
rc = splay_insert(&(*tree)->left->left, key);
rotate_right(tree);
}
else if (key > (*tree)->left->data) {
rc = splay_insert(&(*tree)->left->right, key);
rotate_left(&(*tree)->left);
}
else
rc = 0;
rotate_right(tree);
}
else if (key > (*tree)->data) {
if ((*tree)->right == NULL) {
new_node(&(*tree)->right, key);
rc = ((*tree)->right == NULL) ? 0 : 1;
}
else if (key < (*tree)->right->data) {
rc = splay_insert(&(*tree)->right->right, key);
rotate_left(tree);
}
else if (key > (*tree)->right->data) {
rc = splay_insert(&(*tree)->right->left, key);
rotate_right(&(*tree)->right);
}
else
rc = 0;
rotate_left(tree);
}
else
rc = 0;
return rc;
}
int splay_search(struct Node **tree, int key)
{
int rc;
if ((*tree)->data == key)
rc = 1;
else if (key < (*tree)->data) {
if ((*tree)->left->data == key)
rc = 1;
else if (key < (*tree)->left->data) {
rc = splay_insert(&(*tree)->left->left, key);
rotate_right(tree);
}
else if (key > (*tree)->left->data) {
rc = splay_insert(&(*tree)->left->right, key);
rotate_left(&(*tree)->left);
}
else
rc = 0;
rotate_right(tree);
}
else if (key > (*tree)->data) {
if ((*tree)->right->data == key)
rc = 1;
else if (key < (*tree)->right->data) {
rc = splay_insert(&(*tree)->right->right, key);
rotate_left(tree);
}
else if (key > (*tree)->right->data) {
rc = splay_insert(&(*tree)->right->left, key);
rotate_right(&(*tree)->right);
}
else
rc = 0;
rotate_left(tree);
}
else
rc = 0;
return rc;
}
void rotate_right(struct Node **root)
{
struct Node *save;
save = (*root)->left;
(*root)->left = save->right;
save->right = *root;
*root = save;
}
void rotate_left(struct Node **root)
{
struct Node *save;
save = (*root)->right;
(*root)->right = save->left;
save->left = *root;
*root = save;
}
void btree_walk(struct Node *tree)
{
if (tree == NULL)
return;
btree_walk(tree->left);
printf("%d ", tree->data);
btree_walk(tree->right);
}
int tree_height(struct Node *tree)
{
int left_height;
int right_height;
if (tree == NULL)
return -1;
left_height = tree_height(tree->left);
right_height = tree_height(tree->right);
if (left_height < right_height)
return right_height + 1;
else
return left_height + 1;
}
ヘッダファイルも 作成。
/* t_splay.h */
#define ROOT 30
コンパイルして、badtree.txt*1で 確認。
$cc -c t_splay.c
$cc -o t_splay t_splay.o
$./t_splay < badtree.txt
フムフム ... なかなか 強力ですね。
*1:ソート順のデータ