Binary Search Tree是数据结构中比较有用的一种二叉树结构,这种结构讲大量的数据进行平摊式分布,并且规定大的数在右边,小的数在左边,以这种方式存放的数据可以非常方便地做数据排序和检索。
关于BST的更多信息,可以查看这个链接(英文,讲的非常好,不得不赞):http://algs4.cs.princeton.edu/32bst/
台湾国立清华大学韩永楷老师的MOOC(讲的超级棒,完爆国内,我的代码实现就是参考韩老师的课程内容):http://www.icourse163.org/course/NTHU-451013#/info
下面给出使用C语言的实现方式,我使用了最简单的方式实现,代码中有很多注释,大家可以参考。代码可编译,可运行。
/*************************************************************************
> File Name: bst.c
> Author: Baniel Gao
> Mail: createchance@163.com
> Created Time: Thu 01 Dec 2016 08:29:23 AM EST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int key;
struct node_t* parent;
struct node_t* left;
struct node_t* right;
} node;
/*
* Get min number of this tree pointed by root.
*
* Return min node pointer, NULL if root is NULL.
*/
node* min(node* root)
{
node* min_node = root;
if (root == NULL) {
return NULL;
}
while (min_node->left != NULL) {
min_node = min_node->left;
}
return min_node;
}
/*
* Get max number of this tree pointed by root.
*
* Return max node pointer, NULL if root is NULL.
*/
node* max(node* root)
{
node* max_node = root;
if (root == NULL)
{
return NULL;
}
while (max_node->right != NULL)
{
max_node = max_node->right;
}
return max_node;
}
/*
* Search the number k.
*
* Return node pointer which contains the key, NULL if do not match anything.
*/
node* search(node* root, int k)
{
node* current = root;
if (root == NULL) {
return NULL;
}
while (1) {
if (current->key == k) {
break;
} else if (current->key > k) {
current = current->left;
} else {
current = current->right;
}
if (current == NULL) {
break;
}
}
return current;
}
/*
* Find the predeccessor of k.
*
* Return node pointer of predeccessor if success, NULL if find nothing.
*/
node* predecessor(node* root, int k)
{
if (root == NULL)
{
return NULL;
}
node* target = search(root, k);
if (target != NULL) {
if (target->left != NULL) {
target = max(target->left);
} else {
while (1) {
if (target->parent == NULL) {
target = target->parent;
break;
} else if (target == target->parent->right) {
target = target->parent;
break;
} else if (target == target->parent->left) {
target = target->parent;
}
}
}
}
return target;
}
/*
* Find successor of number k.
*
* Return node pointer of successor if success, NULL if find nothing.
*/
node* successor(node* root, int k)
{
if (root == NULL) {
return NULL;
}
node* target = search(root, k);
if (target != NULL) {
if (target->right != NULL) {
target = min(target->right);
} else {
while (1) {
if (target->parent == NULL) {
target = target->parent;
break;
} else if (target == target->parent->left) {
target = target->parent;
break;
} else if (target == target->parent->right) {
target = target->parent;
}
}
}
}
return target;
}
/*
* insert one number k to binary search tree.
*
* Return node pointer if success, NULL if key already exists.
*/
node* insert(node* root, int k)
{
node* current = root;
if (root == NULL) {
root = (node*) malloc(sizeof(node));
root->key = k;
return root;
}
while (1) {
if (current->key == k)
{
current = NULL;
break;
} else if (current->key > k) {
if (current->left != NULL) {
current = current->left;
} else {
// no left child, so we are left child, create one node and insert.
node* new = (node*) malloc(sizeof(node));
new->key = k;
new->parent = current;
new->left = NULL;
new->right = NULL;
current->left = new;
// move current to target node.
current = current->left;
break;
}
} else if (current->key < k) {
if (current->right != NULL) {
current = current->right;
} else {
// no right child, so we are left child, create one node and insert.
node* new = (node*) malloc(sizeof(node));
new->key = k;
new->parent = current;
new->left = NULL;
new->right = NULL;
current->right = new;
// move current to target node.
current = current->right;
break;
}
}
}
return current;
}
/*
* Delete node contains number k.
*
* Return 0 if succeed, -1 if number k not found or tree root is NULL, 1 if the tree is empty after deletion.
*/
int delete(node* root, int k)
{
if (root == NULL) {
return -1;
}
// Find this node first.
node* target = search(root, k);
// Well, we can not find this node.
if (target == NULL) {
return -1;
}
/* Case 1: this node is leaf node. */
if (target->left == NULL && target->right == NULL) {
if (target != root) {
if (target == target->parent->right) {
target->parent->right = NULL;
} else {
target->parent->left = NULL;
}
} else {
root = NULL;
}
free(target);
}
/* Case 2: this node has only one child node. */
else if (target->left != NULL && target->right == NULL) {
// Case 2.1: this node only has a left child.
if (target == root) {
node* predecessor_node = predecessor(root, k);
if (predecessor_node == NULL) {
return -1;
}
// Replace the number first.
target->key = predecessor_node->key;
// predecessor does not have any child.
if (predecessor_node->left == NULL && predecessor_node->right == NULL) {
if (target->right == predecessor_node) {
target->right = NULL;
} else {
predecessor_node->parent->left = NULL;
}
}
// predecessor only have left child.
else {
predecessor_node->parent->right = predecessor_node->left;
predecessor_node->left->parent = predecessor_node->parent;
}
// Free predecessor node.
free(predecessor_node);
} else {
target->left->parent = target->parent;
if (target == target->parent->left) {
target->parent->left = target->left;
} else {
target->parent->right = target->left;
}
}
} else if (target->left == NULL && target->right != NULL) {
// Case 2.2: this node only has a right child.
if (target == root) {
node* successor_node = successor(root, k);
if (successor_node == NULL) {
return -1;
}
// Replace the number first.
target->key = successor_node->key;
// successor does not have any child.
if (successor_node->left == NULL && successor_node->right == NULL) {
if (target->right == successor_node) {
target->right = NULL;
} else {
successor_node->parent->left = NULL;
}
}
// successor only have right child.
else {
successor_node->parent->left = successor_node->right;
successor_node->right->parent = successor_node->parent;
}
// Free successor node.
free(successor_node);
} else {
target->right->parent = target->parent;
if (target == target->parent->left) {
target->parent->left = target->right;
} else {
target->parent->right = target->right;
}
}
}
/* Case 3: this node has two child node. */
else if (target->left != NULL && target->right != NULL) {
node* successor_node = successor(root, k);
if (successor_node == NULL) {
return -1;
}
// Replace the number first.
target->key = successor_node->key;
// Case 3.1: successor does not have any child.
if (successor_node->left == NULL && successor_node->right == NULL) {
if (target->right == successor_node) {
target->right = NULL;
} else {
successor_node->parent->left = NULL;
}
}
// Case 3.2: successor only have right child.
else {
successor_node->parent->left = successor_node->right;
successor_node->right->parent = successor_node->parent;
}
// Free successor node.
free(successor_node);
}
if (root == NULL) {
return 1;
}
return 0;
}
/*
* Modify one node'key. Change it from src to dst.
*
* Return the node modified, NULL if this node does not exist.
*/
node* modify(node* root, int src, int dst)
{
if (root == NULL) {
return NULL;
}
// We have to make sure the src exists and dst does not exist.
node* source = search(root, src);
node* destination = search(root, dst);
if (source == NULL) {
printf("The source number %d does not exist. \n", src);
return NULL;
}
if (destination != NULL) {
printf("The destination number %d already exist. \n", dst);
return NULL;
}
// we delete the old node first.
delete(root, src);
// then insert new node.
insert(root, dst);
return source;
}
/*
* Print this tree by inorder.
*
* The numbers printed is sorted.
*/
void print_tree_inorder(node* root) {
if(root != NULL) {
print_tree_inorder(root->left);
printf("%d ",root->key);
print_tree_inorder(root->right);
}
}
/*
* Console helper function.
*/
void show_help()
{
printf("1. insert\n");
printf("2. delete\n");
printf("3. modify\n");
printf("4. search\n");
printf("5. predeccessor\n");
printf("6. successor\n");
printf("7. min\n");
printf("8. max\n");
printf("9. print tree\n");
}
int main()
{
char cmd;
int key, key2;
node* root = NULL;
printf("This is a binary search tree demo.\n");
while (1) {
printf("Command<m for help>: ");
fflush(stdout);
scanf("%c", &cmd);
if (cmd == 'm') {
show_help();
} else if (cmd == '1') {
printf("Input number to insert: ");
fflush(stdout);
scanf("%d", &key);
node* inserted_node = insert(root, key);
if (root == NULL) {
root = inserted_node;
}
if (inserted_node == NULL) {
printf("The number %d already exist. \n", key);
} else {
printf("Complete!\n");
}
} else if (cmd == '2') {
printf("Input number to delete: ");
fflush(stdout);
scanf("%d", &key);
int ret = delete(root, key);
if (ret < 0) {
printf("The numnber %d does not exist. \n", key);
} else if (ret == 1) {
printf("The tree is empty now. \n");
root = NULL;
} else {
printf("Complete!\n");
}
} else if (cmd == '3') {
printf("Input the number you want to change from and to: ");
fflush(stdout);
scanf("%d %d", &key, &key2);
node* modified_node = modify(root, key, key2);
if (modified_node == NULL) {
printf("Modify failed. \n");
} else {
printf("Complete!\n");
}
} else if (cmd == '4') {
printf("Input the number you want to search: ");
fflush(stdout);
scanf("%d", &key);
node* result = search(root, key);
if (result == NULL) {
printf("The number %d does not exist.\n", key);
} else {
printf("Complete!\n");
}
} else if (cmd == '5') {
printf("Input the number you want to find predecessor: ");
fflush(stdout);
scanf("%d", &key);
node* result = predecessor(root, key);
if (result == NULL) {
printf("Predecessor do not found!\n");
} else {
printf("Predecessor is %d. \n", result->key);
}
} else if (cmd == '6') {
printf("Input the number you want to find successor: ");
fflush(stdout);
scanf("%d", &key);
node* result = successor(root, key);
if (result == NULL) {
printf("Successor do not found!\n");
} else {
printf("Successor is %d. \n", result->key);
}
} else if (cmd == '7') {
node* result = min(root);
if (result != NULL) {
printf("Min number is: %d. \n", result->key);
} else {
printf("This tree is empty! \n");
}
} else if (cmd == '8') {
node* result = max(root);
if (result != NULL) {
printf("Max number is: %d. \n", result->key);
} else {
printf("This tree is empty! \n");
}
} else if (cmd == '9') {
if (root != NULL) {
print_tree_inorder(root);
printf("\n");
} else {
printf("This tree is empty! \n");
}
}
getchar();
}
return 0;
}
上面程序支持9中操作:
1. insert:插入一个数据,如果当前bst为空,那么新建根节点,并且赋值
2. delete:删除一个数据,如果给定数字不存在,则删除失败
3. modify:修改一个数据,需要源数据存在,且目标数据不能存在
4. search:检索一个数据,如果数据存在成功返回,反之失败
5. predeccessor:检索一个数的前导数(这个数必须存在于树中),就是比目标数小的所有数的最大数
6. successor:检索一个数的后导数(这个数必须存在于数中),就是比目标数大的所有数的最小数
7. min:检索树中最小的数
8. max:检索树中最大的数
9. print tree:按照中序打印树,对于BST来说中序就是所有数的升序排序
分别输入以上操作前的序号,就可以对BST发起操作。运行如下图:

6581

被折叠的 条评论
为什么被折叠?



