实现算法导论第三版中的BTree

只实现了插入、查找算法,未实现删除算法。

#include <stdlib.h>
#include <stdio.h>
#include <memory.h>

#define BTreeKey char
#define T 2 //minmum degree
#define TRUE 1
#define FALSE 0

struct BTree
{
struct BTreeNode * root;
};

struct BTreeNode
{
int n; //节点内关键字个数
char bLeaf;
BTreeKey keys[2*T-1];
struct BTreeNode * subTree[2*T];//至多有2T个孩子
};

struct BTreeResult
{
char ok; //是否成功
struct BTreeNode * node;
int index;
};


void BTreeCreate(struct BTree * tree)
{
    struct BTreeNode * root = (struct BTreeNode * )malloc(sizeof(struct BTreeNode));
    memset(root, 0, sizeof(struct BTreeNode));

    root->bLeaf = TRUE;
    root->n = 0;
    //DISKWRITE(root)
    tree->root = root;
}

struct BTreeNode * BTreeRead(struct BTreeNode * node, int subTreeIndex)
{
    return node->subTree[subTreeIndex];
}

struct BTreeResult BTreeSearch(struct BTreeNode * node, BTreeKey k)
{
    int i = 0;
    while(i<node->n && k>node->keys[i])
        i++;

    if(i<node->n && k == node->keys[i])
    {
        struct BTreeResult res={1, node, i}; //TODO:optimize
        return res;
    }
    else if(node->bLeaf)
    {
        struct BTreeResult res={0, 0, 0};
        return res;
    }
    else
    {
        struct BTreeNode * childNode = 0;
        childNode = BTreeRead(node, i);
        return BTreeSearch(childNode, k);
    }

    struct BTreeResult res={0, 0, 0};
    return res;
}

//subTreeIndex 满节点的索引位置
void BTreeSplitChild(BTreeNode * paNode, int subTreeIndex)
{
    struct BTreeNode * newNode = (struct BTreeNode * )malloc(sizeof(struct BTreeNode));
    memset(newNode, 0, sizeof(struct BTreeNode));

    struct BTreeNode * fullNode = paNode->subTree[subTreeIndex];

    newNode->bLeaf = fullNode->bLeaf;
    newNode->n = T - 1;

    //将fullNode中后半部分的关键字赋给newNOde
    for(int j=0;j<(T-1);++j)
    {
        newNode->keys[j] = fullNode->keys[j+T];
    }

    //将fullNode中后半部分的子节点赋给newNOde
    if(!fullNode->bLeaf)
    {
        for(int j=0; j<T;++j) //2T个子节点
        {
            newNode->subTree[j] = fullNode->subTree[j+T];
        }
    }

    fullNode->n = T - 1;

    //父节点subTreeIndex之后的节点 向后移动
    for(int j=paNode->n; j>subTreeIndex; j++)
    {
        paNode->subTree[j+1] = paNode->subTree[j];
    }
    paNode->subTree[subTreeIndex+1] = newNode; //将新生成的子节点填入父节点中

    for(int j=paNode->n-1; j<subTreeIndex-1; --j)
    {
        paNode->keys[j+1] = paNode->keys[j];
    }
    paNode->keys[subTreeIndex] = fullNode->keys[T-1];

    paNode->n++;
    //DISKWRITE(fullNode)
    //DISKWRITE(newNode)
    //DISKWRITE(paNode)
}

void BTreeInsertNonFull(struct BTreeNode * node, BTreeKey k)
{
    int i = node->n-1;

    if(node->bLeaf)
    {
        //为k找到要插入的点
        while(i>=0 && k<node->keys[i]) //从后向前找要插入的位置,同时向后移动键值.
        {
            node->keys[i+1] = node->keys[i];
            i--;
        }

        node->keys[i+1] = k;
        node->n++;
        //DISKWRITE(node)
    }
    else
    {
        //确定子节点
        while(i>=0 && k<node->keys[i])
            i--;

        i++;
        //DiskRead(node->subTree[i])

        if(node->subTree[i]->n == 2*T-1) //满了
        {
            BTreeSplitChild(node, i);
            if(k > node->keys[i])
                i++;
        }

        BTreeInsertNonFull(node->subTree[i], k);
    }
}

void BTreeInsert(struct BTree * tree, BTreeKey k)
{
    struct BTreeNode * r = tree->root;

    if(r->n == (2*T-1))
    {
        struct BTreeNode * s = (struct BTreeNode * )malloc(sizeof(struct BTreeNode));
        memset(s, 0, sizeof(struct BTreeNode));

        tree->root = s;
        s->bLeaf = FALSE;
        s->n = 0;
        s->subTree[0] = r;
        BTreeSplitChild(s, 0);
        BTreeInsertNonFull(s, k);
    }
    else
    {
        BTreeInsertNonFull(r, k);
    }
}

void PrintTree(int kind, BTreeNode * pRoot); //打印树的关键字

int main()
{
    struct BTree tree;
    BTreeCreate(&tree);
    BTreeInsert(&tree, 'A');
    BTreeInsert(&tree, 'C');
    BTreeInsert(&tree, 'G');

    BTreeInsert(&tree, 'N');
    BTreeInsert(&tree, 'H');

    BTreeInsert(&tree, 'E');
    BTreeInsert(&tree, 'K');
    BTreeInsert(&tree, 'Q');
    BTreeInsert(&tree, 'M');
    BTreeInsert(&tree, 'F');
    BTreeInsert(&tree, 'W');
    BTreeInsert(&tree, 'L');
    BTreeInsert(&tree, 'T');
    BTreeInsert(&tree, 'Z');
    BTreeInsert(&tree, 'D');

    PrintTree(2, tree.root);

    struct BTreeResult  res = BTreeSearch(tree.root, 'M');
    return 0;
}
///
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
/*
 * 1 means integer
 * 2 means character
 */
//PrintTree from https://github.com/gzc/CLRS/blob/master/C18-B-Trees/btree.cpp
void PrintTree(int kind, BTreeNode * pRoot) //打印树的关键字
{
    queue<BTreeNode*> myqueue;
    myqueue.push(pRoot);
    int depth = 0;

    cout << "c btree "  << endl;

    while(!myqueue.empty())
    {
        queue<BTreeNode*> nextlevel;
        cout << "depth : " << depth << endl;

        while(!myqueue.empty())
        {
            BTreeNode* temp = myqueue.front();
            myqueue.pop();

            cout << "[";
            for(int i = 0;i <temp->n;i++)
            {
                if(kind == 2)cout << (char)temp->keys[i] << " ";
                else cout << temp->keys[i] << " ";
            }
            cout << "]";

            if(!temp->bLeaf)
                for(int i = 0;i <temp->n+1;i++)
                    nextlevel.push(temp->subTree[i]);
        }
        cout << endl;
        depth++;
        myqueue = nextlevel;
    }
}


输出结果

c btree 
depth : 0
[H ]
depth : 1
[C F ][N T ]
depth : 2
[A ][D E ][G ][K L M ][Q ][W Z ]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值