class List {
ListNode *head;
ListNode *prev;
};
class ListNode {
int data;
ListNode *next;
friend class List;
ListNode(int d, ListNode *n) : data(d), next(NULL) {}
void insertM(int d) {
ListNode *ptr, *temp, *curr;
ptr = head;
while (ptr->data < d) {
prev = ptr;
ptr = ptr->next;
} // end while
temp = prev->next;
curr = new ListNode(d, ptr);
curr->next = prev->next; // or temp->next
prev->next = curr;
;
}
};
List mylist;
In this function, I'm trying to add a node in the middle of linked list. Other functions add items to the back and front just fine. When I add in the middle of the list, my prev->next links to curr just fine, but curr->next points to NULL.
I have been trying to make this program work for past 1.5 hours. I'll appreciate your help. This is homework.
The general procedure you'll want to use is:
surf down the next pointers until you reach the node you want to insert after (call it A)
change your inserted node (B)'s next pointer to match that of A's next pointer
change A's next pointer to point to B
It looks from your code that you're trying to maintain a sorted list of integers. This being homework you probably won't get a code snippet, but from glancing at your code, I have to ask why you take a next parameter in your node constructor, but then set the next value to null. Without seeing the rest of your code I can't say for sure, but I'd change next(NULL) on line 9 to be next(n), and then remove the curr->next line near the bottom
Related
This question already has answers here:
Binary Search Tree Destructor
(6 answers)
Closed 2 years ago.
Please help me. I am stuck at this.
What am I trying to do: Binary search tree.
I am a C# developer and I learn C++ for about 2 weeks, therefore don't be so harsh with me and that's why pointers are still difficult for me.
I have a struct Node
struct Node
{
int Value;
Node* _LeftNode;
Node* _RightNode;
Node(int value)
: Value(value), _LeftNode(NULL), _RightNode(NULL)
{
}
};
and a Delete() function in BinarySearchTree.cpp
void BinarySearchТрее::Delete(Node* node)
{
if (node)
{
Delete(node->_LeftNode);
Delete(node->_RightNode);
delete(node);
node = NULL;
}
}
I want to delete the node and all of its child nodes.
When I first step in the recursion... For example:
I have two child nodes with values 10 and 19.
With recursion, I delete the nodes and set the pointers to NULL.
And here is the problem:
When I came out from the recursion the nodes are not NULL, but something strange.
And this is my problem. Why when I am in the recursion and I NULL the pointer everything is fine, but when I come out the pointer is something else.
As I talked in the comments, I think the thing is that how we can reset the pointer of the parent's(left or right child) of the initially passed node. (recursively deleting a node and its all children looks good.)
And I don't think it is possible in your current design. As Node does not contain a pointer to its parent, so there is no way to know who's the parent. node = NULL sets just the argument(local variable)'s value so it is pointless.
The C++ way would be to use std::unique_ptr.
struct Node
{
int Value;
std::unique_ptr<Node> LeftNode;
std::unique_ptr<Node> RightNode;
Node(int value)
: Value(value)
{
}
};
Then to destroy a node and all of its children, you'd call reset on the appropriate std::unique_ptr<Node>
I think what you actually want ist this:
struct Node
{
int Value;
Node* _LeftNode;
Node* _RightNode;
Node(int value)
: Value(value), _LeftNode(NULL), _RightNode(NULL)
{
}
~Node() {
delete _LeftNode;
delete _RightNode;
}
};
This way you are using the destructor to clean up recursivly.
delete nullptr is ok btw.
EDIT:
the unique_ptr<> usage in one of the other answers is probably the smarter way to do this.
Given:
struct Node
{
int data = 0;
struct Node * left = nullptr, * right = nullptr;
Node(int data) { this->data = data; }
};
This recursive function deletes a node & its childs (+ one comment):
void DeleteTree(struct Node* node) // A copy of the caller pointer
{
if (node)
{
DeleteTree(node->left); // Recur on left subtree
DeleteTree(node->right); // Recur on right subtree
delete node;
// node = nullptr; <-- This line is useless
}
}
To your wondering "but when I come out the pointer is something else":
There is no point in node = nullptr line, since when you call DeleteTree(my_node) function, node is a copy of my_mode, so when you set node = nullptr it has no effect on my_node that on exit from DeleteTree(my_node) points to a deleted, invalid object.
--
Possible solution:
#define DELETE_TREE(node) DeleteTree(node); node = nullptr; // Macro
int main()
{
struct Node* root = new Node(1);
root->left = new Node(2);
root->right = new Node(3);
root->left->left = new Node(4);
root->left->right = new Node(5);
DELETE_TREE(root->left); // root->left became nullptr
DELETE_TREE(root); // root became nullptr
return 0;
}
After DeleteTree function, the caller pointer points to an invalid object since its object already released. A possible solution is to define a DELETE_TREE Macro to "auto-nullify" the caller pointer after DeleteTree function.
--
Implementation with Modern C++ Smart Pointers:
#include <memory>
struct Node
{
int data = 0;
std::unique_ptr<Node> left, right;
Node(int data) { this->data = data; }
};
int main()
{
std::unique_ptr<Node> root;
root = std::make_unique<Node>(1);
root->left = std::make_unique<Node>(2);
root->right = std::make_unique<Node>(3);
root->left->left = std::make_unique<Node>(4);
root->left->right = std::make_unique<Node>(5);
root.reset();
return 0;
}
I am currently trying to write a doubly linked list class in c++ language on cygwin64. My addToTail function (to add a node to the end of the list) causes a core dump. I have identified the line of code which does it but cannot work out why.
I have peeled back my code to the simplest form to work out where the problem is. I have identified it as the current->setNext(temp); line.
below is all relevant code
class Node
{
private:
classType data;
Node* next;
Node* previous;
public:
void Node::setData(const valueType& newData)
{
data = newData;
}
void Node::setNext(Node* newNext)
{
next = newNext;
}
void Node::setPrevious(Node* newPrevious)
{
previous = newPrevious;
}
};
class LinkedList
{
private:
Node* tail;
Node* head;
Node* current;
public:
void LinkedList::addToTail(const classType& newTail)
{
Node* temp = new Node;
temp->setData(newTail);
current = tail;
temp->setPrevious(current);
current->setNext(temp);
tail = temp;
delete temp;
}
};
The expected results of the function is to add a new Node onto the end of the list. What happens is it causes a core dump.
(I assume that LinkedList has valid constructors, and assignment operators no shown in the question. If it lacks those, then addToTail treads on undefined behavior from the the start)
public:
void LinkedList::addToTail(const classType& newTail)
{
Node* temp = new Node;
temp->setData(newTail);
...
tail = temp;
delete temp;
}
The last delete makes no sense. It deletes temp, which is the same as deleting tail since tail is still accessible from LinkedList. It will trigger undefined behavior the next time addToTail is called, since it will access the deleted tail here:
temp->setData(newTail);
So I have a class, lets call it Cow. This cow has an age and some other variables like a static number of Cows alive variable.
Well I want to make a linked list, and I made the class for it and the node structure inside of the linkedlist class, looks a bit like this.
struct node{
Cow data;
node* next;
};
Then there's my addNode function to add a node.
void List::addNode(Cow newData)
{
//Creates a Cow object that will skew counters. BELOW.
node* n = new node;
n->data = newData;
n->next = NULL;
if(head == NULL){
head = n;
}else{
curr = head;
while(curr->next != NULL){
curr = curr->next;
}
curr->next = n;
}
}
With the line
node* n = new node, it'll create a new Cow object, which calls the Cow constructor, which increments the number of Cows alive static variable.
Simply, my question is...
How would I go about not calling the constructor for that Cow object when the node is first created, so I can fill it up with the newData object instead. Therefore not messing up my counter, which increments in the constructor?
You could create a node constructor which takes a Cow parameter and uses it to copy-construct its internal Cow. I assume Cow's copy constructor doesn't increment the static counter.
struct node{
node(Cow &cow): data(cow) {}
Cow data;
node* next;
};
What you may want is moving your object into the list. That way, you won't have more 'live' objects than needed.
You can accomplish this the simplest way by separating the Cow from the Node by e.g. wrapping it inside an std::unique_ptr<Cow>. You get all the correctness for free.
The other way is to only allow moving cows into your list:
List::addNode(Cow &&cow) {
auto node = new node(std::move(cow));
...
}
But then you'll also need to add a move constructor to Cow, which obviously does not increment the counter:
Cow::Cow(Cow &&other)
: field1(std::move(other.field1))
, field2(std::move(other.field2))
{ // dont increment counter!
other.dontDecrementCounterOnDestruction(); // important!
}
An extra possibility is to actually 'emplace' your cow onto the list (like std::emplace_back()):
template<typename T...>
void List::addNode(T... arguments) {
auto n = new node(arguments...);
...
};
template<typename T...>
node::node(T... arguments): myCow(arguments...)
{ // ... whatever else needs to be done
}
But then you're getting very close to what std::list does, and unless it's an exercise, you'll better be of just using std::list or std::forward_list anyway.
How would I go about not calling the constructor for that Cow object when the node is first created,
You can't do that. When you construct a node object, all of its member variables will be initialized. With node being defined the way it is and if Cow has a default constructor, then it will be called to initialize data.
so I can fill it up with the newData object instead.
The best you can do is use a move constructor or a copy constructor to avoid the cost of construction followed by assignment.
Update node to:
struct node{
node() : data(), next(nullptr) {}
node(Cow const& copy) : data(copy), next(nullptr) {}
Cow data;
node* next;
};
and then update addNode to:
void List::addNode(Cow newData)
{
node* n = new node(newData);
if(head == NULL){
head = n;
}else{
curr = head;
while(curr->next != NULL){
curr = curr->next;
}
curr->next = n;
}
}
I am trying to create a function that adds a node to the end of a LinkedList. I know how to do it using loops, but my professor wants it done a certain way and I don't understand why it's not working. He practically gave us all the code for it..
This is the pseudo-code he gave us:
process append(data)
if (not the end)
next->append(data);
else
next=new Node();
next->data=data;
next->data = nullptr;
And this is what I came up with:
struct Node {
int data;
Node* next;
};
struct LinkedList {
Node* head;
LinkedList() {head = nullptr;}
void prepend(int data) {
if (head == nullptr) {
Node* tmp = new Node();
tmp->data=data;
tmp->next=nullptr;
}
else {
Node* tmp = new Node();
tmp->data=data;
tmp->next=head;
head=tmp;
}
}
void append(int data) {
Node* tmp = head;
if (tmp->next != nullptr) {
tmp=tmp->next->append(data);
}
else {
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
}
};
int main()
{
LinkedList LL = LinkedList();
LL.prepend(7);
LL.append(6);
std::cout << LL.head->data << std::endl;
}
My prepend (to add to the beginning of the LinkedList) works fine, but when I try this code, I get
main.cpp:48:20: error: 'struct Node' has no member named 'append'
tmp->next->append(data);
So I'm pretty sure that there's something wrong with saying next->append(data), which from what I understood, is supposed to be recursively calling back the append function until it reaches a nullpointer. I'm thinking maybe there's some sort of way to write it, but people in my class are telling me that the next->append(data) thing SHOULD work, so I guess I'm not exactly sure why this isn't doing anything. I tried instead writing the append function in the Node struct, but then it says that head wasn't declared in the scope and I really just don't know how to work with this. I'm also sort of new to classes/structs in C++ so I'm assuming it's something about that that I'm not understanding.
The class Node has not any method named append so you get that error message:
tmp->next->append(data);
^^^^^^^^^^^^^
struct Node {
int data;
Node* next;
};
To append a node to a linked-list, you don't need an append method within Node. Remove that. Correct the append process in LinkedList::append:
void append(int data) {
Node* tmp = head;
while (tmp->next)
tmp = tmp->next;
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
I did't test, but you need something like above code. At first, it tries to access to the end of list. Then it appends a node.
Recursive implementation:
void append(int data) {
append(data, head);
}
void append(int data, Node *node) {
if (node->next)
append(data, node->next);
else {
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
}
Your append method isn't defined on the Struct Node. Instead it's defined on the LinkedList class so you need to invoke it accordingly. You can redefine the append method to take a node as a parameter or add an append method to the Struct Node itself. Also there's no need to assign the result of append to tmp =
Your append method is void.
tmp->next is a Node, so to call append function, you must declare it in Node struct
Like this
struct Node
{
void append(int data)
{
if (next)
next->append(data);
else
{
next = new Node();
next->data = data;
next->next= nullptr;
}
}
int data;
Node* next;
};
it's clear from the pseudo code next->append(data); that append is meant to be a member of Node.
Here's how you might use Node::append from LinkedList::append
class LinkedList {
void append(int data) {
if (head == nullptr) {
head = new Node();
head->data=data;
head->next=nullptr;
}
else {
head->append(data);
}
}
}
The node structure does not contain any append method.
Moreover, you are splitting work that can be done in one methos to two methods, writing more code.
See my answer to another question here with working code I wrote
https://stackoverflow.com/a/37358192/6341507
As you can see, I solve all in method
AddItem(int i)
I start seeing that creating linked list i kindof har for many people here, so I will further edit my answer there to provide additional information.
Good luck!
I have a linked_list and currently my destructor is not working properly. Not entirely sure why.
Can somebody explain me how to solve this?
class linked_list {
private:
struct node
{
// String in this node
std::string data;
// Pointer to next node
struct node *next;
};
//First item in the list
struct node *first;
Here is my destructor
linked_list::~linked_list(void)
{
while (first)
{
delete first;
first = first->next;
}
}
The problem lies here:
delete first;
first = first->next;
When you delete first, but then try to access first->next. Cache first->next into a temp variable of type node*, then do delete first to fix this:
struct node* temp;
while (first != NULL)
{
temp = first->next;
delete first;
first = temp;
}
change to
linked_list::~linked_list(void)
{
struct node *next;
while (first != NULL)
{
next = first->next;
delete first;
first = next;
}
}
When you 'delete' first, you actually clear all the links from it. Now, if you try to access some other node using this, will not produce the required result.
First, you have to point that node with some other pointer, so that you still have some link which you can access later.