C++: linked list head and tail pointers - c++

I donĀ“t get this, when I call head->valueit returns me the last value added to the linked list. Should it not return me the first item since head is only set when it is empty? correct? I am thinking maybe there is there some other bug in the code.
void LinkedListPQueue::enqueue(const string& elem) {
cell *newCell = new cell;
newCell->value = elem;
newCell->next = NULL;
if(this->isEmpty()) {
this->head = this->tail = newCell;
} else {
// find smallest and put it there
this->tail->next = newCell;
this->tail = newCell;
}
}
declared in header
struct cell {
std::string value;
cell *next;
};
cell *head, *tail;

My be isEmpty is not implemented correctly so everytime you add a new node you re-assign the head to that node

Related

Why it is printing only 1st value of doubly linked list and than my program is crashing

I am trying to create a doubly linked list and then printing its value but the output is showing only first value and then the whole program is crashing.
I can't understand where is the problem in the code .
Input
3
1 2 3
Expected output
1 2 3
current output
1
#include<iostream>
#include<stdlib.h>
using namespace std;
class node //declation of node
{
public:
int data;
node *next;
node *prev;
};
node *makenode(node *head,int val) //function to create node
{
node *newnode=new node;
node *temp;
newnode->data=val;
newnode->next=0;
newnode->prev=0;
if(head==0) temp=head=newnode;
else
{
temp->next=newnode;
newnode->prev=temp;
temp=newnode;
}
return head;
}
void display(node *head) //display function
{
system("cls"); //clearing output screen
while(head!=0)
{
cout<<head->data<<" ";
head=head->next;
}
}
int main()
{
node *head;
head=0;
int val;
int s; //size of list
cout<<"ENTER THE SIZE OF LIST";
cin>>s;
system("cls");
for(int i=0;i<s;i++)
{
cout<<"ENTER THE "<<i+1<<" VALUE\n";
cin>>val;
head=makenode(head,val); //calling makenode and putting value
}
display(head); //printing value
return 0;
}
node *makenode(node *head,int val) //function to create node
{
node *newnode=new node;
node *temp; // #1
newnode->data=val;
newnode->next=0;
newnode->prev=0;
if(head==0) temp=head=newnode;
else
{
temp->next=newnode; // #2
Between the lines marked #1 and #2 above, what exactly is setting the variable temp to point to an actual node rather than pointing to some arbitrary memory address?
"Nothing", I hear you say? Well, that would be a problem :-)
In more detail, the line:
node *temp;
will set temp to point to some "random" location and, unless your list is currently empty, nothing will change that before you attempt to execute:
temp->next = newnode;
In other words, it will use a very-likely invalid pointer value and crash if you're lucky. If you're unlucky, it won't crash but will instead exhibit some strange behaviour at some point after that.
If you're not worried about the order in the list, this could be fixed by just always inserting at the head, with something like:
node *makenode(node *head, int val) {
node *newnode = new node;
newnode->data = val;
if (head == 0) { // probably should use nullptr rather than 0.
newnode->next = 0;
newnode->prev = 0;
} else {
newnode->next = head->next;
newnode->prev = 0;
}
head = newnode;
return head;
}
If you are concerned about order, you have to find out where the new node should go, based on the value, such as with:
node *makenode(node *head, int val) {
node *newnode = new node;
newnode->data = val;
// Special case for empty list, just make new list.
if (head == 0) { // probably should use nullptr rather than 0.
newnode->next = 0;
newnode->prev = 0;
head = newnode;
return head;
}
// Special case for insertion before head.
if (head->data > val) {
newnode->next = head->next;
newnode->prev = 0;
head = newnode;
return head;
}
// Otherwise find node you can insert after, and act on it.
// Checknode will end up as first node where next is greater than
// or equal to insertion value, or the last node if it's greater
// than all current items.
node *checknode = head;
while (checknode->next != 0 && (checknode->next->data < val) {
checknode = checknode->next;
}
// Then it's just a matter of adjusting three or four pointers
// to insert (three if inserting after current last element).
newnode->next = checknode->next;
newnode->prev = checknode;
if (checknode->next != 0) {
checknode->next->prev = newnode;
}
checknode->next = newnode;
return head;
}
You aren't actually linking anything together. This line: if(head==0) temp=head=newnode; is the only reason your linked list contains a value at all. The very first value sets head equal to it and when you print head you get that value. In order to properly do a linked list you need a head and tail pointer. The head points to the first element in the list and the tail points to the last. When you add an element to the end of the list you use tail to find the last element and link to it. It is easiest to make Linked List a class where you can encapsulate head and tail:
struct Node {
public:
int data;
node *next;
node *prev;
Node(int data) : data(data), next(nullptr), prev(nullptr) {} // constructor
};
class LinkedList {
private:
Node* head;
Node* tail;
public:
LinkedList() { head = tail = nullptr; }
// This function adds a node to the end of the linked list
void add(int data) {
Node* newNode = new Node(data);
if (head == nullptr) { // the list is empty
head = newNode;
tail = newNode;
}
else { // the list is not empty
tail->next = newNode; // point the last element to the new node
newNode->prev = tail; // point the new element to the prev
tail = tail->next; // point the tail to the new node
}
}
};
int main() {
LinkedList lList;
lList.add(1);
lList.add(2);
// etc...
return 0;
}

algorithm for finding a node in a linked list

what is the algorithm used to write Snode* find and set& operator=( set &rhs) I just can't understand these two. I can read the code but I can't figure out why are they there. I can't understand the steps of the used algorithm.
Things I already figured out:
1. Snode is a function that gets a value and returns the node with the same data.but what do prev and previous do and what is **previous and why ahould we create a pointer to a pointer?
2. set& operator= is for overriding the = operator. but I can't understand what does it do after overriding.and why should we swap the heads of temp and rhs sets.
here's the code:
#include <iostream>
using namespace std;
struct Snode //Snode class defines a node in a list
{
char data;//a node includes a character
int count;//an integer to count the occurrence
Snode *next = NULL;//and a pointer to the next node
Snode(char data, Snode* next) : data(data), next(next) {}
};
class set
{
private:
Snode *head;//first node in the list
Snode *tail;//last node of the list
public:
set() : head(NULL), tail(NULL)
{
}
set( set &src) : head(NULL), tail(NULL)//copy constructor method
{
Snode *temp = src.head;//set head of the second list as temp to travers
while (temp)//untill the end of the list
{
// insert(temp->data);
Snode *newNode = new Snode(temp->data,NULL);//create a new node with the same data and count
newNode->count = temp->count;
//now puts it in the right place
if (!head)//if head = NULL (if sset is empty)
head = newNode;//set the new node as the first node
if (tail)//if tail != NULL (if set isn't empty)
tail->next = newNode;//set new node as the next node of current tail, so it'll be the tail
tail = newNode;
temp = temp->next;//does the same thing for all the nodes of the second list
}
}
~set()//destructor method
{
Snode *temp = head;
while (temp)//traverse the list and delete each node
{
Snode *next = temp->next;
delete temp;
temp = next;
}
}
set& operator=( set &rhs)
{
if (&rhs != this)
{
set temp(rhs);
Snode *ptr = head;
head = temp.head;
temp.head = ptr;
}
return *this;
}
bool isAvailable(char value)//checks if any node with the same data exists or not
{
return (find(value) != NULL);//if find function can't find any, there's no same node
}
Snode* find(char value, Snode **previous = NULL)
{
if (previous)
*previous = NULL;
Snode *temp = head;
Snode *prev = NULL;
while (temp)
{
if (temp->data == value)
{
if (previous)
*previous = prev;
return temp;
}
temp = temp->next;
}
return NULL;
}
bool isFirst(char value)
{
return ((head) && (head->data == value));//if head's data is equal to value returns true
}
bool isLast(char value)
{
return ((tail) && (tail->data == value));//if tail's data is equal to value returns true
}
void display()
{
Snode *temp = head;
while (temp)
{
cout << temp->data << " " << temp->count+1 << "\n";
temp = temp->next;
}
}
void insert(char value)//to insert a new value
{
Snode *temp = find(value);//if a node with the same data alreay exists
if (temp)
temp->count += 1;//increase the count by one
else
{
temp = new Snode(value,NULL);//if if a node with the same data doesn't exist
if (!head)//if list is empty
head = temp;
if (tail)//if list is not empty
tail->next = temp;
tail = temp;
}
}
int count(char value)//count the nodes by the counter temp
{
Snode *temp = find(value);//travers the set
return (temp) ? temp->count : 0;//if the list is empty return 0, else return the counter
}
void deleteFirst()//deletes the first node
{
if (head)//if list isn't empty
{
Snode *temp = head;
head = head->next;//move the head forward
if (tail == temp)//if loop faced the tail
tail = NULL;
delete temp;//delete the data
}
}
void deleteLast()//delete the last node
{
if (head)
{
Snode *last = head;
Snode *previous = NULL;
while (last->next)//move forward untill the node before the last one
{
previous = last;
last = last->next;
}
if (previous)//at the end of the list
previous->next = NULL;
tail = previous;
if (head == last)//if there's only one node
head = NULL;
delete last;
}
}
void remove(char value)//remove the node with the same data as the entry
{
Snode *previous;
Snode *temp = find(value, &previous);
if (temp)
{
if (temp->count > 1)
temp->count -= 1;
else
{
if (previous)
previous->next = temp->next;
if (head == temp)
head = temp->next;
if (tail == temp)
tail = previous;
delete temp;
}
}
} };
As you have guessed, find tries to locate a Snode containing the required character. If only that is required, you can ignore the previous parameter (it will be NULL), and previous/prev processing will just be useless.
But find is used in remove... In order to remove a node in a singly linked list, you must have the previous one point to the next one. So you must browse the list keeping a track of the previous node. That is exactly the way it is used in remove with:
if (previous)
previous->next = temp->next;
The assignment operator uses a close variant of the copy and swap idiom. But as the destructor only uses the head member, only that member is swapped: that will be enough to have the destructor of temp to destroy all nodes of the original list.
Simply tail should be set in this even if it is useless to set it in tmp. A correct implementation could be:
set& operator=( set &rhs)
{
if (&rhs != this)
{
set temp(rhs);
Snode *ptr = head;
head = temp.head;
temp.head = ptr;
tail = temp.tail; // no need for a full swap here
}
return *this;
}

What is wrong in below linked list program in cpp?

I'm facing weird problem that the only 1st element of the list is get printed. I have writing linked list program after long time. thanks for the help. Is there something wrong with printAll function or add function in list class. I have tried printing previous elements while adding new one & it works. So, I'm not getting why only 1st element .ie. head is getting printed & head->next seems to be null.
#include<iostream>
using namespace std;
class Node{
public: int data;
public: Node *next;
public: Node(int data){
this->data = data;
this->next = NULL;
}
};
class List{
Node *head, *trav;
public: List(){
this->head = NULL;
this->trav = NULL;
};
void add(int data){
if(this->head==NULL && this->trav==NULL){
cout<<"inside the if block"<<endl;
this->head = new Node(data);
this->trav = this->head->next;
}
else{
cout <<"inside the else block"<<endl;
this->trav = new Node(data);
this->trav = this->trav->next;
}
}
void printAll(){
this->trav = this->head;
while(this->trav!=NULL){
cout<<this->trav->data<<endl;
this->trav = this->trav->next;
}
}
};
int main(){
List list;
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.printAll();
cout<<sizeof(list);
}
The add() method else part is not linking list properly, do some paper work.
Here is the working one, I tried to explain in comments.
void add(int data){
if(this->head==NULL && this->trav==NULL){ /* for 1st node */
cout<<"inside the if block"<<endl;
this->head = new Node(data);
this->trav = this->head->next;
}
else{
this->new_node = new Node(data); /*new_node */
cout <<"inside the else block"<<endl;
this->trav = head;/*temp var to point to ast node */
while(this->trav->next!=NULL) {
this->trav = this->trav->next;
}
this->trav->next = this->new_node; /*adding at end */
this->new_node->next = NULL; /*new_node next make it NULL */
}
}
Your add function doesn't link anything. Whenever you get into the else block trav is NULL and you set it equal a new node. But you never link that new node to the previous last node.
Normally trav would be named tail and point to the last element so that you can link a new element to the current last element.
Something like:
if(this->head==NULL && this->trav==NULL){
cout<<"inside the if block"<<endl;
this->head = new Node(data);
this->trav = this->head;
}
else{
cout <<"inside the else block"<<endl;
this->trav->next = new Node(data);
this->trav = this->trav->next;
}
Edit
OP commented that trav is not considered a tail pointer but just a pointer to traverse the list.
So therefore the answer is different as the code need to find the current tail using a loop.
Something like:
if(this->head==NULL){
cout<<"inside the if block"<<endl;
this->head = new Node(data);
}
else{
cout <<"inside the else block"<<endl;
this->trav = this->head;
while(this->trav->next)
{
this->trav = this->trav->next;
}
this->trav->next = new Node(data);
}
However, notice:
If trav is "just" a pointer to traverse the list, there is no real purpose in making it a member of List. Simply use a local variable inside the functions that need to traverse the list.
Since your code adds new elements to end-of-list it's often a very good idea to have a tail pointer as member in List. Especially if the list can hold many elements and you frequently add new elements.
Your code use this->some_member in many places where it's not needed. Avoiding that will make your code easier to read.
You never set the next pointer in Node.
Your code also has less-than-ideal indentation, uses raw pointers in places where you could use unique_ptr, doesn't initialise variables in constructors the C++ way, uses NULL instead of nullptr, and performs undefined behaviour by falling off the bottom without returning a value in a function declared to return a value (main(), specifically).
The problem is in your add() method.
Replace it with this
void add(int data){
if(this->head == NULL){ /*If head is null, init it and trav node*/
cout<<"inside the if block"<<endl;
this->head = new Node(data); /*init head*/
this->trav = this->head; /*point to head of list*/
} else{
cout <<"inside the else block"<<endl;
this->trav->next = new Node(data); /* add new elem to next of trav*/
this->trav = this->trav->next; /*move trav to next node i.e. reset */
}
}

Accessing struct within struct C++

I'm writing a C++ programm which has to work with linked list. But I can't figure out how can I access structure which is in another structure.
#include <cstddef>
#include "list.hpp"
using std::size_t;
struct list {
struct node {
double val;
node* prev;
node* next;
};
node* head = nullptr;
node* tail = nullptr;
size_t size = 0;
};
Can you explain me how it works? I have a method, but I don't know how I can use this structur in this method.
void push_back(list& l, double elem) {
node *new_node = new node(elem);
if (l.head==null) {
l.head = new_node;
}
node *curent = l.head;
while (curent) {
if (!curent->next) {
curent->next = new_node;
}
cur = cur->next;
}
}
Thank you.
in this code , you have a doubly linked list
i'll try to explain the code of the push_back function .
at the beginning we have void push_back(list& l, double elem) , l is your current LinkedList whish you want to add a new element to it in queue, elem is the value of your new element .
if (l.head==null) {
l.head = new_node;
}
if your linkedList is empty , we add the new element
exemple1 : empty LinkedList
if the linkedList is not empty
push back
this a simple code
node *curent = l.head; // the current node is pointed to the head of the LinkedList
while (curent->next != null) { // while current->next is not equal to null
curent=curent->next ; // step forward to the next node
}
curent->next =new_node ; // add the new node to the queue of the linkedList

Dummy Head Node Linked List

I'm trying to write an insert function for string values for a circular doubly linked list. I saw that creating a dummy node is beneficial in doing this so I can eliminate special cases like when the list is empty. The problem is I'm not finding alot of good information on dummy head nodes. I understand their purpose, but I don't understand how I create/implement it.
appreciate all the code examples guys, tried to figure it out on my own getting a little stuck though if someone can look at it.
#include <iostream>
#include <string>
using namespace std;
typedef string ListItemType;
struct node {
node * next;
node * prev;
ListItemType value;
};
node * head;
node * dummyHead = new node;
void insert(const ListItemType input, node * & within);
void main(){
insert("bob",dummyHead);
}
void insert( const ListItemType input, node * &ListHead){
node *newPtr = new node;
node *curr;
newPtr->value = input;
curr = ListHead->next; //point to first node;
while (curr != ListHead && input < curr->value){
curr = curr->next;
}
//insert the new node pointed to by the newPTr before
// the node pointed to by curr
newPtr->next = curr;
newPtr->prev = curr->prev;
curr->prev = newPtr;
newPtr->prev->next = newPtr;
}
For a circular doubly linked list, you can setup 1 sentinel node where both "next" and "prev" points to itself when list is empty. When list is not empty, sentinel->next points to first element and sentinel->prev points to last element. With this knowledge, your insert and remove function would look something like this.
This is very basic and your LinkedList and Node class maybe implemented differently. That is OK. The main thing is the insert() and remove() function implementation that shows how sentinel node(s) removes the need for checking for NULL values.
Hope this helps.
class DoublyLinkedList
{
Node *sentinel;
int size = 0;
public DoublyLinkedList() {
sentinel = new Node(null);
}
// Insert to the end of the list
public void insert(Node *node) {
// being the last node, point next to sentinel
node->next = sentinel;
// previous would be whatever sentinel->prev is pointing previously
node->prev = sentinel->prev;
// setup previous node->next to point to newly inserted node
node->prev->next = node;
// sentinel previous points to new current last node
sentinel->prev = node;
size++;
}
public Node* remove(int index) {
if(index<0 || index>=size) throw new NoSuchElementException();
Node *retval = sentinel->next;
while(index!=0) {
retval=retval->next;
index--;
}
retval->prev->next = retval->next;
retval->next->prev = retval->prev;
size--;
return retval;
}
}
class Node
{
friend class DoublyLinkedList;
string *value;
Node *next;
Node *prev;
public Node(string *value) {
this->value = value;
next = this;
prev = this;
}
public string* value() { return value; }
}
Why are you trying to use dummy node?
I hope you can handle it without a dummy node.
Eg:
void AddNode(Node node)
{
if(ptrHead == NULL)
{
ptrHead = node;
}else
{
Node* itr = ptrHead;
for(int i=1; i<listSize; i++)
{
itr = itr->next;
}
itr->next = node;
}
listSize++;
}
The above one is an example to handle the linked list without dummy node.
For a circular double linked list without a dummy node, the first node previous pointer points to the last node, and the last node next pointer points to the first node. The list itself has a head pointer to first node and optionally a tail pointer to last node and/or a count.
With a dummy node, the first node previous pointer points to the dummy node and the last node next pointer points to the dummy node. The dummy nodes pointers can point to the dummy node itself or be null.
The HP / Microsoft STL list function uses a dummy node as a list head node with the next pointer used as a head pointer to the first real node, and the previous pointer used as a tail pointer to the last real node.
#include <iostream>
#include <string>
using namespace std;
typedef string ElementType;
struct Node
{
Node(){}
Node(ElementType element, Node* prev = NULL, Node* next = NULL):element(element){}
ElementType element;
Node* prev;
Node* next;
};
class LinkList
{
public:
LinkList()
{
head = tail = dummyHead = new Node("Dummy Head", NULL, NULL);
dummyHead->next = dummyHead;
dummyHead->prev = dummyHead;
numberOfElement = 0;
}
void insert(ElementType element)
{
Node* temp = new Node(element, NULL, NULL);
if (0 == numberOfElement)
{
head = tail = temp;
head->prev = dummyHead;
dummyHead->next = head;
tail->next = dummyHead;
dummyHead->prev = tail;
}
else
{
tail->next = temp;
temp->prev = dummyHead->next;
temp->next = dummyHead;
dummyHead->next = temp;
tail = temp;
}
numberOfElement += 1;
}
int length() const { return numberOfElement; }
bool empty() const { return head == dummyHead; }
friend ostream& operator<< (ostream& out, const LinkList& List);
private:
Node* head;
Node* tail;
Node* dummyHead;
int numberOfElement;
};
ostream& operator<< (ostream& out, const LinkList& List)
{
Node* current = List.head;
while (current != List.dummyHead)
{
out<<current->element<<" ";
current = current->next;
}
out<<endl;
return out;
}
int main()
{
string arr[] = {"one", "two", "three", "four", "five"};
LinkList list;
int len = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < len; ++i)
{
list.insert(arr[i]);
}
cout<<list<<endl;
}
I think this code can help you. When you want to implement some data structure, you must have a clear blueprint about it.
Do the following inside the constructor
ptrHead = new Node();
listSize = 1;
if you have tail also,
ptrHead->next = ptrTail;
The above code will create dummy node.
Make sure you implementation should not affected by this dummy node.
eg:
int getSize()
{
return listSize-1;
}