繁体   English   中英

在C中打印B +树

[英]Printing B+ tree in C

我已经在C实现了B+树,并希望以树形式打印其键。 我遵循以下算法进行打印,但遇到了一些分割错误。

  1. 从根开始,首先对其进行排队。 然后出队直到队列变为零。

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

以下是对叶子进行排队,出队和打印的代码。 请让我知道此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第一个连续节点,然后出现分段错误。 您能帮我弄清楚这段代码有什么问题吗?

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

bplusTemp->bplusNode = bplusNode;

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

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

这只是简单的坚果:)

级别顺序遍历是通过两个队列完成的,一个队列用于访问当前级别的元素,另一个队列用于为下一个级别建立队列。 我已经为二进制搜索树成功实现了这一点。 您可以对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

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

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

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

这对于为什么您能够打印前两个节点值(根及其子节点之一)并获得段错误也很有意义。 基本上,当队列为空时,您永远不会调用这些行,而是要添加第一个节点。 因此,当您添加root ,您就可以了……您不会对其free打电话。 然后,将其出队,然后再将其清空。 因此,将root的下一个孩子添加到队列中,这也很好,因为因为队列为空,所以您不必在bplusNew上调用free 但是现在,当您添加根的任何其他子级并且队列不为空时,您最终在bplusNew上调用free ,导致队列仅包含单个值。 换句话说, queue->next指向的第一个节点(即链表中的第二个节点)实际上不再可用了……您在该内存上称为free

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

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

您要重新分配链表的最前面,而不会释放作为链表原头的节点。 现在,您不再有指向该节点的指针,并且它被视为内存泄漏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM