Return element of linked list - c++

Please delete.
I want to implement a linked list. Unfortunately I'm not sure whether I'm on the right track.
#include <iostream>
using namespace std;
class Node {
friend class List;
public:
int value;
private:
Node *next;
};
class List {
public:
List ();
~List ();
Node * first() const;
Node * next(const Node * n) const;
void append (int i);
Node* head;
};
List::List() {
Node* head = new Node();
}
List::~List() {
while(head != NULL) {
Node * n = head->next;
delete head;
head = n;
}
}
Node * List::first() const {
return head; // this could also be wrong
}
Node * List::next(const Node * n) const {
return n + 1; // ERROR
}
void List::append(int i) {
Node * n = new Node;
n->value = i;
n->next = head;
head = n;
}
int main(void) {
List list;
list.append(10);
return 0;
}
When I try to return an element in next() I get this error:
In member function ‘Node* List::next(const Node*) const’:|
error: invalid conversion from ‘const Node*’ to ‘Node*’ [-fpermissive]|
Could somebody please help me?
EDIT:
I've updated the error-line.

I think what you mean to be doing is returning the Node's next:
Node * List::next(const Node * n) const {
return n->next;
}
You would use pointer arithmetic if this were an array where the size of each object was constant, but linked lists can't use pointer arithmetic. If you have an iterator, you could use the '++' operator to get the next object, but with this just stick to returning the node's next field.
I'm assuming this will also work because even though next is declared as private, you've made List a friend.

You are thinking that consecutive nodes are in consecutive blocks of memory, and they are not. Linked lists have nodes in random places in memory, which is why "next" points to the NEXT node. You cannot increment or add as you are trying (well you can, but semantically it would be incorrect.)

Related

How did this loophole around const member function worked?

In the below code we try to multiply each element's data in the list by 2 and assign it. But the apply function is a const function therefore should not be able to change the values of member fields. Output for the fifth line in main is
6
4
2
2
4
So code below succeeds in changing the values as intended and I can't figure out why.
#include <iostream>
#include <list>
#include <string>
using std::ostream;
using std::cout;
using std::endl;
template<class E> class MyList {
class Node {
friend class MyList<E>;
E data;
Node* next = nullptr;
}; // end of class Node
Node* head = new Node;
Node* tail = head;
MyList(const MyList&) = default;
public:
MyList() = default;
MyList& operator=(const MyList&) = delete;
void push_front(const E& data) {
Node* node = new Node;
node->data = data;
node->next = head->next;
head->next = node;
if(head->next == nullptr) tail = node;
}
void push_back(const E& data) {
if(head->next == nullptr) {
push_front(data); return;
}
MyList temp(*this);
temp.head = temp.head->next;
temp.push_back(data);
temp.head = nullptr;
}
~MyList() {
Node *node = head, *next;
while(node != nullptr) {
next = node->next;
delete node;
node = next;
}
}
template<class Function>
void apply (Function f) const {
Node* node = head->next;
while(node != nullptr) {
f(node->data);
node = node->next;
}
}
};
int main() {
MyList<int> m1;
m1.push_back(3);
for(int i = 1; i <= 2; ++i) m1.push_front(i);
for(int i = 1; i <= 2; ++i) m1.push_back(i);
m1.apply(
[](auto& val){ val *= 2;}
);
m1.apply(
[](const auto& val){cout << val << endl;}
);
return 0;
}
The key is logical vs bitwise constness. The head data member is a non-const pointer to non-const Node: the const correctness of the apply member function is bitwise constness:
you cannot change what the head data member (pointer) points to from a const-qualified member function.
You can, however, mutate the Node object that it points to.
Because it is not the same, the pointer you store in your const struct as a member, than the data pointed by that pointer, which still is of type Node* (non const).
Just for the sake of showing, try to set all the pointers to NULL:
while(node != nullptr) {
f(node); // Pass the Node*, instead of the reference to the value
node = node->next;
}
The above code will not compile, as you will be passing a Node* const& to your lambda, which will be a const reference and will not be possible to set it to NULL.
The const in the functions declarations is not transitive. The pointed memory accessed through some pointer member is not affected by that. It will still have the same type as that of the declared pointer member, in this case Node*.
This is called (as stated in the other answer) logical constness, and is ensured by the function const signature.
While you are trying to achieve bitwise constness, which is not achieved with the signature, but with the type declaration.
And about types, inside the const function the type of the pointer would become Node* const, meaning a constant pointer (logical constness, cannot change where it points), while the type of the data pointed is Node* (it can be changed, bitwise constness)

Recursive length function implementation in a linked-list

I am implementing a linked-list, and one of the function asks for the number of nodes in the linked list. However, as the requirement says it needs to be done recursively.
Here is my implementation so far.
class LList {
public:
bool isEmpty() const;
void cons(int x);
int length() const;
private:
struct Node {
int item;
Node* next;
};
Node* head;
}
bool LList::isEmpty() const{
if(head == nullptr)
return true;
else
return false;
}
void LList::cons(int x){
Node* temp = new Node;
temp->item = x;
temp->next = head;
head = temp;
}
I can only do this iteratively, but couldn't make the recursion work.
int LList::length(Node* head) const{
Node* temp = head;
if (temp == nullptr) {
return 0;
}
return 1 + length(temp->next);
}
int LList::length() const {
return length(head);
}
I tried to use a helper function to do the job, but it's saying declaration is incompatible with int LList::length() const
Can anyone help me with this problem?
You are recursing the wrong place: You only have a single LList, so there is nothing to recurse on there. What you want to do instead is to recurse on the Node objects.
Keep your int LList::length() const function, but all it has to do is check if head is nullptr and then call the new recursive function that you are going to make: int LList::Node::length() const. This one then recurses through the next pointers of your Node objects and counts them.

Class member function works normally, but gets stuck in an infinite loop when called as a data member of another class

I wrote a tree structure and made a basic search function to look for nodes within the tree. The tree itself uses a sentinel node to mark all ends (parent of the root, child of the leaves), and search simply iterates through nodes until it either finds a match or hits the sentinel node. The search function works fine when I call it on an instance of a tree, however it gets stuck when the tree is a data member of another class. In the following code, "t.search(1)" works, but "embedded_tree.t.search(1)" gets stuck in an infinite loop.
I have narrowed it down to the fact that when the call to embedded_tree.t.search() is made, the content of "&sentinel" correctly points to the sentinel node, but seems to be a new pointer, as it is not equivalent to the contents of root, sentinel.parent, and sentinel.child. From here I am stuck and am not sure how to call it so that &sentinel matches the pointers that were created when the tree was constructed.
#include <iostream>
struct NODE {
int key;
NODE* parent;
NODE* child;
NODE() : key(0), parent(NULL), child(NULL) {};
};
struct TREE {
NODE sentinel;
NODE* root;
TREE()
{
sentinel = *new NODE;
sentinel.parent = &sentinel;
sentinel.child = &sentinel;
root = &sentinel;
}
NODE* search(int k)
{
NODE* x = root;
while (x != &sentinel)
{
if (x->key == k) return x;
x = x->child;
}
return &sentinel;
}
};
struct A {
TREE t;
A() : t(*new TREE()) {};
};
int main()
{
TREE t;
t.search(1);
A embedded_tree;
embedded_tree.t.search(1);
}
You're confusing dynamic memory allocation with stack allocation. When you do
sentinel = *new NODE
bad things happen. Memory gets allocated for NODE sentinel on the stack, then for NODE in new operator, then assignment gets done to sentinel variable, and memory created in new operator is lost. You should rewrite your code to use pointers instead, and add destructors, something like this
#include <iostream>
struct NODE {
int key;
NODE* parent;
NODE* child;
NODE() : key(0), parent(NULL), child(NULL) {};
};
struct TREE {
NODE* sentinel;
NODE* root;
TREE()
{
sentinel = new NODE;
sentinel->parent = sentinel;
sentinel->child = sentinel;
root = sentinel;
}
~TREE() {
if (NULL != sentinel) {
delete sentinel;
sentinel = NULL;
root = NULL;
}
}
NODE* search(int k)
{
NODE* x = root;
while (x != sentinel)
{
if (x->key == k) return x;
x = x->child;
}
return sentinel;
}
};
struct A {
TREE* t;
A() : t(new TREE()) {};
~A() {
if (NULL != t) {
delete t;
t = NULL;
}
}
};
int main()
{
TREE t;
t.search(1);
A embedded_tree;
embedded_tree.t->search(1);
}
However, since we're talking about C++, I'd suggest you to look to smart pointers and containers after you get familiar with manual memory management.

Linked List destructor in C++: should I delete?

I've start implementing some data structures in C++, starting from Linked Lists.
Coming from a Java background, I'm still wrapping my head around pointers and objects lifespans.
LinkedList:
struct Node
{
int data;
Node *next;
};
class LinkedList
{
private:
Node *head;
Node *tail;
int length;
public:
LinkedList();
~LinkedList();
void addToHead(Node &newHead);
void popHead();
void printList();
};
and then I've implemented it like this:
LinkedList::LinkedList()
{
head = NULL;
tail = NULL;
length = 0;
}
LinkedList::~LinkedList(){}
void LinkedList::addToHead(Node& newHead)
{
newHead.next = head;
head = &newHead;
length++;
}
void LinkedList::popHead()
{
Node *currHead = head;
head = head->next;
length--;
}
void LinkedList::printList()
{
Node *curr = head;
while(curr)
{
curr = curr->next;
}
}
Lastly there's a simple main:
int main()
{
LinkedList list;
Node n1 = {3};
Node n2 = {4};
Node n3 = {5};
list.addToHead(n1);
list.addToHead(n2);
list.addToHead(n3);
list.printList();
list.popHead();
list.printList();
return 0;
}
This a rather naive implementation, and I was wondering if I had to provide a proper destructor which deletes the Node* pointers upon iteration.
Whenever I've tried to add it, the program results in a memory error, and I was thinking that the memory being allocated is being also deallocated at the end of the main, since all the Node*s live there.
Should I fix my destructor? Should I change the whole interface?
Thanks in advance!
Although there are no memory leaks in your code as it stands, I think you should change your interface.
Your linked list isn't doing what you probably think its doing - taking ownership of its contents. A linked list that doesn't own its contents is a strange beast and probably something you did not intend.
One easy way to make it take ownership is to change your design to use std::unique_ptr instead of raw pointers. Your addToHead function would then be change to take std::unique_ptr r-value references pointers (or simply raw pointers that create new std::unique_ptr internally if that's too advanced)
Here is your implementation changed to use std::unique_ptr. Its a bit rough-and-ready, but should get you on your way:
#include <memory>
struct Node
{
Node(int i) : data(i)
{}
int data;
std::unique_ptr<Node> next;
};
class LinkedList
{
private:
std::unique_ptr<Node> head;
Node *tail;
int length;
public:
LinkedList();
~LinkedList();
void addToHead(std::unique_ptr<Node>&& newHead);
void popHead();
void printList();
};
LinkedList::LinkedList()
{
head = NULL;
tail = NULL;
length = 0;
}
LinkedList::~LinkedList(){}
void LinkedList::addToHead(std::unique_ptr<Node>&& newHead)
{
newHead->next = std::move(head);
head = std::move(newHead);
length++;
}
void LinkedList::popHead()
{
head = std::move(head->next);
length--;
}
void LinkedList::printList()
{
auto* curr = head.get();
while(curr)
{
curr = curr->next.get();
}
}
int main()
{
LinkedList list;
list.addToHead(std::make_unique<Node>(3));
list.addToHead(std::make_unique<Node>(4));
list.addToHead(std::make_unique<Node>(5));
list.printList();
list.popHead();
list.printList();
return 0;
}

how to use "new" to allocate memory of the point reference argument inside a function

Here is my code
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
void insert(ListNode *&head,int value)
{
ListNode *node;
node = head;
if(!node)
{
//node = new ListNode(value);
head = new ListNode(value);
}
else
{
while(node->next != NULL)
node = node->next;
node->next = new ListNode(value);
}
}
void print(ListNode *head)
{
ListNode *node = head;
for(;node!=NULL;){
printf("%d ",node->val);
node = node->next;
}
}
int main(int argc,char *argv[])
{
ListNode *head = NULL;
insert(head,0);
insert(head,1);
insert(head,2);
print(head);
return 0;
}
Inside function insert,if I pass head to the point node,and use node = new ListNode(value);,the insert action fail and head is still NULL.But I use
new allocate memory to head directly,it works.I am confused about the point reference inside function in C++ and hope somebody help me figure it out.
This:
ptr = new whatever;
allocates memory, maybe calls a constructor, and assigns a new value to ptr.
Now consider these two functions:
void foo1(int &n)
{
int k=n;
k=5;
}
void foo2(int &n)
{
n=5;
}
After I call foo1, the value of the variable I passed (by reference) is unchanged. But after I call foo2, it is 5.
Find my inline comments to understand what each step is doing
node = head; //! Here your node pointer pointing to the memory pointed by head
if(!node) //! You are checking if that memory is null or not
{
node = new ListNode(value); //! now you are pointing your node pointer to some newly allocated memory, there is no impact on head pointer.
//! If you want to change the head pointer also so
head = node; //! Now head also pointing to the newly allocated location.
}