C++ 自平衡AVL树内存泄漏
所以我一直在研究这个自平衡AVL树,我觉得它工作正常,但是有一些内存泄漏。我已经搜索了一百万次,感觉就像是在试图找出我做错了什么,但我对这整个内存泄漏事件还不熟悉,显然需要了解更多。如果有人能帮我解决问题,或者能看到漏洞在哪里,那就太棒了,下面是我的AVL树的代码:C++ 自平衡AVL树内存泄漏,c++,memory-leaks,avl-tree,C++,Memory Leaks,Avl Tree,所以我一直在研究这个自平衡AVL树,我觉得它工作正常,但是有一些内存泄漏。我已经搜索了一百万次,感觉就像是在试图找出我做错了什么,但我对这整个内存泄漏事件还不熟悉,显然需要了解更多。如果有人能帮我解决问题,或者能看到漏洞在哪里,那就太棒了,下面是我的AVL树的代码: #pragma once #include <algorithm> #include <fstream> #include "LinkedList.h" template <typename Item
#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;
}
};
#pragma一次
#包括
#包括
#包括“LinkedList.h”
样板
类AVLTreeSet{
私人:
结构节点{
项目类型信息;
节点*左;
节点*右;
内部高度;
};
节点*根;
整数大小;
公众:
AVLTreeSet()
{
root=NULL;
尺寸=0;
}
~AVLTreeSet()
{
清除();
}
无效清除()
{
节点*n=根;
如果(n!=NULL)
{
clearTree(n->左);
clearTree(n->右侧);
删除n;
}
root=NULL;
}
void clearTree(节点*n)
{
如果(n!=NULL)
{
clearTree(n->左);
clearTree(n->右侧);
删除n;
}
}
无效打印(标准::流和输出)
{
//cout left=添加(项目,当前->左侧);
}
如果(当前->信息<项目)
{
当前->右侧=添加(项目,当前->右侧);
}
回流;
}
作废删除(const ItemType&item)
{
节点*当前=根;
如果(当前==NULL)
{
//cout info<项目)
{
//不正确);
如果(当前==根)
{
根=平衡(当前);
}
回来
}
}
节点*removeNext(常量项类型&项,节点*current)
{
节点*温度;
如果(当前!=NULL)
{
如果(当前->信息>项目)
{
//不能离开);
回流;
}
如果(当前->信息<项目)
{
//不正确);
回流;
}
//不正确!=空)
{
//cout left=temp->left;
//cout info,temp->right);
删除临时文件;
大小--;
电流=平衡(电流);
回流;
}
else if(当前->右侧!=NULL)
{
//不能左!=空)
{
//cout info- right!=NULL)
{
find=findRight(项目,当前->右侧);
}
返回查找;
}
bool findLeft(常量项类型&项,节点*当前)
{
bool find=false;
如果(项目==当前->信息)
{
发现=真;
返回查找;
}
如果(当前->信息>项目和当前->左侧!=NULL)
{
find=findLeft(项目,当前->左侧);
}
如果(当前->信息
- right!=NULL)
{
find=findRight(项目,当前->右侧);
}
返回查找;
}
布尔findRight(常量项类型和项,节点*当前)
{
bool find=false;
如果(项目==当前->信息)
{
发现=真;
返回查找;
}
如果(当前->信息>项目和当前->左侧!=NULL)
{
find=findLeft(项目,当前->左侧);
}
如果(当前->信息
- right!=NULL)
{
find=findRight(项目,当前->右侧);
}
返回查找;
}
int getHeight(节点*temp)
{
int h=0;
如果(温度!=NULL)
{
int l_height=getHeight(临时->左);
int r_height=getHeight(温度->右侧);
int max_height=std::max(l_height,r_height);
h=最大高度+1;
}
返回h;
}
无效设置高度(节点*n)
{
n->height=std::max(getHeight(n->right),getHeight(n->left))+1;
}
节点*余额(节点*n)
{
如果(大小==1)
{
返回n;
}
否则如果(getHeight(n->left)-getHeight(n->right)>1)//n不平衡
{
//不能左)大于1)
{
//cout right)>getHeight(n->left->left))
{
n->left=rotateLeft(n->left);//left)>getHeight(n->right->right))
{
n->右=旋转右(n->右);//左=临时->右;
温度->右=n;
setHeight(n);//右;
n->右=温度->左;
温度->左=n;
setHeight(n);//您如何知道存在内存泄漏
除非您使用某种工具查找内存泄漏,例如@jsantander建议的valgrind,否则请尝试以下操作:
避免代码重复。当前表单中有太多的重复。例如,clear()
可以通过调用cleartree(root)
来简化。类似于insert()
打印/记录每个内存分配(new
)和释放(delete
)的内存
始终增加计数器,newCount
和deleteCount
。在有效方法的末尾,添加一个断言,assert(newCount-deleteCount==size);
。在第一次出现内存泄漏时,assert()
将爆炸。请参阅第7页“其他经验”
你试过运行它吗?你有漏洞,因为你正在手动调用new
和delete
。停止。你是一个简单的定向树。用std::unique\u ptr
替换子节点*
,在需要时实现移动
,那么我敢说你有漏洞。你可能必须编写模板td::unique\u ptr make_unique(Args&&…Args)
从客户机代码中删除新的
,但这可能是过分的:在您的情况下,您不需要