I'm trying to implement a linked list class in C++ using a node class and a pointer to the next node.
template<class T>
class Node {
public: T val;
public: Node* next;
public: Node() { }
public: Node(T val) { this.val = val; }
};
I created a linked list class with a pointer to the head and a function append to add nodes to the list:
template<class T>
class LinkedList {
private: Node<T>* head;
public: LinkedList() { }
public: LinkedList(T val) { head -> val = val; }
public: void append(T val) {
Node<T>* temp = head;
while(temp -> val != NULL) {
temp = temp -> next;
}
temp -> val = val;
}
};
but after compilation and running, it throws this error "Segmentation fault (core dumped)"
I know a little about segmentation fault like trying to access a memory location that is no longer existed but I don't get it in this example, any help??
The main problem is that you don't initialize the next pointer with null pointer, but you assume it is null pointer by default. Here's how you fix it:
template <class T>
class Node {
public:
T val;
Node* next;
Node( T val_ = {} )
: val{ val_ }
, next{ nullptr }
{ }
};
Besides that, in the append there are problems. Here's how the code should have looked like completely:
template <class T>
class Node {
public:
T val;
Node* next;
Node(T val_ = {}) : val{ val_ }, next{ nullptr } {}
};
template <class T>
class LinkedList {
private:
Node<T>* head;
public:
LinkedList(T val_ = {}) : head{ new Node{val_} } {}
void append(T val) {
Node<T>* temp = head;
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = new Node<T>{ val };
}
};
int main() {
LinkedList<int> l;
l.append(10);
}
Other comments:
this.val won't compile, because this is a pointer. You meant this->val.
You should consider using member initializer lists instead of this->val = val.
Initialize all members in all constructors.
Related
I am trying to implement two member functions, i.e., push_front and the destructor. I have written the code of the push_front function. But I seem, I am doing wrong anywhere. How can I fix this issue? How can I insert a node in front of Linked-List properly?
template <typename T>
class Node {
public:
Node():next_p_{nullptr} {}
Node(T v, Node* n):data_{v}, next_p_{n} {}
~Node() {};
void setData( T &v ) { data_ = v; }
const T &getData() const { return data_; }
void setNext( Node *n ) { next_p_ = n; }
Node *getNext() const { return next_p_; }
private:
T data_;
Node *next_p_;
};
template <typename T>
class LinkedList {
private:
Node<T> *head_ptr_;
public:
LinkedList():head_ptr_{nullptr} {}
~LinkedList() {
}
// Insert at the front of the linked list (UPDATED)
void push_front( T v ){
Node *new_node = new Node;
new_node->setNext(*head_ptr_) = v;
new_node->next_p_ = this->head_ptr_;
this->head_ptr_ = new_node;
}
};
The first Node constructor takes the value and next pointer, use that to create the new node in one step.
You shouldn't dereference head_ptr_ when using it as the next pointer. It's already a Node*, which is the correct type for head_ptr_.
void push_front( T v ){
Node *new_node = new Node(v, head_ptr_);
this->head_ptr_ = new_node;
}
I would also recommend not dealing with manual memory management and instead use smart pointers to simplify your life a bit.
Using std::unique_ptr you wont have to deal with reclaiming the memory you allocated from the free store.
One caveat to this approach is you lose your ability to copy the List but usually that's what you want anyway.
template<typename T>
class List {
struct Node {
Node( T value ) noexcept
: data{ std::move_if_noexcept( value ) }
{ }
T data;
std::unique_ptr<Node> next{ nullptr };
};
public:
auto push_front( T value ) -> void {
auto node{ std::make_unique<Node>( std::move_if_noexcept( value ) ) };
std::swap( node->next, head_ );
std::swap( head_, node );
}
~List()
{
while (head_) {
std::unique_ptr<Node> tmp(std::move(head_));
head_ = std::move(tmp->next);
}
}
private:
std::unique_ptr<Node> head_{ nullptr };
};
please help. I am getting segmentation fault when i try to print elements in this linked list.
i first declare a class and the function to insert and display the elements of the list are its functions.
code:
#include <iostream>
using namespace std;
struct node{
int data;
node *next;
};
class ll{
node *head,*tail;
public:
void push(int x){
node *temp = new node;
temp->data = x;
temp->next = NULL;
if(head == NULL){
head = temp;
tail= temp;
}
else{
tail->next = temp;
tail= temp;
}
}
void show(){
node *n = head;
while(n!=NULL){
cout<<n->data<<"\n";
n = n->next;
}
}
};
int main()
{
ll a;
a.push(1);
a.push(2);
a.show();
return 0;
}
Neither the data member head nor the data member tail are initialized by nullptr. So the program has undefined behavior.
You could write in the class definition
class ll{
node *head = nullptr, *tail = nullptr;
//...
Bear in mind the structure node should be member of the class ll. For example
class ll{
struct node{
int data;
node *next;
} *head = nullptr,*tail = nullptr;
public:
void push( int x ){
node *temp = new node { x, nullptr };
if( head == NULL ){
head = tail = temp;
}
else {
tail = tail->next = temp;
}
}
//...
Instead of initializing data members in the class definition you coudl initialize them in the default constructor like for example
class ll{
struct node{
int data;
node *next;
} *head,*tail;
public:
ll() : head( nullptr ), tail( nullptr ) {}
// ...
Also you need at least to define the destructor and either explicitly define the copy constructor and copy assignment constructor or define them as deleted. For example
class ll{
struct node{
int data;
node *next;
} *head,*tail;
public:
ll() : head( nullptr ), tail( nullptr ) {}
~ll() { /* must be defined */ }
ll( const LL & ) = delete;
ll & operator =( const ll & ) = delete;
// ...
The problem is that you don't set head to NULL when you list is created. Same issue applies to tail. This is a job for the constructor
class ll {
node *head,*tail;
public:
ll() { head = tail = NULL; }
void push(int x) {
...
so I am trying to make the queue with the linked list
which uses template in c++ to make any kind of data type queue.
However, it gives me a such error when I am trying to make template with "ListNode" class and its friend class "List":
Error C2955 'ListNode': use of class template requires template argument
this error is at line 33 where I declare head listnode and tail list node in List class
ListNode* list_head;
ListNode* list_tail;
How can I find solution to unite these two classes into template? please help.
below is my code sample:
template <typename T>
class ListNode
{
private:
T data;
int priority;
ListNode* prev;
ListNode* next;
public:
ListNode() { prev = next = NULL; }
ListNode(T d, int pr, ListNode* p, ListNode* n) { data = d; priority = pr; prev = p; next = n; }
template <typename T>
friend class List;
};
template <typename T>
class List
{
private:
ListNode* list_head;
ListNode* list_tail;
public:
List() { list_head = list_tail = NULL; }
~List() { clear(); }
bool isEmpty() { return list_head == NULL; }
bool contains(T value);
void addToQueList(T value, int priority);
T head() { return list_head->data; }
T tail() { return list_tail->data; }
T removeHead();
T removeTail();
void clear();
};
template <typename T>
bool List<T>::contains(T value)
{
ListNode *temp = list_head;
while (temp != NULL && temp->data != value)
temp = temp->next;
return temp != NULL;
}
I'm realitively new to using linked lists. I'm trying to overload the ostream opperator for a doubly linked list with decleration :
template <class T>
class DynamicList;
template <class T>
template <class T>
class DynamicList
{
private:
Node<T> *head;
public:
class Node
{
public:
T* value;
Node<T> *next;
Node<T> *prev;
Node(T val)
{
next = nullptr;
prev = nullptr;
value = &val;
}
};
DynamicList();
~DynamicList();
void operator+=(const T);
friend std::ostream & operator<< <>(std::ostream &, const DynamicList<T> &);
};
and function defenition:
template <class T>
ostream& operator << (ostream & out , const DynamicList<T> & rhs)
{
Node<T>* nodePtr = rhs.head;
Node<T>* nptr = nodePtr->next;
while(nodePtr != NULL)
{
cout<<*(nodePtr->value)<<" ";
nodePtr = nodePtr->next;
}
out<<endl;
return out;
}
template <class T>
void DynamicList<T>:: operator +=(const T val)
{
Node<T>* nodePtr = nullptr;
T vall = val;
Node<T>* newNode = new Node<T>(vall);
if(!head)
{
head = newNode;
}
else
{
nodePtr = head;
while((nodePtr->next))
{
nodePtr = nodePtr->next;
}
nodePtr->next = newNode;
newNode->prev = nodePtr;
}
Every time I'm calling the opperator it gives a weird output for example using:
for(int i = 1; i <= 3; i++)
{
list += i;
}
cout<<list;
It would give an output like 135727363 135727383 135727383 ,I'd just like to know what I'm doing wrong and possibly how I could solve it
Your problem is here:
T* value;
You are storing the address of a value.
The problem is that you are storing the address of a variable that has gone out of scope.
T vall = val;
Node<T>* newNode = new Node<T>(vall);
The variable vall is local to the function operator += which means after it exists it no longer exists (and can contain anything).
To fix change the node to store the value.
class Node
{
public:
T value; // Notice no star here.
Node<T> *next;
Node<T> *prev;
Node(T const& val) // Add `const&` here to avoid a copy.
{
next = nullptr;
prev = nullptr;
value = val; // Notice no and `&` here
}
};
My code is below as well as the description of my problem:
class node
{
public:
node(float val1, node* next1)
: val(val1), next(next1) { }
node(int val1)
:val(val1), next(NULL) { }
node() { }
float getvalue() { return val;}
node* getnext() { return next;}
private:
float val;
node* next;
};
class linkedlist
{ public:
linkedlist(): head(NULL), tail(NULL) { }
node* addnode(node* a)
{
tail->getnext() = a;
tail = a;
}
float printlist()
{
node* tmp = head;
while(tmp!=NULL)
{
std::cout << tmp->getvalue() << std::endl;
tmp = tmp->getnext();
}
}
private :
node* head;
node* tail;
};
int main()
{
}
Could anyone help me fix the error? I just want to set tail->next = a, but
as next is a private value, I can't do this. I've been using tail->getnext() = a, but then the error occurs. Why does the error occur?
Thanks!
node::genNext () returns a pointer an it is an R-value, so you cannot assign anything to it.
To do this, you have to return a reference to the pointer, which is a modifiable L-value:
node*& getnext() { return next;}