B树 C++代码 总感觉哪里有问题,只供参考

#include<iostream>
using namespace std;

static const int MMM = 5;      //B树阶数
//static const int key_max = MMM + 1;      //key[0]不作用途, key[m]用于插入分裂时使用
#define DEFAULT 333
struct node
{
    int *key;      //关键码数组  [m/2-1]到[m-1],若m/2-1小于1,则关键码至少为1 
    //T *data;      //暂时不想考虑,其实data数组只要紧跟key数组就行
    node *parent;
    node **child;
    int key_num;      //当前关键码个数

    node() :key_num(0), parent(NULL), child(NULL)
    {
        key = new int[MMM + 1];
        key[0] = 0;
        child = new node*[MMM + 1];
        parent = NULL;
        for (int i = 0; i < MMM + 1; i++)
        {
            child[i] = NULL;
        }
    }
    ~node()      //用类对象表示节点时必须写,结构体应该可以不用谢
    {
        for (int i = 0; i < MMM + 1; i++)
        {
            delete child[i];
            child[i] = NULL;
        }
        delete key;
        delete child;
        child = NULL;
    }
};

class B_tree
{
private:
    node *b_root;
public:
    B_tree() :b_root(new node) {}
    ~B_tree() 
    {
        Destory(b_root);

        delete b_root->key;
        b_root->key = NULL;
        b_root->parent = NULL;
        for (int i = 0; i < b_root->key_num; i++)
        {
            delete b_root->child[i];
            b_root->child[i] = NULL;
        }
        b_root = NULL;
    };

    void Insert(const int k);      //往B树中插入节点   只要考虑最大子树个数,删除是才要考虑【m/2】这个最小子树个数
    node* Search(node *root, const int k);      //在B树中寻找关键码值为k的关键码,并返回所在的节点
    node* Split(node* &root, const int index);      //插入节点后向上分裂   返回值类型任意
    node* Root();      //获取根节点
    void Level_order();      //层序遍历B树
    void Adjust(node *root);      //调整B树
    bool Remove(const int k);      //删除内部节点,用后继节点节点代替,即复制删除
    void Destory(node *root);      //销毁B树
};


inline node* B_tree::Root()
{
    return b_root;
}

node* B_tree::Search(node *root, const int k)
{
    if (root->key_num == 0)
    {
        cout << "B树为空,查找失败!" << endl;
        return NULL;
    }
    while (root->child[0] != 0)
    {
        for (int i = root->key_num; i >= 0;  i--)
        {
            if (root->key[i] == k)
            {
                cout << "关键码值 " << k << " 是B树的关键码!" << endl;
                return root;
            }
            if (root->key[i] < k)
            {
                root = root->child[i];
                break;
            }
        }
    }
    for (int i = 1; i <= root->key_num; i++)
    {
        if (root->key[i] == k)
        {
            cout << "关键码值 " << k << " 是B树的关键码!" << endl;
            return root;
        }
    }
    cout << "关键码值 " << k << " 不是B树的关键码!" << endl;
    return NULL;
}

void B_tree::Insert(const int k)      //往B树中插入节点   只要考虑最大子树个数,删除是才要考虑【m/2】这个最小子树个数
{
    node *root = b_root;
    for (int m = 1; m <= root->key_num; m++)
    {
        cout << "[" << root->key[m] << "]";
    }
    cout << endl;
    if (root->child[0] == NULL && root->key_num == 0)
    {
        root->key_num++;
        root->key[1] = k;
        root->parent = NULL;
        return;
    }
    int i, j;
    while (root->child[0] != NULL)
    {
        for (i = root->key_num; i >= 0; i--)
        {
            if (root->key[i] == k)
            {
                cout << "关键码值 " << k << " 已经是B树的关键码!" << endl;
                return;
            }
            if (root->key[i] < k)
            {
                root = root->child[i];
                break;
            }
        }
    }
    for (i = root->key_num; i >= 0; i--)
    {
        if (root->key[i] == k)
        {
            cout << "B树中已经有 " << k << " 这个关键码" << endl;
            return;
        }
        if (root->key[i] < k)
        {
            for (j = root->key_num; j > i; j--)
            {
                root->key[j + 1] = root->key[j];
            }
            root->key[i + 1] = k;
            root->key_num++;
            break;
        }
    }
    while (root->key_num == MMM)
    {
        Split(root, (1 + MMM) / 2);
    }
}

node* B_tree::Split(node* &root, int index)      //root节点是待分裂节点
{
    int i, j;
    int k = root->key[index];
    node *other = new node;      //root节点分裂后的另一半
    for (i = index + 1; i <= root->key_num; i++)
    {
        other->key[i - index] = root->key[i];
        other->key_num++;
    }
    if (root->child[0] != NULL)       //分裂节点为内部节点
    {
        
        for (i = index; i <= root->key_num; i++)
        {
            other->child[i - index] = root->child[i];      //分裂内部节点时,孩子比关键码要多一个
            root->child[i]->parent = other;      //这个是重中之重, 移动分裂孩子节点其父节点必须一并修改
            //delete root->child[i];      //删除后,空间释放,会出问题,指针置空就行  类可以,结构体删除即释放
            root->child[i] = NULL;
        }
    }
    root->key_num = index - 1;
    if (root->parent == NULL)
    {
        node *r = new node;      //新根节点,树的高度会增加
        r->key_num++;
        r->key[1] = k;
        r->child[0] = root;
        r->child[1] = other;
        r->parent = NULL;
        other->parent = r;
        root->parent = r;
        b_root = r;
        return b_root;
    }
    else
    {
        node *p = root->parent;
        for (i = p->key_num; i >= 0; i--)
        {
            if (p->key[i] < k)
            {
                break;
            }
        }
        for (j = p->key_num; j > i; j--)
        {
            p->key[j + 1] = p->key[j];
            p->child[j + 1] = p->child[j];
        }
        p->key_num++;
        p->key[i + 1] = k;
        p->child[i + 1] = other;
        //p->child[i] = root;      //注意下就行
        other->parent = p;
        root = p;
        return root;
    }
}

void B_tree::Level_order()      //层序遍历B树
{
    if (b_root == NULL)
    {
        cout << "B树为空,层序遍历失败!" << endl;
        return;
    }
    node **qu = new node*[DEFAULT];
    int front = 0;
    int rear = 0;
    qu[front] = qu[rear++] = b_root;
    int max = DEFAULT;      //假设循环空间足够大,要不然还得判断是不是装满了
    int counter = 0;
    cout << "B树的层序遍历为:{";
    while (front != rear)
    {
        node *p = qu[front];
        front = (front + 1) % max;
        if (counter = 1)
        {
            cout << "[";
            for (int i = 1; i <= p->key_num; i++)
            {
                cout << " " << p->key[i] << " ";
            }
            cout << "]";
        }
        //cout << endl;
        if (p->child[0] != NULL)
        {
            for (int j = 0; j <= p->key_num; j++)
            {
                qu[rear] = p->child[j];
                rear = (rear + 1) % max;
            }
        }
        counter++;
    }
    cout << "}";
    
}

bool B_tree::Remove(const int k)
{
    node *root = b_root;
    root = Search(root, k);
    if (root == NULL)
    {
        cout << "B树中不存在关键码值为 " << k << " 的关键码!" << endl;
        return false;
    }
    int i, index;
    for (i = 1; i <= root->key_num; i++)      //确定k所在的节点
    {
        if (root->key[i] == k)
        {
            index = i;      //k为其所在节点第i个元素
            break;
        }
    }
    if (root->child[0] == NULL)      //被删除的关键码在叶节点上
    {
        for (i = index; i < root->key_num; i++)      //在节点中删除k,并移动关键码数组
        {
            root->key[i] = root->key[i + 1];
        }
        root->key_num--; 
        if (root->parent == NULL)      //只有根节点
        {
            if (root->key_num == 0)      //根节点没有关键码,B树为空     
            {
                root = NULL;
            }
            return true;
        }
        if (root->key_num >= (MMM - 1) / 2)      //删除k后的节点关键码的个数比最少大,直接返回
        {
            return true;
        }
        else
        {
            Adjust(root);      //调整B树
        }
    }
    if (root->child[0] != NULL)      //如果k在内部节点中,先把其与其后继最小的交换,然后相当于删除叶节点         
    {
        node *curr = root->child[index];
        while (curr->child[0] != NULL)      //直到找到k节点后继中的最小值,然后复制删除
        {
            curr = curr->child[0];
        }
        root->key[index] = curr->key[1];      //复制删除
        curr->key[1] = k;
        for (i = 1; i < curr->key_num; i++)
        {
            curr->key[i] = curr->key[i + 1];
        }
        curr->key_num--;
        if (curr->key_num >= (MMM - 1) / 2)
        {
            return true;
        }
        else
        {
            Adjust(curr);
        }
    }
    return true;
}

void B_tree::Adjust(node *root)
{
    if (root->parent == NULL)
    {
        return;
    }
    int i, index;
    node *p = root->parent;
    for (i = 0; i <= p->key_num; i++)      //确定root节点在父节点孩子节点指针数组中的位置
    {
        if (p->child[i] == root)
        {
            index = i;
            break;
        }
    }
    cout << index << endl;
    
    if (index == 0)      //防止越界,不写这个判定条件跟右边借总会出问题,非得这样坑我
    {
        if (p->child[index + 1] != NULL && p->child[index + 1]->key_num > (MMM - 1) / 2)      //右兄弟
        {
            node *right = p->child[index + 1];
            root->key_num++;
            root->key[root->key_num] = p->key[index + 1];
            p->key[index + 1] = right->key[1];
            for (i = 1; i < right->key_num; i++)
            {
                right->key[i] = right->key[i + 1];
            }
            if (root->child[0] != NULL)      //root不为叶子节点
            {
                root->child[root->key_num] = right->child[0];
                right->child[0]->parent = root;
                for (i = 0; i < right->key_num; i++)
                {
                    right->child[i] = right->child[i + 1];
                }
                right->child[right->key_num] = NULL;
            }
            right->key_num--;
            return;
        }
        if (p->child[index + 1] != NULL && p->child[index + 1]->key_num == (MMM - 1) / 2)
    {
        node *right = p->child[index + 1];
        root->key_num++;
        root->key[root->key_num] = p->key[index + 1];
        if (root->child[0] != NULL)
        {
            int mmm = root->key_num;
            for (i = 0; i <= right->key_num; i++)
            {
                root->child[mmm++] = right->child[i];
                right->child[i]->parent = root;
            }
        }
        for (i = 1; i <= right->key_num; i++)
        {
            root->key_num++;
            root->key[root->key_num] = right->key[i];
        }
        for (i = index + 1; i < p->key_num; i++)
        {
            p->child[i] = p->child[i + 1];
            p->key[i] = p->key[i + 1];
        }
        p->child[p->key_num] = NULL;
        p->key_num--;
        delete right;
        right = NULL;
        if (p == b_root && p->key_num == 0)
        {
            p = NULL;
            b_root = root;
            root->parent = NULL;
            return;
        }
        if (p->key_num < (MMM - 1) / 2)
        {
            Adjust(p);
        }
    }
    }
    if (index > 0 && index <= p->key_num)
    {
        if (p->child[index - 1] != NULL && p->child[index - 1]->key_num > (MMM - 1) / 2)      //左兄弟
        {
            node *left = p->child[index - 1];
            for (i = root->key_num; i >= 1; i--)
            {
                root->key[i + 1] = root->key[i];
            }
            root->key[1] = p->key[index];
            p->key[index] = left->key[left->key_num];
            if (root->child[0] != NULL)
            {
                for (i = root->key_num; i >= 0; i--)
                {
                    root->child[i + 1] = root->child[i];
                }
                root->child[0] = left->child[left->key_num];
                left->child[left->key_num]->parent = root;
                left->child[left->key_num] = NULL;
            }
            root->key_num++;
            left->key_num--;
            return;
        }
        if (p->child[index - 1] != NULL && p->child[index - 1]->key_num == (MMM - 1) / 2)
        {
            node *left = p->child[index - 1];
            left->key_num++;
            left->key[left->key_num] = p->key[index];
            if (root->child[0] != NULL)
            {
                int mmm = left->key_num;
                for (i = 0; i <= root->key_num; i++)
                {
                    left->child[mmm++] = root->child[i];
                    root->child[i]->parent = left;
                }
            }
            for (i = 1; i <= root->key_num; i++)
            {
                left->key_num++;
                left->key[left->key_num] = root->key[i];
            }
            for (i = index; i < p->key_num; i++)
            {
                p->child[i] = p->child[i + 1];
                p->key[i] = p->key[i + 1];
            }
            p->child[p->key_num] = NULL;
            p->key_num--;
            root = NULL;
            if (p == b_root && b_root->key_num == 0)
            {
                p = NULL;
                b_root = left;
                left->parent = NULL;
                return;
            }
            if (p->key_num < (MMM - 1) / 2)
            {
                Adjust(p);
            }
        }
    }
    
}

void B_tree::Destory(node *root)
{
    if (root->child[0] == NULL && root->key_num != 0)
    {
        delete root->key;
        root->key = NULL;
        root->parent = NULL;
        for (int i = 0; i < root->key_num; i++)
        {
            delete root->child[i];
            root->child[i] = NULL;
        }
        delete root;
        root = NULL;
        return;
    }
    if (root->child[0] != NULL)
    {
        for (int i = 0; i <= root->key_num; i++)
        {
                Destory(root->child[i]);
        }
    }
}

void main()
{
    B_tree tree;
    node *root = new node;
    int arr[22] = { 39,22,97,41,53,13,21,40,30,27,33,36,35,34,24,29,26,23,17,28,31,32 };
    for (int i = 0; i < 22; i++)
    {
        tree.Insert(arr[i]);
    }
    root = tree.Root();
    tree.Search(root, 35);
    tree.Level_order();
    cout << endl;
    tree.Remove(13);
    tree.Level_order();
    cout << endl;
    tree.Remove(27);
    tree.Level_order();
    cout << endl;
    tree.Remove(32);
    tree.Level_order();
    cout << endl;
    tree.Remove(40);
    tree.Level_order();
    cout << endl;
    tree.Remove(17);
    tree.Level_order();
    cout << endl;
    tree.Remove(34);
    tree.Level_order();
    cout << endl;
    tree.Remove(22);
    tree.Level_order();
    cout << endl;
    tree.Remove(23);
    tree.Level_order();
    cout << endl;
    tree.Remove(21);
    tree.Level_order();
    cout << endl;
    tree.Remove(24);
    tree.Level_order();
    cout << endl;
    tree.Remove(36);
    tree.Level_order();
    cout << endl;
    tree.Remove(39);
    tree.Level_order();
    cout << endl;
    tree.Remove(31);
    tree.Level_order();
    cout << endl;
    tree.Remove(33);
    tree.Level_order();
    cout << endl;
    tree.Remove(28);
    tree.Level_order();
    cout << endl;
    tree.Remove(97);
    tree.Level_order();
    cout << endl;
    tree.Remove(53);
    tree.Level_order();
    cout << endl;
    tree.Remove(41);
    tree.Level_order();
    cout << endl;
    tree.Remove(26);
    tree.Remove(29);
    tree.Remove(30);
    tree.Remove(35);
    tree.Level_order();
    cout << endl;
    //tree.Destory(tree.Root());
    tree.Level_order();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值