はじめての C
ランダム関数 rand() を 利用した balance tree を つくってみる。 RAND_MAX は 生成される 乱数の範囲 (K&R 2nd p317)。 ライブラリ time.h を 使って srand() の引数を 決めるようにした。
/* rand_insert.c */
#include
#include
#include struct Node {
int data;
struct Node *left;
struct Node *right;
};
struct Tree {
struct Node *root;
};
int insert();
int norm_insert();
int root_insert();
void btree_walk();
int tree_height();
void rotate_right();
void rotate_left();
main()
{
int value;
struct Tree *root;
srand(time(NULL));
root = NULL;
while (fscanf(stdin, "%d", &value) != EOF)
insert(&root, value);
btree_walk(root);
putchar('\n');
printf("%d\n", tree_height(root));
return 0;
}
int insert(struct Node **tree, int key)
{
if (rand() < RAND_MAX/2)
return root_insert(tree, key);
else
return norm_insert(tree, key);
}
int norm_insert(struct Node **tree, int key)
{
int rc;
if (*tree == NULL) {
*tree = malloc(sizeof(**tree));
if (*tree == NULL)
rc = 0;
(*tree)->data = key;
(*tree)->left = NULL;
(*tree)->right = NULL;
rc = 1;
}
else if (key < (*tree)->data)
rc = norm_insert(&(*tree)->left, key);
else if (key > (*tree)->data)
rc = norm_insert(&(*tree)->right, key);
else
rc = 0;
return rc;
}
int root_insert(struct Node **tree, int key)
{
int rc;
if (*tree == NULL) {
*tree = malloc(sizeof(**tree));
if (*tree == NULL)
rc = 0;
(*tree)->data = key;
(*tree)->left = NULL;
(*tree)->right = NULL;
rc = 1;
}
else if (key < (*tree)->data) {
rc = root_insert(&(*tree)->left, key);
rotate_right(tree);
}
else if (key > (*tree)->data) {
rc = root_insert(&(*tree)->right, key);
rotate_left(tree);
}
else
rc = 0;
return rc;
}
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;
}
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;
}
入力データとして ソート順のテキストを準備 ... あれっ? どうやって つくるんだった? (;_;)
/* badtree.c */
#include
#define MAX 100main()
{
int i, n;
n = 0;
for (i = 0; i < MAX; i++) {
n = i;
printf("%d ", n);
}
putchar('\n');
return 0;
}
ソートデータを 作成。
$cc -o badtree badtree.c
$./badtree > badtree.txt
コンパイルして、確認。 t_balance と 比べてみる。
$cc -c rand_insert.c
$cc -o rand_insert rand_insert.o
$./rand_insert < random.txt
$./t_balance < badtree.txt
$./rand_insert < badtree.txt