Binary Search Tree C语言实现

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发起操作。运行如下图:
这里写图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值