2014-04-03 59 views
0

所以我一直在研究這種自平衡AVL樹,我覺得它的工作正常,但有一些內存泄漏。我搜索並經歷了一百萬次,這感覺就像試圖弄清楚我做錯了什麼,但是我對這個內存泄漏事情很陌生,顯然需要了解更多。如果有人能幫助我或者能看到該泄漏可能是將是真棒,這裏是我的AVL樹代碼:自平衡AVL樹內存泄漏

#pragma once 
#include <algorithm> 
#include <fstream> 
#include "LinkedList.h" 

template <typename ItemType> 

class AVLTreeSet { 

private: 

    struct Node { 
    ItemType info; 
    Node* left; 
    Node* right; 
    int height; 
    }; 

    Node* root; 
    int size; 

public: 
    AVLTreeSet() 
    { 
     root = NULL; 
     size = 0; 
    } 

    ~AVLTreeSet() 
    { 
     clear(); 
    } 
    void clear() 
    { 
     Node* n = root; 
     if(n != NULL) 
     { 
      clearTree(n->left); 
      clearTree(n->right); 
      delete n; 
     } 
     root = NULL; 
    } 
    void clearTree(Node* n) 
    { 
     if(n != NULL) 
     { 
      clearTree(n->left); 
      clearTree(n->right); 
      delete n;   
     } 

    } 

    void print(std::ofstream &out) 
    { 
     //cout << "HERE" << endl; 
     LinkedList<Node*> list; 
     int level = 0; 
     int levelSize; 
     int count = 0; 
     Node* n = root; 
     if (n == NULL) 
     { 
      return; 
     } 
     list.insert(n); 
     levelSize = list.getSize(); 
     while(list.getSize() != 0) 
     { 
      count = 0; 
      out << "level " << level << ": "; 
      for (unsigned i = levelSize; i > 0; i--) 
      { 
       count++; 
       if (count > 8) 
       { 
        out << std::endl; 
        out << "level " << level << ": "; 
        count = 0; 
       } 
       n = list.getInfo(); 
       out <<n->info << "(" << getHeight(n) << ") "; 
       if (n->left != NULL) 
       { 
        //cout << "left is not null" << endl; 
        list.insert(n->left); 
       } 
       if (n->right != NULL) 
       { 
        list.insert(n->right); 
        //cout << "right is not null" << endl;   
       } 
       list.remove(); 

      } 

      levelSize = list.getSize(); 
      level++; 
      out << std::endl; 
      //levelSize = list.getSize(); 
     } 
    } 
    void insert(const ItemType& item) 
    { 
     //cout << "Insert FUNCTION" << endl; 
     Node* current = root; 

     if (current == NULL) 
     { 
      //cout << "ADD FUNCTION NULL" << endl; 
      current = new Node; 
      current->info = item; 
      current->left = NULL; 
      current->right = NULL; 
      current->height = 0; 
      root = current; 
      size++; 
      //cout << current->info << endl; 
      //cout << current->height << endl; 
      return; 
     } 
     if (current->info > item) 
     { 
      current->left = add(item, current->left); 
     } 
     if (current->info < item) 
     { 
      current->right = add(item, current->right); 
     } 
     current = balance(current); 
     root = current; 

    } 
    Node* add(const ItemType& item, Node* current) 
    { 
     if (current == NULL) 
     { 
      current = new Node; 
      current->info = item; 
      current->left = NULL; 
      current->right = NULL; 
      current->height = 0; 
      size++; 
     } 

     if (current->info > item) 
     { 
      current->left = add(item, current->left); 
     } 
     if (current->info < item) 
     { 
      current->right = add(item, current->right); 
     } 
     return current; 
    } 
    void remove(const ItemType& item) 
    { 
     Node* current = root; 
     if (current == NULL) 
     { 
      //cout << "NULL" << endl; 
      return; 
     } 
     if (current->info == item) 
     { 
      //cout << "FOUND" << endl; 
      current = removeNext(item, current); 
      current = balance(current); 
      root = current; 
      return; 
     } 
     if (current->info > item) 
     { 
      //cout << "LEFT" << endl; 
      current->left = removeNext(item, current->left); 
      if (current == root) 
      { 
       root = balance(current); 
      } 
      return; 
     } 
     if (current->info < item) 
     { 
      //cout << "RIGHT" << endl; 
      current->right = removeNext(item, current->right); 
      if (current == root) 
      { 
       root = balance(current); 
      } 
      return; 
     } 
    } 
    Node* removeNext(const ItemType& item, Node* current) 
    { 
     Node* temp; 
     if (current != NULL) 
     { 
     if (current->info > item) 
     { 
      //cout << "REMOVENEXT LEFT" << endl; 
      current->left = removeNext(item, current->left); 
      return current; 
     } 
     if (current->info < item) 
     { 
      //cout << "REMOVENEXT RIGHT" << endl; 
      current->right = removeNext(item, current->right); 
      return current; 
     } 
      //cout << "FOUND" << endl; 
      if (current->left != NULL && current->right != NULL) 
      { 
       //cout << "LEFT AND RIGHT CHILDREN" << endl; 
       temp = current; 
       current = CTR(current->right); 
       current->left = temp->left; 
       //cout << current->info << endl; 
       //looker = removeNext(current->info, temp->right); 
       delete temp; 
       size--; 
       current = balance(current); 
       return current; 
      } 
      else if (current->right != NULL) 
      { 
       //cout << "RIGHT ONE CHILD" << endl; 
       temp = current; 
       current = current->right; 
       delete temp; 
       size--; 
       current = balance(current); 
       return current; 
      } 
      else if (current->left != NULL) 
      { 
       //cout << "LEFT ONE CHILD" << endl; 
       temp = current; 
       current = current->left; 
       delete temp; 
       size--; 
       current = balance(current); 
       return current; 
      } 
      //cout << "CURRENT NODE" << endl; 
      delete current; 
      size--; 
      return NULL; 
     } 
     //cout << "NOT FOUND" << endl; 
     return current; 
    } 
    Node* CTR(Node* current) 
    { 
     while(current->left != NULL) 
     { 
      //cout << "ENTERED LOOP" << endl; 
      current = current->left; 
     } 
     //cout << current->info << endl; 
     return current; 

    } 
    bool find(const ItemType& item) 
    { 
     Node* current = root; 
     bool find = false; 
     if (current == NULL) 
     { 
      return find; 
     } 
     if (item == current->info) 
     { 
      find = true; 
      return find; 
     } 
     if (current->info > item && current->left != NULL) 
     { 
      find = findLeft(item, current->left); 
     } 
     if (current->info < item && current->right != NULL) 
     { 
      find = findRight(item, current->right); 
     } 
     return find; 
    } 
    bool findLeft(const ItemType& item, Node* current) 
    { 
     bool find = false; 
     if (item == current->info) 
     { 
      find = true; 
      return find; 
     } 
     if (current->info > item && current->left != NULL) 
     { 
      find = findLeft(item, current->left); 
     } 
     if (current->info < item && current->right != NULL) 
     { 
      find = findRight(item, current->right); 
     } 
     return find; 
    } 
    bool findRight(const ItemType& item, Node* current) 
    { 
     bool find = false; 
     if (item == current->info) 
     { 
      find = true; 
      return find; 
     } 
     if (current->info > item && current->left != NULL) 
     { 
      find = findLeft(item, current->left); 
     } 
     if (current->info < item && current->right != NULL) 
     { 
      find = findRight(item, current->right); 
     } 
     return find; 
    } 
    int getHeight(Node* temp) 
    { 
     int h = 0; 
     if (temp != NULL) 
     { 
      int l_height = getHeight(temp->left); 
      int r_height = getHeight(temp->right); 
      int max_height = std::max(l_height, r_height); 
      h = max_height + 1; 
     } 
     return h; 
    } 
    void setHeight(Node* n) 
    { 
     n->height = std::max(getHeight(n->right), getHeight(n->left)) + 1; 
    } 

    Node* balance(Node* n) 
    { 
     if (size == 1) 
     { 
      return n; 
     } 
     else if(getHeight(n->left) - getHeight(n->right) > 1) //n is out of balance 
     { 
      //cout << "BALANCE RIGHT" << endl; 
      n = balanceToRight(n); 
     } 
     else if(getHeight(n->right) - getHeight(n->left) > 1) 
     { 
      //cout << "BALANCE LEFT" << endl; 
      n = balanceToLeft(n); 
     } 
      return n; 
    } 
    Node* balanceToRight(Node* n) 
    { 
     if(getHeight(n->left->right) > getHeight(n->left->left)) 
      { 
       n->left = rotateLeft(n->left); //<--- extra step for double rotate 
      } 
      n = rotateRight(n); //<--- this is for single 
     return n; 
    } 
    Node* balanceToLeft(Node* n) 
    { 
     if(getHeight(n->right->left) > getHeight(n->right->right)) 
      { 
       n->right = rotateRight(n->right); //<--- extra step for double rotate 
      } 
      n = rotateLeft(n); //<--- this is for single 
     return n; 
    } 
    Node* rotateRight(Node* n) 
    { 
     Node* temp = n->left; 
     n->left = temp->right; 
     temp->right = n; 
     setHeight(n); //<--- set first 
     setHeight(temp); 
     return temp; 
    } 
    Node* rotateLeft(Node* n) 
    { 
     Node* temp = n->right; 
     n->right = temp->left; 
     temp->left = n; 
     setHeight(n); //<--- set first 
     setHeight(temp); 
     return temp; 
    } 

}; 

我在與我的main.cpp文件讀取運行程序調用我的AVLtree的命令。我知道它有很多代碼,但我強調,因爲我無法找到它可能發生的地方。謝謝。

+1

您是否嘗試過通過運行它[的valgrind-MEMCHECK(http://valgrind.org/info/tools.html#memcheck)? – jsantander

+1

因爲您正在手動調用'new'和'delete',所以您有泄漏。不要那麼做。你是一棵簡單的定向樹。將'Node *'替換爲'std :: unique_ptr ',在需要時執行'move',然後我敢於泄漏。你可能需要編寫'templare std :: unique_ptr make_unique(Args && ... args)'從客戶端代碼中刪除'new',但這可能會過度:在你的的情況下,你不需要處理任意ctors。 – Yakk

+0

是否存在導致您檢測泄漏的特定命令序列? – jsantander

回答

0

你怎麼知道有內存泄漏?

除非你使用一些工具來查找內存泄漏,例如通過Valgrind的作爲@jsantander建議,然後嘗試以下方法:

  1. 避免代碼重複。目前的形式有太多的重複。例如clear()可以簡化,只需撥打cleartree(root)。類似於insert()

  2. 打印/日誌內存中的每個內存分配(new)和釋放(delete

  3. 始終保持增加計數器,newCountdeleteCount。在重要方法結束時,添加一個斷言assert(newCount - deleteCount == size);。在第一次發生內存泄漏時,assert()會受到打擊。見http://accu.org/var/uploads/journals/overload102.pdf,第7頁, 「其他方面的經驗」