Why is my print function not working? Linked list - c++

I am doing a class assignment, where I have to create a linked list representing a big number, but I cant get the print function to work.
This is the code:
Header
class List
{
private:
struct node
{
int data;
node* next;
};
node* head;
node* temp;
node* curr;
public:
List();
void addNode(std::string digits);
void printList();
};
Constructor
List::List()
{
head = NULL;
curr = NULL;
temp = NULL;
}
Function that creates the list
void List::addNode(string digits)
{
int o = 1;
int j = 0;
int i = 0;
node *n;
node *head;
node *temp;
//=================================================================================//
n = new node;
if (digits[0]=='-')
{
n -> data = -1;
head = n;
temp = n;
}
else
{
n -> data = 1;
head = n;
temp = n;
}
//================================================================================//
if ((head->data) == -1)
{
while (o < digits.length())
{
n = new node;
n->data = stoi(digits.substr(o,1));
temp -> next = n;
temp = temp -> next;
o++;
}
}
else
{
while(i < digits.length())
{
n = new node;
n->data = stoi(digits.substr(i,1));
temp -> next = n;
temp = temp -> next;
i++;
}
}
The print function I've been trying to implement, it gives no output (blank):
void List::printList()
{
node* curr = head;
while(curr != NULL)
{
cout<<curr -> data<<" ";
curr = curr -> next;
}
}
The list prints fine when I use this code in the addNode function:
if ((head -> data) == -1)
{
while(j < digits.length())
{
cout<<head -> data<<" ";
head = head -> next;
j++;
}
}
else
{
while(j<=digits.length())
{
cout<<head -> data<<" ";
head = head -> next;
j++;
}
}

For starters these data members
node* temp;
node* curr;
are redundant. Instead of them you can use similar local variables in member functions of the class if it is required.
The function addNode deals with the local variable head instead of the data member with the same name.
void List::addNode(string digits)
{
int o = 1;
int j = 0;
int i = 0;
node *n;
node *head;
//…
Also you forgot to set the data member next of the last node to nullptr.
If the member function will be called a second time then there will be memory leaks.
Calling the standard function std::stoi for one character
n->data = stoi(digits.substr(i,1));
is inefficient.
The class can look the following way as it is shown in the demonstrative program below. You will need to add other required member functions (as for example the copy constructor or destructor) yourself.
#include <iostream>
#include <string>
class List
{
private:
struct node
{
int data;
node *next;
} *head = nullptr;
public:
List() = default;
void addNode( const std::string &digits );
std::ostream & printList( std::ostream &os = std::cout ) const;
};
void List::addNode( const std::string &digits )
{
if ( !digits.empty() &&
!( digits.size() == 1 && ( digits[0] == '-' || digits[0] == '+') ) )
{
node **current = &head;
while ( *current )
{
node *tmp = *current;
*current = ( *current )->next;
delete tmp;
}
std::string::size_type i = 0;
*current = new node { digits[i] == '-' ? -1 : 1, nullptr };
if ( digits[i] == '-' || digits[i] == '+' ) ++i;
for ( ; i < digits.size(); i++ )
{
current = &( *current )->next;
*current = new node { digits[i] - '0', nullptr };
}
}
}
std::ostream & List::printList( std::ostream &os ) const
{
if ( head != nullptr )
{
if ( head->data == -1 ) os << '-';
for ( node *current = head->next; current != nullptr; current = current->next )
{
os << current->data;
}
}
return os;
}
int main()
{
List lst;
lst.addNode( "-123456789" );
lst.printList() << '\n';
lst.addNode( "987654321" );
lst.printList() << '\n';
return 0;
}
The program output is
-123456789
987654321

Related

Inserting a node before a specific node in a singly linked list

I have implemented a method to insert a new node before a specific node.
#ifndef FORWARD_SINGLY_LINKED_LIST_H
#define FORWARD_SINGLY_LINKED_LIST_H
#include <cstdlib>
#include <string.h>
#include <iostream>
namespace forward_singly_linked_list {
typedef struct Node {
std::string data;
struct Node *nextPointer;
} Node;
typedef Node *NodeP;
class LinkedList {
private:
int elementsCount;
Node *head;
public:
LinkedList() {
head = NULL;
elementsCount = 0;
}
int get_length() const
{
return elementsCount;
}
// ... ... ...
void add_before(std::string value, std::string before)
{
// empty an area in the memory, and
// save the address of the empty area in 'newNode'
Node *newNode = new Node();
// assign 'value' to the 'data' section of the
// area pointed by 'newNode'
newNode->data = value;
Node * copyOfHead = head;
if (copyOfHead == nullptr)
{
// the list is empty.
// there is no possibility to find 'before'.
// so, return.
return;
}
else
{
bool found = false;
Node * previousNode = nullptr;
while (copyOfHead != nullptr)
{
if (copyOfHead->data == before)
{
found = true;
break;
}
else
{
previousNode = copyOfHead;
copyOfHead = copyOfHead->nextPointer;
}
}
if (!found)
{
return;
}
if (previousNode != nullptr)
{
newNode->nextPointer = previousNode->nextPointer;
previousNode->nextPointer = newNode;
}
else
{
newNode->nextPointer = head;
head = newNode;
}
}
elementsCount++;
}
// ... ... ...
void print() {
Node *copyOfHead = head;
while (copyOfHead != NULL) {
std::cout << copyOfHead->data;
copyOfHead = copyOfHead->nextPointer;
}
std::cout<<"\n\n";
}
public:
static int Test() {
forward_singly_linked_list::LinkedList list;
list.print();
// list.add_at_tail("A");
// list.add_at_tail("B");
// list.add_at_tail("C");
list.print();
list.add_at("-XXX-", 1);
list.print();
return 0;
}
};
}
#endif
Personally, I don't like it because it uses an extra pointer previousNode. I have a feeling that it could be improved.
How can I improve the implementation?
The idea is about link the previous node to input/target node, then link the target/input node to current node.
Here is my code using simple loop index(i) instead of using extra pointer
void Sll::add_at_index( int ind , int value ){
Node *target = new Node( value ) ;
if( ind == 1){
target->next = head ;
head = target ;
}else if( ind == length){
tail->next = target ;
tail = target ;
tail->next = nullptr ;
}else{
Node *curr =head ;
for( int i = 1 ; i < length ; i++ ){
if( i+1 == ind){
Node *Mynext = curr->next ;
curr->next = target ;
target->next = Mynext ;
break ;
}
curr = curr->next ;
}
}
length++ ;
}
Become a two-star programmer:
void add_before(std::string value, std::string_view before) {
auto p = &head;
while (*p && (*p)->data != before)
p = &(*p)->nextPointer;
if (!*p)
return;
*p = new Node {
.data = std::move(value),
.nextPointer = *p,
};
++elementsCount;
}

I'm trying to code a binary search tree using c++ but the program takes only 2 inputs and stops

Notice the //, the program stops taking input and that is the main problem.
root->cand = data;
Here is the full code:
#include <bits/stdc++.h>
using namespace std;
struct node
{
int cand;
node *left;
node *right;
};
class candies
{
node *root;
public:
candies();
int add(int);
int check();
};
candies::candies()
{
root = NULL;
}
int candies::add(int data)
{
if (root == NULL)
{
root->cand = data; //code stops here
root->left = NULL;
root->right = NULL;
}
else
{
node *temp = root;
while (temp != NULL)
{
if (data < temp->cand)
{
temp = temp->left;
}
else
{
temp = temp->right;
}
}
temp = new node;
temp->cand = data;
temp->left = temp->right = NULL;
}
return 1;
}
int candies::check()
{
node *temp;
temp = root;
int data;
cin >> data;
while (temp != NULL)
{
if (temp->cand == data)
{
cout << "YES\n";
return 1;
}
else if (data < temp->cand)
temp = temp->left;
else if (data > temp->cand)
temp = temp->right;
}
cout << "NO\n";
return 0;
}
int main()
{
candies c;
int n;
cin >> n;
while (n--)
{
int data;
cin >> data;
c.add(data);
}
c.check();
}
The member function add is invalid and moreover has undefined behavior.
In this if statement
if (root == NULL)
{
root->cand = data; //code stops here
root->left = NULL;
root->right = NULL;
}
there is used a null-pointer to access memory.
In this else statement
else
{
node *temp = root;
while (temp != NULL)
{
if (data < temp->cand)
{
temp = temp->left;
}
else
{
temp = temp->right;
}
}
temp = new node;
temp->cand = data;
temp->left = temp->right = NULL;
}
the created node temp is not added to the tree. So the program has a memory leak.
The function can be written the following way. It is better to make its return type void. Otherwise the returned value 1 as in your function implementation does not make sense.
class candies
{
node *root;
public:
candies();
void add(int);
int check();
};
//...
void candies::add( int data )
{
node **current = &root;
while ( *current != nullptr )
{
if ( data < ( *current )->cand )
{
current = &( *current )->left;
}
else
{
current = &( *current )->right;
}
}
*current = new node { data, nullptr, nullptr };
}
You are first checking that root is NULL. If it is, you are changing its data. This is not good at all, and will cause a crash.
if (root == NULL)
{
root->cand = data; //code stops here
If root is NULL, you must create a root node first.
if ( root == nullptr ) {
root = new node;
root->cand = data;

Segmentation fault on insertion of more than one elements in the linked list in a sorted order

I tried to do an insertion sort in a linked list. When only one element is inserted(i.e the first one),it executes well and fine but for multiple elements it gives segmentation fault. Can anyone tell me where the problem is?
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
} *head = NULL;
node* createNode(int x)
{
node *temp = new node;
temp->data = x;
temp->next = NULL;
return temp;
}
void insertSort(int x)
{
if(head==NULL)
{
node *temp = createNode(x);
head = temp;
return;
}
node *temp = createNode(x);
node *prev = NULL;
node *curr = head;
bool inserted = false;
while(curr != NULL || !inserted)
{
if(temp->data < head->data)
{
temp->next = head;
head = temp;
inserted = true;
}
else
{
if(temp->data < curr->data)
{
prev->next = temp;
temp->next = curr;
inserted = true;
}
else
{
prev = curr;
curr = curr->next;
}
}
}
if(!inserted)
{
prev->next = temp;
}
}
void display()
{
node *p = head;
while(p != NULL)
{
cout<<p->data<<" ";
p = p->next;
}
}
For starters the function insertSort has redundant code
if(head==NULL)
{
node *temp = createNode(x);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
head = temp;
return;
}
node *temp = createNode(x);
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Secondly the condition in the while statement
while(curr != NULL || !inserted)
is incorrect. There must be
while(curr != NULL && !inserted)
In any case the function is too complicated. It can be written simpler.
Here is a demonstrative program that shows how the function can be implemented.
#include <iostream>
#include <cstdlib>
#include <ctime>
struct node
{
int data;
node* next;
} *head = nullptr;
node* createNode(int x)
{
return new node { x, nullptr };
}
std::ostream & display( std::ostream &os = std::cout )
{
for ( node *current = head; current != nullptr; current = current->next )
{
os << current->data << " - > ";
}
return os << "NULL";
}
void insertSort( int x )
{
node *new_node = createNode( x );
node **current = &head;
while ( *current != NULL && not ( x < ( *current )->data ) )
{
current = &( *current )->next;
}
new_node->next = *current;
*current = new_node;
}
int main()
{
const int N = 10;
std::srand( ( unsigned int )std::time( nullptr ) );
for ( int i = 0; i < N; i++ ) insertSort( std::rand() % N );
display() << '\n';
return 0;
}
The program output might look like
1 - > 2 - > 2 - > 3 - > 3 - > 3 - > 3 - > 8 - > 9 - > 9 - > NULL

How to insert an element in a doubly linked list and keep it sorted - c++

This an implementation of doubly linked list in c++
..I try to insert elements in my linked list
so I added the numbers 2 , 2 , 2 , 4 , 8 , 7
before printing , I call quicksort function
quick sort replaces the last element ( 7 ) , with the previous element (8)
..print function results in the output : 2,2,2,4 , 7 , 7
How can this code be modified to get the correct result
Here is my code..
#include <iostream>
using namespace std ;
template <class T>
class node
{
public :
T data;
node * next;
node * previous ;
};
template <class T>
class LinkedList
{
public:
string delimeter; // optional: just for printing
node<T>* addSorted(T v)
{
insert(T) ;
_quicksort(first , last) ;
}
void swap ( T* a, T* b )
{
T t = *a;
*a = *b;
*b = t;
}
node<T>* get(T v)
{
bool found = false ;
node<T> * Curr = first ;
while (!found)
{
if (Curr-> data == v )
found = true;
else
Curr = Curr-> next;
}
return Curr ;
}
// operator overloading for printing
friend ostream& operator<<(ostream& o, LinkedList<T> & c);
LinkedList()
{
node<T> * curr = new node<T> ;
first = last = curr;
first->next = last ;
first-> previous = NULL;
}
LinkedList(T value, int initial_size) // make n elements = value
{
node<T> * tempNode ;
node<T> * curr = new node<T> ;
first = last = curr;
first->previous =NULL;
for(int i = 0 ; i < initial_size ; i++)
{
tempNode = new node<T>;
tempNode->data = value ;
tempNode->next = first;
first->previous = tempNode;
first = tempNode ;
}
}
~LinkedList()
{
node<T> * current ;
while (first != last)
{
current = first ;
first = first-> next;
delete current;
}
delete last;
}
void print()
{
_quickSort(first, last);
//bubbleSort(first) ;
node<T> * Curr = first ;
while (Curr != NULL)
{
cout << Curr-> data <<"\t";
Curr = Curr-> next;
}
cout << endl;
}
int _size() // returns No. of elements
{
int NumOfelements = 0;
node<T> * temp = first ;
while (temp != last)
{
NumOfelements++;
temp = temp->next;
}
return NumOfelements ;
}
void insert(T value )
{
node<T> * temp = first ;
node<T> * dummy ;
node<T> * n = new node<T> ;
n->data = value;
last->data = value;
last->next = n;
n->previous = last;
last = n;
return;
while (temp != nullptr)
{
dummy = temp ;
temp = temp->next;
if(temp==last)
{
return;
}
}
dummy ->next = n ;
n -> previous = dummy;
n -> next = temp ;
temp-> previous =n;
// _quickSort(first, last) ;
//bubbleSort(first) ;
}
/* Considers last element as pivot, places the pivot element at its
correct position in sorted array, and places all smaller (smaller than
pivot) to left of pivot and all greater elements to right of pivot */
node<T>* pivot_partition(node<T> *f, node<T> *l)
{
// set pivot as l element
T x = l->data;
node<T> *i = f-> previous;
for (node<T> *j = f; j != l; j = j->next)
{
if (j->data <= x)
{
if (i == NULL)
i = f ;
else
i = i-> next ;
swap(&(i->data), &(j->data));
}
}
i = (i == NULL)? f : i->next; // Similar to i++
swap(&(i->data), &(l->data));
return i;
}
/* A recursive implementation of quicksort for linked list */
void _quickSort(node<T> *first, node<T> *last )
{
if (last != NULL && first != last && first != last->next)
{
node<T> *p = pivot_partition(first, last);
_quickSort(first, p->previous);
_quickSort(p->next, last);
}
}
T mylast () // even this returns 7 not 8
{
return last->data ;
}
private:
node<T> * first ;
node<T> * last ;
};
int main (){
LinkedList <int> l(2,3) ;
l.insert(4) ;
l.insert(8) ;
l.insert(7) ;
l.print() ;
return 0 ;
}
I fixed many small issues like styling and nullptr. But the big problems were in the constructor and in insert. The constructor created one element to much and initialized it with a default value. The insert method overwrote the last element. Next time please use a tool for code style before posting it here.
#include <iostream>
using namespace std;
template <class T>
class node {
public:
T data;
node* next;
node* previous;
};
template <class T>
class LinkedList {
public:
string delimeter;
node<T>* addSorted(T v) {
insert(v);
_quicksort(first , last);
}
void swap(T* a, T* b) {
T t = *a;
*a = *b;
*b = t;
}
node<T>* get(T v) {
bool found = false;
node<T>* Curr = first;
while (!found) {
if (Curr->data == v )
found = true;
else
Curr = Curr->next;
}
return Curr;
}
friend ostream& operator<<(ostream& o, LinkedList<T>& c);
LinkedList() {
node<T>* curr = new node<T>;
first = last = curr;
first->next = last ;
first->previous = nullptr;
}
LinkedList(T value, int initial_size) {
if (initial_size <= 0) return;
node<T>* tempNode;
node<T>* curr = new node<T>;
curr->data = value;
first = last = curr;
first->previous = nullptr;
for(int i = 0; i < initial_size - 1; i++) {
tempNode = new node<T>;
tempNode->data = value;
tempNode->next = first;
first->previous = tempNode;
first = tempNode;
}
}
~LinkedList() {
node<T>* current;
while (first != last) {
current = first;
first = first->next;
delete current;
}
delete last;
}
void print() {
_quickSort(first, last);
node<T>* Curr = first;
while (Curr != nullptr) {
cout << Curr->data << "\t";
Curr = Curr->next;
}
cout << endl;
}
int _size() {
int NumOfelements = 0;
node<T>* temp = first;
while (temp != last) {
NumOfelements++;
temp = temp->next;
}
return NumOfelements;
}
void insert(T value) {
node<T>* temp = first;
node<T>* dummy;
node<T>* n = new node<T>;
n->data = value;
last->next = n;
n->previous = last;
last = n;
return;
while (temp != nullptr) {
dummy = temp;
temp = temp->next;
if (temp == last) {
return;
}
}
dummy->next = n ;
n->previous = dummy;
n->next = temp;
temp->previous = n;
}
node<T>* pivot_partition(node<T>* f, node<T>* l) {
T x = l->data;
node<T>* i = f->previous;
for (node<T>* j = f; j != l; j = j->next) {
if (j->data <= x) {
if (i == nullptr)
i = f;
else
i = i->next;
swap(&(i->data), &(j->data));
}
}
i = (i == nullptr) ? f : i->next;
swap(&(i->data), &(l->data));
return i;
}
void _quickSort(node<T>* first, node<T>* last) {
if (last != nullptr && first != last && first != last->next) {
node<T>* p = pivot_partition(first, last);
_quickSort(first, p->previous);
_quickSort(p->next, last);
}
}
T mylast() {
return last->data;
}
private:
node<T>* first;
node<T>* last;
};
int main() {
LinkedList<int> l(2,3);
l.insert(4);
l.insert(8);
l.insert(7);
l.print();
return 0;
}

Adding a node to the end of a linked list

I've been trying to add an item to the end of a linked list. I think I have a handle on the concept but i'm having difficulty implementing the code. In particular, being able to traverse a linked list and find the tail. Here is what i have so far. I've been at this for a while trying different things. Any help would be appreciated.
##include <iostream>
using namespace std;
class node
{
public:
int data;
node *next;
};
class linkedList
{
private:
node* ptrHead;
node* ptrTail;
int size;
public:
linkedList(); //default constructor
void display();
void addFront(int);
void removeFront();
void addBack(int);
void removeBack();
};
//default constructor
linkedList::linkedList(){
size = 0;
ptrHead = ptrTail = NULL;
}
//display linked list
void linkedList::display(){
node* current = ptrHead;
while (current != NULL) {
cout << current->data << " "; //display current item
current = current->next; //move to next item
}
cout << size;
}
//add item to front of linked list
void linkedList::addFront(int addData){
node* n = new node;
n->next = ptrHead;
n->data = addData;
ptrHead = n;
size++;
}
//remove item from front of linked list
void linkedList::removeFront(){
node* n = ptrHead;
ptrHead = ptrHead->next;
delete n;
size--;
}
void linkedList::addBack(int addData){ ////work in progress
node* n = new node; //create new node
n->data = addData; //input data
n->next = NULL; //set node to point to NULL
if ( ptrTail == NULL ) // or if ( ptrTail == nullptr )
{
ptrHead = n;
ptrTail = n;
}
else
{
ptrTail->next = n;
ptrTail = n;
}
size++;
}
//this is the test code from my main function
int main()
{
//test code
linkedList list;
list.addFront(40);
list.addFront(30);
list.addFront(20);
list.addFront(10);
list.addFront(0);
list.addBack(50);
list.addBack(60);
list.display(); //50 60 7 (the 7 is the count/size of the linked list)
cout << endl;
}
for(int i=1; i<size; i++)
pCurrent = pCurrent->next;
pCurrent = n;
This will work. But you have to keep the size variable as real size of the Linked List.
Or If you want to add element in the end always, you can follows the below steps.
Keep a extra node tail and add the element to that.
if(head == NULL)
{
head = n;
tail = n;
}
else
{
tail->next = n;
tail = tail->next;
}
You did not show the definition of your linkedList.
So I can only suppose that it has data members ptrTail and ptrHead. In this case the function will look the following way
void linkedList::addBack(int addData)
{
node* n = new node; //create new node
n->data = addData; //input data
n->next = NULL; //set node to point to NULL
if ( ptrTail == NULL ) // or if ( ptrTail == nullptr )
{
ptrHead = n;
}
else
{
ptrTail->next = n;
}
ptrTail = n;
size++;
}
Function addFront can be defined the similar way
void linkedList::addFront(int addData)
{
node* n = new node; //create new node
n->data = addData; //input data
if ( ptrHead == NULL ) // or if ( ptrHead == nullptr )
{
ptrTail = n;
}
n->next = ptrHead;
ptrHead = n;
size++;
}
One more function
void linkedList::removeFront()
{
if ( ptrHead != NULL )
{
if ( ptrTail == ptrHead ) ptrTail = NULL;
node* n = ptrHead;
ptrHead = ptrHead->next;
delete n;
size--;
}
}
Try this
node* pCurrent = ptrHead;
if( pCurrent != NULL ){
//find tail
while (pCurrent->next != NULL)
pCurrent = pCurrent->next;
// add new node at end of tail
pCurrent->next = n;
} else {
pCurrent = n;
}
}