Skip to content

Commit

Permalink
Test bst-put
Browse files Browse the repository at this point in the history
  • Loading branch information
bangoc committed Mar 22, 2024
1 parent 9a68a37 commit baf9101
Show file tree
Hide file tree
Showing 6 changed files with 397 additions and 0 deletions.
4 changes: 4 additions & 0 deletions training/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 2.8)
project(training)
add_executable(demo demo.c bst-int.c)
add_executable(rand-put rand-put.c bst-int.c)
3 changes: 3 additions & 0 deletions training/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Có thể biên dịch bằng CMake,
hoặc trực tiếp với trình biên dịch, ví dụ:
gcc -o rand-put rand-put.c bst-int.c
233 changes: 233 additions & 0 deletions training/bst-int.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/* (C) Nguyễn Bá Ngọc 2023 */

#include "bst-int.h"

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Minh họa ánh xạ char * => int dựa trên cây
nhị phân tìm kiếm. */

struct bst_node {
int key;
struct bst_node *left;
struct bst_node *right;
struct bst_node *top;
};

struct bst_tree {
struct bst_node *root;
int size;
};

struct bst_node *bst_node(int key) {
struct bst_node *nn = malloc(sizeof(struct bst_node));
nn->key = key;
nn->left = NULL;
nn->right = NULL;
nn->top = NULL;
return nn;
}

struct bst_tree *bst_tree() {
struct bst_tree *t = malloc(sizeof(struct bst_tree));
t->root = NULL;
t->size = 0;
}

/**
* Thêm khóa key vào cây t, trong trường hợp key đã tồn tại thì trả về con trỏ
* tới giá trị của nút tương ứng với key. Nếu khóa chưa tồn tại thì trả về NULL.
*/
struct bst_node *bst_put(struct bst_tree *t, int key) {
if (t->root == NULL) {
t->root = bst_node(key);
++t->size;
return NULL;
}
struct bst_node *p = t->root, *c;
for(;;) {
if (key == p->key) {
return p;
}
c = key < p->key? p->left: p->right;
if (!c) {
break;
}
p = c;
}
struct bst_node *nn = bst_node(key);
if (key < p->key) {
p->left = nn;
} else {
p->right = nn;
}
nn->top = p;
++t->size;
return NULL;
}

struct bst_node *bst_search(struct bst_tree *t, int key) {
struct bst_node *u = t->root;
while (u) {
if (key == u->key) {
return u;
}
u = key < u->key ? u->left: u->right;
}
return NULL;
}

int bst_equal(struct bst_tree *t1, struct bst_tree *t2) {
if (t1->size != t2->size) {
return 0;
}
struct bst_node *n1 = bst_first_lnr(t1), *n2 = bst_first_lnr(t2);
while (n1 && n2) {
if (n1->key != n2->key) {
return 0;
}
n1 = bst_next_lnr(n1);
n2 = bst_next_lnr(n2);
}
return 1;
}

void bst_change(struct bst_node *old_node, struct bst_node *new_node,
struct bst_tree *t) {
struct bst_node *top = old_node->top;
if (top) {
if (top->left == old_node) {
top->left = new_node;
} else if (top->right == old_node) {
top->right = new_node;
}
} else {
t->root = new_node;
}
if (new_node) {
new_node->top = top;
}
}

/* Xóa nút tương ứng với khóa khỏi cây
* Trả về 1 nếu đã xóa, hoặc 0 nếu khóa không tồn tại
*/
int bst_remove(struct bst_tree *t, int key) {
struct bst_node *d = bst_search(t, key);
if (!d) {
return 0;
}
struct bst_node *n = d, *nr = n->right, *tmp = n->left;
if (!tmp) {
bst_change(n, nr, t);
} else if (!nr) {
bst_change(n, tmp, t);
} else {
struct bst_node *s = nr;
/* Trường hợp 2: Nút liền sau n là con phải của n.
*
* (n) (s)
* / \ / \
* (x) (s) -> (x) (sr)
* \
* (sr)
*/
tmp = nr->left;
if (tmp) {
/* Trường hợp 3: Nút liền sau n là nút trái nhất trong
* cây con phải của n
*
* (n) (s)
* / \ / \
* (x)(nr) -> (x)(nr)
* / /
* (top) (top)
* / /
* (s) (sr)
* \
* (sr)
*/
struct bst_node *top;
do {
top = s;
s = tmp;
tmp = tmp->left;
} while (tmp);
struct bst_node *sr = s->right;
top->left = sr;
if (sr) {
sr->top = top;
}
s->right = nr;
nr->top = s;
}
tmp = n->left;
s->left = tmp;
tmp->top = s;
bst_change(n, s, t);
}
free(d);
--t->size;
return 1;
}

void bst_node_print_rnl(struct bst_node *n, int depth) {
if (n->right) {
bst_node_print_rnl(n->right, depth + 1);
}
if (depth > 0) {
printf("%1$*2$c", ' ', 2 * depth);
}
printf("%d\n", n->key);
if (n->left) {
bst_node_print_rnl(n->left, depth + 1);
}
}

void bst_pprint(struct bst_tree *t) {
if (t->root) {
bst_node_print_rnl(t->root, 0);
}
}

void bst_node_free_lrn(struct bst_node *n) {
if (n->left) {
bst_node_free_lrn(n->left);
}
if (n->right) {
bst_node_free_lrn(n->right);
}
free(n);
}

void bst_free(struct bst_tree *t) {
if (t->root) {
bst_node_free_lrn(t->root);
}
free(t);
}

struct bst_node *bst_left_most(struct bst_node *n) {
while (n->left) {
n = n->left;
}
return n;
}

struct bst_node *bst_first_lnr(struct bst_tree *t) {
return bst_left_most(t->root);
}
struct bst_node *bst_next_lnr(struct bst_node *n) {
if (n->right) {
return bst_left_most(n->right);
}
struct bst_node *top = n->top;
while (top != NULL && n == top->right) {
n = top;
top = n->top;
}
return top;
}
18 changes: 18 additions & 0 deletions training/bst-int.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef BST_INT_H_
#define BST_INT_H_

struct bst_node;
struct bst_tree;

struct bst_node *bst_node(int key);
struct bst_tree *bst_tree();
struct bst_node *bst_put(struct bst_tree *t, int key);
struct bst_node *bst_search(struct bst_tree *t, int key);
struct bst_node *bst_first_lnr(struct bst_tree *t);
struct bst_node *bst_next_lnr(struct bst_node *n);
int bst_equal(struct bst_tree *t1, struct bst_tree *t2);
int bst_remove(struct bst_tree *t, int key);
void bst_pprint(struct bst_tree *t);
void bst_free(struct bst_tree *t);

#endif // BST_INT_H_
16 changes: 16 additions & 0 deletions training/demo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "bst-int.h"

#include <stdio.h>

int main() {
struct bst_tree *t = bst_tree();
int key;
while (scanf("%d", &key) == 1) {
if (key == -1) {
break;
}
bst_put(t, key);
}
bst_pprint(t);
bst_free(t);
}
Loading

0 comments on commit baf9101

Please sign in to comment.