自平衡AVL树内存泄漏

时间:2014-04-03 16:38:23

标签: c++ memory-leaks avl-tree

所以我一直在研究这种自平衡的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;
    }

};

我通过读取一个调用我的AVLtree命令的main.cpp文件来运行程序。我知道很多代码,但我强调,因为我无法找到可能发生的地方。感谢。

1 个答案:

答案 0 :(得分:0)

你怎么知道有内存泄漏?

除非您使用某种工具来查找内存泄漏,例如@jsantander建议的valgrind,否则请尝试以下操作:

  1. 避免代码重复。目前的形式存在太多重复。例如,只需调用clear()即可简化cleartree(root)。类似于insert()

  2. 打印/记录每个内存分配(new)和解除分配(delete

  3. 始终保持增加计数器newCountdeleteCount。在重要方法结束时,添加一个断言assert( newCount - deleteCount == size );。在第一次发生内存泄漏时,assert()会爆炸。请参阅http://accu.org/var/uploads/journals/overload102.pdf,第7页,&#34;其他体验&#34;