【數據結構】之實現二叉搜索樹

#include <stdio.h>
#include <malloc.h>

/**
 * 二叉樹是比較高效的存取結構
 * 單次操作的時間複雜度爲O(logN),N爲總元素個數
 * 二叉搜索樹滿足一下特點:
 * 左子樹上的所有節點都比自己小
 * 右子樹上的所有節點都比自己大
 */

//定義數樹的節點
typedef struct Node{
    int val;            //    struct Node *lc;    //左兒子
    struct Node *rc;    //右兒子
} Node;

Node *new_Node(int val){
    Node *node = malloc(sizeof(Node));
    node->lc = NULL;
    node->rc = NULL;
    node->val = val;
    return node;
}

//二叉搜索樹
typedef struct Bst{
    struct Node *root;
    void (*insert)(struct Bst *, int);
    int (*find)(struct Bst *, int);
    Node *(*delete)(struct Bst *, int);
} Bst;

//插入節點
void insert(Bst *this, int val){
    Node **cur_node = &(this->root);
    while ((*cur_node) != NULL){
        if (val < (*cur_node)->val){
            (cur_node) = &((*cur_node)->lc);
        } else {
            (cur_node) = &((*cur_node)->rc);
        }
    }
    (*cur_node) = new_Node(val);
}

//查找是否有該節點,返回0代表沒有,1代表有
int find(Bst *this, int val){
    Node *cur_node = this->root;
    while (cur_node != NULL){
        if (val < cur_node->val){
            cur_node = cur_node->lc;
        } else if (val > cur_node->val){
            cur_node = cur_node->rc;
        } else {
            return 1;
        }
    }
    return 0;
}

//刪除節點
Node *delete(Bst *this, int val) {
    Node **cur_node = &(this->root);
    //不斷向下尋找
    while ((*cur_node) != NULL) {
        if (val < (*cur_node)->val){
            (cur_node) = &((*cur_node)->lc);
        } else if (val > (*cur_node)->val){
            (cur_node) = &((*cur_node)->rc);
        }
        //如果找到要刪除的節點
        else {
            //如果要刪除的節點左兒子爲空,那就把右兒子補到當前節點上
            if ((*cur_node)->lc == NULL){
                Node *q = (*cur_node)->rc;
                Node *temp = *cur_node;
                (*cur_node) = q;
                free(temp);
                return q;
            }
            //如果要刪除的節點左兒子沒有右兒子,那就把左兒子補到當前節點上
            else if ((*cur_node)->lc->rc == NULL){
                Node *q = (*cur_node)->lc;
                q->rc = (*cur_node)->rc;
                Node *temp = *cur_node;
                (*cur_node) = q;
                free(temp);
                return q;
            }
            //其餘情況:把左兒子的子孫中最大的節點補到要刪除的節點上
            else {
                Node *q = (*cur_node)->lc;
                while (q->rc != NULL){
                    q = q->rc;
                }
                Node *temp = *cur_node;
                q->rc = (*cur_node)->rc;
                q->lc = (*cur_node)->lc;
                (*cur_node) = q;
                free(temp);
                return q;
            }
        }
    }
    return NULL;
}

Bst *new_Bst(){
    Bst *bst = malloc(sizeof(Bst));
    bst->root = NULL;
    bst->insert = &insert;
    bst->find = &find;
    bst->delete = &delete;
    return bst;
}


int main() {
    Bst *bst = new_Bst();
    bst->insert(bst, 2);
    bst->insert(bst, 1);
    bst->insert(bst, 2);
    bst->insert(bst, 3);
    printf("%d\n", bst->find(bst, 2));
    bst->delete(bst, 2);
    bst->delete(bst, 2);
    printf("%d\n", bst->find(bst, 2));

    return 0;
}

運行結果:

1
0




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章