簡體   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