As part of an exercise my university has tasked me with, I have written a small Graph implementation, following this header.
class Node {
private:
std::string name;
std::vector<Node*> children;
public:
Node(const std::string& name="");
virtual ~Node();
}
When writing code for the destructor ~Node(), I noticed that my implementation fails when the graph contains a cycle. This is my implementation so far, which obviously doesn't work if the graph contains a cycle.
Node::~Node() {
for (Node* n : children) {
delete n;
n = NULL;
}
children.clear();
}
I am uncertain as to how I would most elegantly write a destructor that can handle cycles in the graph?
Please note that I was specifically tasked to write a recursive destructor.
Thank you for your answers!
Option 1: Choose a representation for the graph where nodes are not owned by other nodes, but rather the graph which would be a distinct object. This way the node destructor doesn't need to do anything. This won't satisfy the requirement of recursion:
struct Graph {
std::vector<std::unique_ptr<Node>> nodes;
};
Note that if there is no inheritance involved, then you could simply use std::vector<Node>. I assume that there is, due to the usage of virtual desturctor in Node.
Alternatively, you could use another representation for the graph such as adjacency list.
Option 2: Use an algorithm to generate a minimum spanning forest of the graph. Then recursively delete the roots of each spanning tree. You can for example use the Kruskal's algorithm. (Given your representation, it looks like your graph may be connected, in which case there would be only one spaning tree).
One option could be to first create an unordered_set of all the Node*s and then to delete them.
void fill(std::unordered_set<Node*>& to_delete, Node* ptr) {
// try to insert ptr and return if it was already in the set
if(not to_delete.emplace(ptr).second) return;
// swap ptr->children with an empty vector
std::vector<Node*> tmp;
std::swap(tmp, ptr->children);
for(Node* c : tmp) // loop over the pointers
fill(to_delete, c); // fill recursively
}
virtual ~Node() noexcept { // std::terminate if anything should throw
if(children.empty()) return; // nothing to do here
std::unordered_set<Node*> to_delete; // to collect all the Node*'s
fill(to_delete, this); // fill the set recursively
to_delete.erase(this); // don't delete "this"
for(auto c : to_delete) // delete all - they have no children by now
delete c;
}
Demo
If your graph is a tree (I assume it since your implementation of destructor is valid only for a tree) and you can store parent of the Node then you can write iterative version which do not require any extra data structure to avoid recursion.
Also learn to use smart pointers.
class Node {
private:
std::string name;
std::vector<std::unique_ptr<Node>> children;
Node* parent;
void safeCleanClildren();
public:
Node(std::string name="", Node* parent = nullptr)
: name{std::move(name)}
{}
~Node() {
iterativeCleanClildren();
}
void addChild(std::string name) {
children.emplace_back(std::make_unique<Node>(std::move(node), this);
}
};
void Node::iterativeCleanClildren()
{
auto p = this;
while (!p->children.empty()) {
while (!p->children.empty()) {
p = p->back().get(); // go as deep as possible
}
if (p != this) {
p = p->parent; // go back to parent
p->children.pop_back();
}
}
}
How this work?
first it finds leaf (right most) in a tree (node which do not have children)
Then goes back to parent node and remove child which was just found p->children.pop_back(); (this destroys unique_ptr of just found leaf).
Then finds again leaf and so on.
This tree clearing continues until root (this) node is reached
This way root node ends with no children at all and since it is iterative implementation overflown is impossible. It doesn't matter how much unbalance this tree is.
Related
I tried searching for this problem on stackoverflow but couldn't find it, so pardon me if it already existed.
So, what I wish to do is to create a function that traverses a tree and returns a pointer to the Node with the highest value. The Tree would be unordered and asymmetric, and will not have a fixed depth. Each node has a pointer to its Parent node, a list containing its Child nodes, and an integer named 'value'. And the tree would have a pointer to its root node, like this:
struct Node
{
private:
Node* parent;
list<Node> childs;
int value;
public:
// Getters, setters and constructors
}
struct Tree
{
private:
Node* root;
public:
// Getters, setters and constructors
}
And, as I stated before, I wish to make a function that traverses the entire tree, aka every single Node in the entire tree regardless of the depth, and returns a pointer to the node with the highest value. I assume it'll require recursion, but I can't figure out a way to do this.
Pardon me if my question seems dumb / stupid, but I really need help
You can use recursive method, which returns the pointer to the node with maximal value of current and child nodes:
struct Node
{
...
Node* getMaxNode()
{
Node* maxNode = this;
for (auto& child : this->childs) {
Node* childsMaxNode = child.getMaxNode();
if (childsMaxNode->getValue() > maxNode->getValue())
maxNode = childsMaxNode;
}
return maxNode;
}
}
If current node doesn't have child nodes, it will return pointer to the current node. So, in struct Tree you can implement something like this:
struct Tree
{
Node* getMax()
{
return this->root->getMaxNode();
}
}
There are two known ways (only two ?) to delete forward linked list
One way is the recursive function which is inefficient and would give stack overflow if the list is too large
Another way (the efficient) is a function that iterates and deletes nodes like this:
class Forward_list {
public:
// Constructor...
~Forward_list() { if(head) destroy(); }
void destroy() {
node* prev = nullptr;
while (head) {
prev = head;
head = head->next;
delete prev;
}
}
// functions...
private:
// data members...
node* head;
};
Now what about doing it this way:
class Forward_list {
public:
// Constructor...
~Forward_list() { if(head) delete this->head; }
// functions...
private:
struct node {
~node() { delete this->next; } // <- this way
type data;
node* next;
};
node* head;
// data members...
};
I tested it and it works fine ... I find this way cleaner but not sure if there would be side effects ?
Your solution is technically correct, the only problem I can think of is you can't delete one node without deleting all the nodes that follow.
Since it wasn't mentioned before: when using
delete this->next;
note that the destructor gets invoked recursively, i.e., the approach of deleteing the next node in the destructor is equivalent to the recursive approach of deleteing a list. The recursion is just not as direct and obvious.
~node() { delete this->next; } // <- this way
I find this way cleaner but not sure if there would be side effects ?
Well, the "side effect" will be, that you can't remove any nodes from the list, without deleting the whole rest of the list, since ~node() is called recursively there.
That's probably not what you want to do.
I have two classes: "node" and "poly". The node objects are linked together to form a linked list. The poly object holds a pointer to the first node. I am trying to deallocate the memory for the entire "poly". I want to delete the poly - then within the poly destructor call a function (something like "freePoly") that will help me iterate through the entire linked list of node objects - deleting all nodes.
Here is the class definition:
class Node
{
private:
double coeff;
int exponent;
Node *next;
public:
Node(double c, int e, Node *nodeobjectPtr)
{
coeff = c;
exponent = e;
next = nodeobjectPtr;
}
~Node()
{
printf("Node Destroyed");
//???
}
class poly
{
private:
Node *start;
public:
poly(Node *head) /*constructor function*/
{
start = head;
}
~poly() /*destructor*/
{
//???
}
void freePoly();
};
void poly::freePoly()
{
//???
}
I've tried a lot of things, but essentially I get stuck where I'm only deleting the first node object. Then I've lost the pointer to the other nodes... and leak memory because I can't access them anymore for deletion.
You can avoid a lot of problems and work by using a std::vector instead of a Do-It-Yourself linked list. Unless this is for learning.
That said, do
~poly() /*destructor*/
{
while( start != 0 )
{
node* p_doomed = start;
start = start->next;
delete p_doomed;
}
}
There are also many other ways to do this, but the above is a pattern that can help you figure out how to do similar things.
If you want to keep your code as is, then your freePoly should look like this:
while(start)
{
Node *ptr = start;
start = start->getNext();
delete ptr;
}
Notice what this code does: first it makes a copy of the pointer to the current head - i.e. the first Node, then it makes head point to the next object and only then calls delete for the old head pointer.
Of course, this design isn't ideal: you are programming using a C++ compiler and you have some classes and some member functions but you aren't really using C++ effectively:
Not only does language provides you with wonderful tools such as std::list or std::vector so that you don't have to reinvent the wheel and things like std::unique_ptr so that pointers know when it's safe to delete themselves.
It also provides you with powerful abstract concepts to model the bahavior of objects.
I suggest that you take a step back and rethink your code. Key questions to ask are: how can I write less code here? What facilities of C++ can I leverage here? What are these objects I have and what does each object do?
I understand that this may be a homework exercise and you have to implement things a certain way, but don't let that stop you from learning.
You could try this:
private:
void auxDestroy(Node* p);
void Node::auxDestroy(Node* p){
if (p!=0) {
if (p->next != 0) {
auxDestroy(p->next);
}
else {
delete p;
}
}
}
Then in the destroy method you could call this auxDestroy(this->next);
~Node(){
auxDestroy(this->next);
}
And in poly destructor:
~poly(){
delete this->start;
}
I have a BST which is a linked list in C++. How would I delete the whole thing from memory? Would it be done from a class function?
Just delete the children:
struct TreeNode {
TreeNode *l, *r, *parent;
Data d;
TreeNode( TreeNode *p ) { l = nullptr; r = nullptr; parent = p; }
TreeNode( TreeNode const & ) = delete;
~TreeNode() {
delete l; // delete does nothing if ptr is 0
delete r; // or recurses if there's an object
}
};
or if you're using unique_ptr or some such, that's not even needed:
struct TreeNode {
unique_ptr< TreeNode > l, r;
TreeNode *parent;
Data d;
TreeNode( TreeNode *p ) { l = nullptr; r = nullptr; parent = p; }
TreeNode( TreeNode const & ) = delete;
~TreeNode() = default;
};
If you have access to the linked list itself, it's a piece of cake:
// Making liberal assumptions about the kind of naming / coding conventions that might have been used...
ListNode *currentNode = rootNode;
while(currentNode != NULL)
{
ListNode *nextNode = currentNode->Next;
delete currentNode;
currentNode = nextNode;
}
rootNode = NULL;
If this is a custom implemention of a BST, then this may well be how it works internally, if it has tied itself to a particular data structure.
If you don't have access to the internals, then Potatoswatter's answer should be spot on. Assuming the BST is setup as they suggest, then simply deleting the root node should automatically delete all the allocated memory as each parent down the tree will delete its children.
If you are asking how to go about iterating across a binary tree manually, then you would do the following recursive step:
void DeleteChildren(BSTNode *node)
{
// Recurse left down the tree...
if(node->HasLeftChild()) DeleteChildren(node->GetLeftChild());
// Recurse right down the tree...
if(node->HasRightChild()) DeleteChildren(node->GetRightChild());
// Clean up the data at this node.
node->ClearData(); // assume deletes internal data
// Free memory used by the node itself.
delete node;
}
// Call this from external code.
DeleteChildren(rootNode);
I hope I've not missed the point here and that something of this helps.
Perform a post-order traversal of the tree (i.e. visiting children before parents), and delete each node as you visit it.
Whether or not this has anything to do with classes depends entirely on your implementation.
With the limited information provided ....
If you allocated the nodes with new or malloc (or related functions) than you need to traverse over all the nodes and free or delete them.
An alternative is to put shared_ptr's (and weak_ptr's to kill cyclics) in your allocations -- provided you do it correctly you won't have to free the nodes manually
If you used a quality implementation that you picked up on the internet than provided the classes don't leak, you don't have to worry about anything.
Use smart pointers and forget about it.
Which of these is a more correct way to store the first object in a linked list?
Or could someone please point out the advantages/disadvantages of each. Thanks.
class Node
{
int var;
Node *next;
static Node *first;
Node()
{
if (first == NULL)
{
first = this;
next = NULL;
}
else
//next code here
}
}
}
Node* Node::first = NULL;
new Node();
-- OR --
class Node
{
int var;
Node *next;
Node()
{
//next code here
}
}
Node* first = new Node();
The latter is definitely preferable. By making the first node pointer a static class member, you are basically saying that there will only be a single linked list in your whole program.
The second example lets you create several lists.
The first example has the definite drawback of only being able to create a single linked list in your entire program, so I wouldn't do that.
The second works fine, but doesn't shield the user of the class from how the linked list works. It would be better to add a second class, for example named LinkedList, that stores the 'first' pointer and performs list management.
Even better, you could use std::list instead.
It's most usual to have a separate List class and a separate Node class. Node is usually very simple. List holds a pointer to the first Node and implements the various list operations (add, remove, find and so on).
Something like the following
class List
{
public:
List()
{
first = new Node();
}
void insert(int val);
void remove(int val);
// ... and so on
~List()
{
// ... clean up
}
private:
struct Node
{
int val;
Node* next;
Node(int val_ = 0, Node* next_ = 0)
: val(val_), next(next_)
{}
};
Node* first;
};
Note that you can place Node outside List if you want to, but this usually doesn't make much sense.
Presumably you may have more than one list? In which case, the static option is a non-starter.
You definitely don't want the "first" to be a static. This implies there's only one linked list in your entire program. static means that every Node in every linked list in your entire program has the same beginning.
That being said you want your Node to have the fewest responsibilities-- It make sense for it to store its value and be able to get to the next Node. It adds complexity to add the job of1 maintaining the "first" pointer. For example what happens when you insert a new element at the beginning? Then you'd have to update everyone's "first" pointer. Given the two choices above I'd chose the second choice.
I would furthermore add a third choice. Add a "linked list" wrapper that gave you easy access to "first", "last" and allow you to easily insert into and iterate through the list. Something like:
class LinkedList
{
Node* First;
Node* Last;
public:
Node* GetFirst() {return First;}
Node* GetLast() {return Last;}
// insert after "where"
void Insert(Node* where, Node* newNode);
...
}
Not uselessly limiting your code to a single list instance is one very good argument for code variant 2.
However, just from superficially looking at the two examples, the sheer number of lines of code also gives a good indication that variant 2 has merits over variant 1 by being significantly shorter.