【发布时间】:2021-03-31 16:37:36
【问题描述】:
嗨,目前我一直在磨练我在数据结构方面的技能,以便我可以成为一名优秀的游戏开发人员,我正在学习链表并制作了一个链表程序,其中包含插入、删除和递归插入以及反转链表你能伙计们告诉我我在这里清除分配的内存使用新的运算符正确创建,我得到了所需的输出,但我担心内存泄漏。 ...请温柔瞄准 还在学习中。
class Node
{
int data;
Node *Next;
public:
int GetData()
{
return data;
}
void SetData(int Data)
{
data = Data;
}
Node *GetNext()
{
return Next;
}
void SetNext(Node *next)
{
Next = next;
}
};
void Insert(Node **Head, int x)
{
Node *temp = new Node();
temp->SetData(x);
temp->SetNext(*Head);
*Head = temp;
}
void InsertAt(Node **Head, int x, int n)
{
if (n == 0)
{
std::cout << "The Given data at 'n' cannot be assigned to null\n";
}
Node *temp = new Node();
temp->SetData(x);
if (n == 1)
{
temp->SetNext(nullptr);
*Head = temp;
return;
}
Node *temp2 = *Head;
if (Head == nullptr)
{
std::cout << "The Given data cannot be assigned to null\n";
}
for (int i = 0; i < n - 2; i++)
{
temp2 = temp2->GetNext();
}
temp->SetNext(temp2->GetNext());
temp2->SetNext(temp);
}
void AppendList(Node **Head, int Data)
{
Node *temp = new Node();
Node *LastNode = *Head;
temp->SetData(Data);
temp->SetNext(nullptr);
if (*Head == nullptr)
{
*Head = temp;
return;
}
// else Traverse till last node.
while (LastNode->GetNext() != nullptr)
{
LastNode = LastNode->GetNext();
}
LastNode->SetNext(temp);
}
void DeleteNode(Node **Head, int n)
{
Node *temp = *Head;
if (n == 1)
{
*Head = temp->GetNext();
std::cout << "\nAfter Deletion of Head Node\n";
return;
}
for (int i = 0; i < n - 2; i++)
{
temp = temp->GetNext();
}
Node *temp2 = temp->GetNext();
temp->SetNext(temp2->GetNext());
std::cout << "After Deletion of Node\n";
}
Node *ReverseList(Node *Head)
{
Node *Current, *Prev, *next;
Current = Head;
Prev = nullptr;
while (Current != nullptr)
{
next = Current->GetNext();
Current->SetNext(Prev);
Prev = Current;
Current = next;
}
Head = Prev;
return Head;
}
int LinkedList_Count(Node *Head)
{
int count = 0;
Node *Current = Head;
while (Current != nullptr)
{
count++;
Current = Current->GetNext();
}
std::cout << "Number of Elements: " << count;
return count;
}
void PrintList(Node *Head)
{
std::cout << "Data list : ";
while (Head != nullptr)
{
std::cout << " " << Head->GetData();
Head = Head->GetNext();
}
std::cout << "\n";
}
//Print Listed using Recursion
void Recursion_Print(Node *Head)
{
if (Head == nullptr)
{
return;
}
std::cout << ' ' << Head->GetData(); //comment to Do Reverse the Linked list
Recursion_Print(Head->GetNext());
//std::cout << ' ' << Head->GetData();//unComment to Reverse the linked List recursively
}
Node *RecursiveRevList(Node *Head)
{
Node *temp;
if (Head->GetNext() == nullptr)
{
temp = Head;
return temp;
}
temp = RecursiveRevList(Head->GetNext());
Head->GetNext()->SetNext(Head);
Head->SetNext(nullptr);
return temp;
}
void RunList()
{
Node *Head = NULL;
//AppendList(&Head, 16);
Insert(&Head, 6);
Insert(&Head, 7);
Insert(&Head, 8);
InsertAt(&Head, 18, 2);
std::cout << "Data list : \n";
Recursion_Print(Head);
std::cout << '\n';
LinkedList_Count(Head);
DeleteNode(&Head, 1);
//Head = ReverseList(Head);
Head = RecursiveRevList(Head);
PrintList(Head);
LinkedList_Count(Head);
delete Head;
}
【问题讨论】:
-
您肯定有泄漏,因为您从不释放内存,也没有使用会自动释放内存的智能指针。特别是您的
DeleteNode从列表中分离一个节点但从不删除它。 -
检查是否没有内存泄漏的最佳方法是编写大量测试并在 valgrind 等泄漏检测工具下运行它们。仅通过查看代码很难检测到内存泄漏,尤其是如果它不符合 RAII 原则。
-
另见this C++ reference,了解standard containers 和C++ rule of five。使用至少使用
g++ -Wall -Wextra -g调用的GCC 进行编译。从现有的开源 C++ 项目中汲取灵感(例如fish、RefPerSys、ninja...) -
无关,更多的是个人反思,但你用来学习 C++ 的资源或老师可能在教授 C++ 方面做得不好。您清楚地知道类,那么为什么不将类用于列表本身呢?使所有全局函数成为例如的成员函数
List类? -
链表是我会使用
new的少数几个地方之一,特别是如果我知道链表会长到足以威胁堆栈溢出。在这种情况下,已经存在递归迭代,所以不妨使用unique_ptr。总的来说,这里有一个关于 C++ 智能指针的精彩演示:Leak-Freedom in C++... By Default. 如果我没有混淆演示,我相信这是 Sutter 先生使用链表作为示例的那个。
标签: c++