在C中打印B +树

时间:2011-07-31 14:41:09

标签: c b-tree

我在B+中实现了C树,并希望以树形式打印其键。我按照以下算法进行打印但得到了一些分段错误。

  1. 从root开始,首先排队。然后出队,直到队列变为零。

  2. 由于每个节点都包含密钥及其值(指向下一级节点的指针),因此每个值在到达特定节点时也会排队。

  3. 以下是排队,出列和打印叶子的代码。请告诉我这个partcularcode有什么问题。

               typedef struct QUEUE{
                BPLUS bplusNode;
                struct QUEUE * next;
                        }*ENQUEUE;
    

    以下代码是对树的节点进行排队。(我将实现广度优先搜索)

          void bplus_Enqueue(BPLUS bplusNew){
              ENQUEUE bplusTemp;
              if (queue == NULL){
              queue = (ENQUEUE)malloc(sizeof(ENQUEUE));
              queue->bplusNode= bplusNew;
              queue->next = NULL;
                  }
                   else {
                   bplusTemp = (ENQUEUE)malloc(sizeof(ENQUEUE));
                   bplusTemp->bplusNode = bplusNew;
                   bplusTemp->next = NULL;
            while(queue->next != NULL) {
                    queue = queue->next;
                          }
                    queue->next = bplusTemp;
                    free(bplusTemp);
                       }
                 }
    

    以下代码用于出列

              BPLUS bplus_Dequeue( void ){
              BPLUS bplusTemp = queue->bplusNode;
              queue = queue->next;
              return bplusTemp;
               }
    

    以下代码用于打印树。

       void  bplus_PrintBplus(BPLUS root){
       int i;
       BPLUS tempBplus;
       queue = NULL;
       bplus_Enqueue(root);
       if(queue == NULL){
         printf("Sala kaam garena\n");
        }
       while(queue != NULL){
       tempBplus = bplus_Dequeue();
              for(i=0;i<tempBplus->numKeys;i++){
              printf("%d -----> %d\n",i,tempBplus->keys[i]);
                 }
              if(tempBplus->next != NULL){
                 for(i=0;i<=tempBplus->numKeys;i++)
               bplus_Enqueue(tempBplus->pointers[i]);
                }
            }
        }
    

    此代码打印root的键值和root的第一个连续节点,然后获取分段错误。你能帮我弄清楚这段代码有什么问题吗?

3 个答案:

答案 0 :(得分:1)

我没有检查完整的代码,但这些部分真的很奇怪:

bplusTemp->bplusNode = bplusNode;

这里有什么是bplusNode?还没有看到它的声明。

queue->next = bplusTemp;
free(bplusTemp);

这只是简单的坚果:)

答案 1 :(得分:1)

级别顺序遍历是通过两个队列完成的,一个用于访问当前级别的元素,另一个用于构建下一级别的队列。我已成功为二进制搜索树实现了这个功能。您可以对B +树使用相同的逻辑。

void BinarySearchTree::printLevelBased()
{
    Queue<Node *> *nodeQueue1 = new Queue<Node *>();
    Queue<Node *> *nodeQueue2 = new Queue<Node *>();;
    Node *currentNode;
    int numOfLevels = 0;

    nodeQueue1->put(mRoot);

    while(false == nodeQueue1->isEmpty())
    {
        numOfLevels++;
        Queue<Node *> *temp = nodeQueue1;
        nodeQueue1 = nodeQueue2;
        nodeQueue2 = temp;

        while(false == nodeQueue2->isEmpty())
        {
            currentNode = nodeQueue2->get(); // Dequeue
            PRINT_NODE_DATA(currentNode);
            if(currentNode->hasLeft())
            {
                nodeQueue1->put(currentNode->mLeft); // Enqueue
            }
            if(currentNode->hasRight())
            {
                nodeQueue1->put(currentNode->mRight);
            }
        }
        cout << endl;
    }

    return;
}

词shash

答案 2 :(得分:1)

这段代码在bplus_Enqueue函数中看起来很奇怪:

queue->next = bplusTemp;
free(bplusTemp);

基本上,您在设置队列中使用的链接列表中的下一个节点,但在将next指针指向链接列表的上一端后将其释放。这意味着您的倒数第二个节点指向释放的内存而不是有效的链表节点,这会在访问时导致分段错误。 bplusTemp节点指向的内存,在第一行之后,现在由列表“拥有”...您不能在该指针上调用free,否则每个其他指针指向该内存(在这种情况下为queue->next)也指向释放的内存,并在尝试访问该内存时会发生段错误。

这也可以解释为什么你能够打印前两个节点值(root和它的一个子节点),然后得到段错误。基本上,当队列为空时,您永远不会调用这些行,并且您正在添加第一个节点。因此,当您添加root时,您没问题...您不会在其上调用free。然后你将它出列,当你这样做时,队列再次为空。因此,root的下一个孩子会被添加到队列中,这也很好,因为因为队列是空的,所以不要在free上调用bplusNew。但是现在当你添加root的任何其他子节点并且队列不为空时,你最终会在free上调用bplusNew,导致你排队只包含一个值。换句话说,queue->next指向的第一个节点(即链接列表中的第二个节点)实际上不再可访问...您已在该内存上调用free

其次,在你的bplus_Dequeue函数中,你有内存泄漏......特别是在这里:

BPLUS bplusTemp = queue->bplusNode;
queue = queue->next;

您正在重新分配链接列表的前端而不释放作为列表原始头部的节点。现在你不再有一个指向该节点的指针,它被认为是泄漏的内存。