二叉查找树

/*
 * 二叉查找树
 *      1 提供基本的操作集:
 *          得到最大结点
 *          得到最小结点
 *          得到后继结点
 *          得到前驱结点
 *          插入结点
 *          删除结点
 *      2 可以扩展的操作
 *          输出一个有序列
 * 本例中没有对重复的元素进行控制
 *
 * NIL 这个思想是从《算法导论》中来的
 * 有了 NIL 所有的结点都是内结点,便于算法的操作
 * 
 * Successor 算法需要明白两种情况,没有右孩子,有右孩子
 * InsertNode 算法只插入叶子
 * DeleteNode 算法不删除既有右孩子又有左孩子的结点,这种情况需要转化
 */

#include <cstdio>

struct BNode {
    int key;
    BNode *pParent;
    BNode *pRChild;
    BNode *pLChild;
};

class CBTree {
public:
    CBTree() {
        NIL = new BNode;
        NIL->pParent = NIL;
        NIL->pLChild = NIL;
        NIL->pRChild = NIL;

        root = NIL;
    }
    ~CBTree() {
        DestroyTree(root);

        delete NIL;
    }

    int GetMaxKey() {
        BNode *node = GetMaxNode(root);
        if (node == NIL)  return 0;
        else return node->key;
    }

    int GetMinKey() {
        BNode *node = GetMinNode(root);
        if (node == NIL) return 0;
        else return node->key;
    }

    bool KeyInTree(int key) {
        BNode *node = FindInTree(key);
        return node != NIL;
    }

    void InsertKey(int key) {
        BNode *node = new BNode;
        node->key = key;
        node->pParent = NIL;
        node->pLChild = NIL;
        node->pRChild = NIL;
        InsertNode(node);
    }

    void DeleteKey(int key) {
        BNode *node;
        while ((node=FindInTree(key)) != NIL) {
            node = DeleteNode(node) ;
            if (node != NIL) delete node;
        }
    }

private:
    BNode *GetMaxNode(BNode *node) {
        BNode *p = node;
        while (p->pRChild != NIL) {
            p = p->pRChild;
        }
        return p;
    }

    BNode *GetMinNode(BNode *node) {
        BNode *p = node;
        while (p->pLChild != NIL) {
            p = p->pLChild;
        }
        return p;
    }

    BNode *FindInTree(int key) {
        BNode *p = root;
        while (p!=NIL && p->key!=key) {
            if (p->key < key) p = p->pRChild;
            else p = p->pLChild;
        }
        return  p;
    }

    BNode *Successor(BNode *node) {
        if (node->pRChild != NIL) return GetMinNode(node->pRChild);

        BNode *p = node;
        BNode *pParent = p->pParent;
        while (pParent!=NIL && pParent->pRChild==p) {
            p = pParent;
            pParent = p->pParent;
        }

        return pParent;
    }

    BNode *Predecessor(BNode *node) {
        if (node->pLChild != NIL) return GetMaxNode(node->pLChild);

        BNode *p = node;
        BNode *pParent = p->pParent;
        while (pParent!=NIL && pParent->pLChild==p) {
            p = pParent;
            pParent = p->pParent;
        }
        return pParent;
    }

    void InsertNode(BNode *node) {
        BNode *p = root;
        BNode *pParent = NIL;
        while (p != NIL) {
            pParent = p;
            if (p->key < node->key) p = p->pRChild;
            else p = p->pLChild;
        }

        if (p == root) root = node;
        else if (pParent->key < node->key) pParent->pRChild = node;
        else pParent->pLChild = node;

        node->pParent = pParent;
    }

    BNode *DeleteNode(BNode *node) {
        BNode *p = NIL;
        BNode *pChild = NIL;
        if (node->pLChild==NIL || node->pRChild==NIL) p = node;
        else p = Successor(node);

        if (p->pLChild != NIL) pChild = p->pLChild;
        else pChild = p->pRChild;

        if (pChild != NIL) pChild->pParent = p->pParent;

        if (p->pParent == NIL) root = NIL;
        else if (p->pParent->pLChild == p)  p->pParent->pLChild = pChild;
        else p->pParent->pRChild = pChild;

        if (p != node) {
            int tmp = node->key;
            node->key = p->key;
            p->key = tmp;
        }

        return p;
    }

    void DestroyTree(BNode *node) {
        if (node == NIL) return;

        DestroyTree(node->pLChild);
        DestroyTree(node->pRChild);
        delete node;
    }

private:
    BNode *NIL;
    BNode *root;
};

int main() {
    int a[10] = {2, 5, 7, 8, 1, 9 ,10, 3, 4, 6};

    CBTree btree;
    for (int i=0; i<10; ++i)
        btree.InsertKey(a[i]);

    printf("%d %d\n", btree.GetMinKey(), btree.GetMaxKey());

    btree.DeleteKey(1);
    btree.DeleteKey(10);
    printf("%d %d\n", btree.GetMinKey(), btree.GetMaxKey());

    btree.DeleteKey(5);
    if (btree.KeyInTree(5))
        puts("have found 5 in btree");
    else
        puts("can not find 5 in btree");

    if (btree.KeyInTree(4))
        puts("have found 4 in btree");
    else
        puts("can not find 4 in btree");

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值