二叉搜索樹的實現(數據結構中的“hello,world”)

自己實現的二叉搜索樹,可能不是什麼優秀的實現版本,但是好歹是自己通過學習二叉搜索樹的原理,然後摸索出的自己的實現版本。

這裏還用到了C++中的引用,雖然不是什麼大事,但一度困擾了我。

BST的原理可以在任何一本有關數據結構的教科書中找到,關鍵是如何用代碼實現。每個人的實現版本都不太一樣。

接下來,我要找一些簡潔高效而又正確的實現版本,提升自己的能力。

/*
二叉搜索樹模版
成員函數
一、查找函數 
Node * Find(tree_node &root, int key)
功能:在根結點爲root的BST中查找關鍵值爲key的結點
二、插入函數 
void Insert(tree_node &root, int key)
功能:在根結點爲root的BST中插入關鍵值爲key的結點
三、刪除函數 
void DeleteNode(tree_node &root, tree_node u)
功能:在根結點爲root的BST中刪除結點u
*/
#include <cstdio>
#include <cstdlib>

struct Node {
    int key;
    Node *left, *right;
}*root = NULL;
typedef struct Node *tree_node;

//在根爲root的二叉搜索樹中找鍵值爲key的結點
Node * Find(tree_node &root, int key) {
    tree_node u = root;
    while (u != NULL && u->key != key) {
        if (key < u->key)
            u = u->left;
        else
            u = u->right;
    }
    return u;
}
//在根爲root的二叉搜索樹中插入鍵值爲key的結點
void Insert(tree_node &root, int key)
{
    Node *z = (Node *)malloc(sizeof(Node));
    Node *f = NULL, *x = root;
    z->left = z->right = NULL;
    z->key = key;
    // 尋找結點f,其中f爲待插入結點z的父結點
    while (x != NULL) {
        f = x;
        if (z->key < x->key)
            x = x->left;
        else
            x = x->right;
    }
    if (f != NULL) {
        if (z->key < f->key)
            f->left = z;
        else
            f->right = z;
    } else
        root = z;  //根結點root爲空,插入結點就是根結點

    return;
}

//刪除指定結點
void DeleteNode(tree_node &root, tree_node u)
{
    bool L = false;//判斷結點u是否在它的父結點的左邊,是 L爲true,否則爲false
    tree_node father = NULL, x = root;
    //尋找結點u的父結點father
    while (x != u) {
        father = x;
        if (u->key < x->key)
            x = x->left;
        else
            x = x->right;
    }
    if (father != NULL && u->key < father->key) L = true;
    //分類一: 結點u是葉子結點
    if (u->left == NULL && u->right == NULL) {
        free(u);
        if (father != NULL) {
            if (L) father->left = NULL;
            else father->right = NULL;
        } else
            root = NULL; // father爲NULL,說明被剷除的是根結點root
    }
    //分類二(1): 結點u只有右子樹
    else if (u->left == NULL && u->right != NULL) {
        //如果u就是根結點root
        if (u == root) {
            root = u->right;
            free(u);
        } else {
            //u不是根結點
            if (L)
                father->left = u->right;
            else
                father->right = u->right;
            free(u);
        }
    }
    //分類二(2): 結點u只有左子樹,原理同u只有左子樹相同
    else if (u->left != NULL && u->right == NULL) {
        if (u == root) {
            root = u->left;
            free(u);
        } else {
            if (L)
                father->left = u->left;
            else
                father->right = u->left;
            free(u);
        }
    } else {
    //分類三: 結點u的左右子樹均存在
        tree_node r = u->right, f = u;
        //r存放結點u右子樹中最小的結點,f存放r的父結點
        while (r->left != NULL) {
            f = r;
            r = r->left;
        }

        u->key = r->key;
        if (f != u)             //最小結點在結點u->right的左子樹中時
            f->left = r->right;
        else                    //最小結點就是u->right
            f->right = r->right;
        free(r);
    }
    return;
}

//前序遍歷的遞歸實現
void Preorder(Node *u)
{
    if (u == NULL)
        return;
    printf(" %d", u->key);
    Preorder(u->left);
    Preorder(u->right);
}
//中序遍歷的遞歸實現
void Inorder(Node *u)
{
    if (u == NULL)
        return;
    Inorder(u->left);
    printf(" %d", u->key);
    Inorder(u->right);
}
//後序遍歷的遞歸實現
void Postorder(Node *u)
{
    if (u == NULL)
        return;
    Postorder(u->left);
    Postorder(u->right);
    printf(" %d", u->key);
}

int main()
{
    int x;
    char cmd[10];

    while (scanf("%s", cmd) == 1) {
        if (cmd[0] == 'f') {
            scanf("%d", &x);
            tree_node t = Find(root, x);
            if (t != NULL) printf("yes\n");
            else printf("no\n");
        } else if (cmd[0] == 'i') {
            scanf("%d", &x);
            Insert(root, x);
        } else if (cmd[0] == 'd') {
            scanf("%d", &x);
            tree_node u = Find(root, x);
            DeleteNode(root, u);
        } else if (cmd[0] == 'p') {
            Inorder(root);
            printf("\n");
            Preorder(root);
            printf("\n");
            Postorder(root);
            printf("\n");
        } else
            break;
    }

    return 0;
}


發佈了58 篇原創文章 · 獲贊 31 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章