How do you print a linked list recursively in C++ - c++

I followed a guide on youtube by Paul Programming to create this linked list. Now I want to expand on it. I am trying to learn how to do recursive functions.
The error I am getting is that head isn't declared in main.cpp. I was wondering if anyone could shed some light on the issue I am having.
Code:
main.cpp:
#include <cstdlib>
#include <iostream>
#include "linkedlist.h"
using namespace std;
int main(int argc, char** argv)
{
List list;
list.addNode(1);
list.addNode(2);
list.addNode(3);
list.addNode(4);
list.addNode(5);
cout << "Printing list" << endl;
list.printList();
cout << "Printing list recursively" << endl;
list.printListRecur(head);
return 0;
}
linkedlist.h:
#ifndef _LINKEDLISTHEADER_
#define _LINKEDLISTHEADER_
class List{
private:
typedef struct node{
int data;
node* next;
}* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
public:
List();
void addNode(int addData);
void deleteNode(int delData);
void printList();
void printListRecur(nodePtr head);
};
#endif
linkedlist.cpp:
#include <iostream>
#include <cstdlib>
#include "linkedlist.h"
using namespace std;
List::List()
{
head = NULL;
curr = NULL;
temp = NULL;
}
void List::addNode(int addData)
{
nodePtr n = new node;
n->next = NULL;
n->data = addData;
if(head != NULL)
{
curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
curr->next = n;
}
else
{
head = n;
}
}
void List::deleteNode(int delData)
{
nodePtr delPtr = NULL;
temp = head;
curr = head;
while(curr != NULL && curr->data != delData)
{
temp = curr;
curr = curr->next;
}
if(curr == NULL)
{
cout << delData << " was not in the list." << endl;
delete delPtr;
}
else
{
delPtr = curr;
curr = curr->next;
temp->next = curr;
if(delPtr == head)
{
head = head->next;
temp = NULL;
}
delete delPtr;
cout << "The value " << delData << " was deleted" << endl;
}
}
void List::printList()
{
curr = head;
while(curr != NULL)
{
cout << curr->data << endl;
curr = curr->next;
}
}
void List::printListRecur(nodePtr head)
{
if(head == NULL)
{
return;
}
cout << head->data <<endl;
printListRecur(head->next);
}

To use recursion, you need to have the passed and returned data to be the same type, i.e, the function should consume a Node and then return a Node, recursion call will not be formed if function consumes a List but return a Node.
From my understanding, List can be a wrapper class for Node. To give you a very simple example:
class List {
struct Node {
int data;
Node *next;
void print();
...
};
Node *head;
public:
void print();
...
};
void List::Node::print() {
std::cout << data << endl;
if (next) next->print();
}
void List::print() {
if (head) head->print();
}
List will have all the interface methods that a client might need, but the actual work is done by the methods of Node, if you want to go with the recursion way (iteration is more frequently used since recursion consumes much more memory space).

head is a (private) member of the List class. There is no variable named head in main(), that is why the compiler is complaining.
I would suggest either:
adding a method to List to return the head node, then you can pass it to printListRecur():
class List {
...
public:
...
nodePtr getHead() { return head; }
...
void printListRecur(nodePtr node);
...
};
list.printListRecur(list.getHead());
remove the input parameter from printListRecur(), and then define a private method for printListRecur() to call recursively, passing it the head node:
class List {
private:
...
void internalPrintListRecur(nodePtr node);
...
public:
...
void printListRecur();
...
};
void List::internalPrintListRecur(nodePtr node)
{
if (node)
{
cout << node->data <<endl;
internalPrintListRecur(node->next);
}
}
void List::printListRecur()
{
internalPrintListRecur(head);
}
But, as others stated in comments, iterating through the list recursively is not usually desired due to the fact that data may have to be pushed onto the call stack on each iteration. Using recursion to iterate a large list is subject to a stack overflow error, unless the code is written in a way that allows the compiler to apply tail call optimization to avoid the stack error.
In this example, it is better to just use a simple iterative loop instead, like your printList() is already using. Don't use recursion.

Related

C++ linked list implementation, goes to infinite loop while traversing. Guessing something is wrong with the contructors

I'm new to C++. I'm trying to implement a linked list. The output goes to an infinite loop when the traverse function is called(output shown at the bottom). Had no errors when I used 'new' in the insertNodeAtEnd function instead of contructors, but I read up that it's generally not a good practice in C++ and it's better to get accustomed to using constructors.
What am I doing wrong?
#include <iostream>
struct Node
{
int data;
Node *next;
Node(int data)
{
this->data = data;
this->next = NULL;
}
~Node() {}
};
class LinkedList
{
public:
LinkedList()
{
std::cout << "Linked list created \n";
}
static Node *head;
static Node *tail;
static int numberOfNodes;
static int getNumberOfNodes()
{
return numberOfNodes;
}
static void insertNodeAtEnd(int data)
{
Node newNode(data);
if (head == NULL)
{
head = tail = &newNode;
return;
}
tail->next = &newNode;
tail = &newNode;
numberOfNodes++;
return;
}
static void traverse()
{
if (numberOfNodes == 0)
{
std::cout << "Linked list is empty \n";
}
Node *curr = head;
while (curr != NULL)
{
std::cout << curr->data << std::endl;
curr = curr->next;
}
return;
}
~LinkedList()
{
std::cout << "Linked list destroyed \n";
}
};
Node *LinkedList::head = NULL;
Node *LinkedList::tail = NULL;
int LinkedList::numberOfNodes = 0;
int main()
{
LinkedList linkedlist;
linkedlist.insertNodeAtEnd(40);
linkedlist.insertNodeAtEnd(50);
linkedlist.insertNodeAtEnd(60);
linkedlist.insertNodeAtEnd(70);
linkedlist.traverse();
}
And here's the output. (Infinite loop, had to terminate in the console.)
Linked list created
70
70
70
70
70
70
70
Here:
static void insertNodeAtEnd(int data)
{
Node newNode(data);
if (head == NULL)
{
head = tail = &newNode;
return;
}
tail->next = &newNode;
tail = &newNode;
numberOfNodes++;
return;
}
newNode is a function local variable. Its lifetimes ends when the function returns. The pointers you store are dangling. When you dereference them later you invoke undefined behavior.
To dynamically allocate the nodes, such that they persist you can do
Node* newNode = new Node(data);
It is not clear why all members of LinkedList are declared static. The effect is basically that you can only have one linked list, because a second one would share all members.
I got it to work by instead creating a new Node rather than directly instantiating one. What happens in your version is that the created node is destroyed while by creating a new one it will remain valid until explicitly deleted
#include <iostream>
struct Node
{
int data;
Node *next;
Node(int data)
{
this->data = data;
this->next = NULL;
}
~Node() {}
};
class LinkedList
{
public:
LinkedList()
{
std::cout << "Linked list created \n";
}
static Node *head;
static Node *tail;
static int numberOfNodes;
static int getNumberOfNodes()
{
return numberOfNodes;
}
static void insertNodeAtEnd(int data)
{
Node* newNode = new Node(data);
if (head == NULL)
{
head = tail = newNode;
return;
}
tail->next = newNode;
tail = newNode;
numberOfNodes++;
return;
}
static void traverse()
{
if (numberOfNodes == 0)
{
std::cout << "Linked list is empty \n";
}
Node *curr = head;
while (curr != NULL)
{
std::cout << curr->data << std::endl;
curr = curr->next;
}
return;
}
~LinkedList()
{
std::cout << "Linked list destroyed \n";
}
};
Node *LinkedList::head = NULL;
Node *LinkedList::tail = NULL;
int LinkedList::numberOfNodes = 0;
int main()
{
LinkedList linkedlist;
linkedlist.insertNodeAtEnd(40);
linkedlist.insertNodeAtEnd(50);
linkedlist.insertNodeAtEnd(60);
linkedlist.insertNodeAtEnd(70);
linkedlist.traverse();
}

How to fix memory leak with linked list?

Hi I have the following code, and keep getting memory leaks, can someone help me fix this please, I've been at this for hours but cant seem to find why there is a memory leak, I am new with nodes, I think the problem is with the destructor, but can't seem to pin point exactly what, please help!
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node* next;
};
class LinkedList {
public:
LinkedList() { // constructor
head = NULL;
}
~LinkedList(); // destructor
void insert(int val);
void display();
private:
Node* head;
};
LinkedList::~LinkedList() { delete head; }
// function to add node to a list
void LinkedList::insert(int val) {
Node* newnode = new Node();
newnode->data = val;
newnode->next = NULL;
if (head == NULL) {
head = newnode;
} else {
Node* temp = head; // head is not NULL
while (temp->next != NULL) {
temp = temp->next; // go to end of list
}
temp->next = newnode; // linking to newnode
}
}
void LinkedList::display() {
if (head == NULL) {
cout << "List is empty!" << endl;
} else {
Node* temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
}
int main() {
LinkedList* list = new LinkedList();
list->insert(999);
list->insert(200);
list->insert(300);
list->insert(700);
list->insert(500);
cout << "Linked List data" << endl;
list->display();
delete list;
return 0;
}
An alternative to Abel's answer with the Node-destroying Nodes:
LinkedList::~LinkedList()
{
while (head)
{
Node * temp = head;
head = head->next;
delete temp;
}
}
The LinkedList loops removes, and deletes the first Node until there are no Nodes left.
Why do I prefer this approach? Two reasons:
Ownership. Who is responsible for managing the nodes? With the loop, managing the Nodes is entirely in the hands of LinkedList. If Nodes can destroy one another, management is split between LinkedList and Node, and both owners need to remain in agreement about the state of the managed resource. Maintaining this agreement is tricky and tricky means more code you can get wrong. For example, if LinkedList isn't careful when removing a single Node from the list, that Node will recursively destroy the rest of the list. Ooops.
The second reason is recursion. If the list gets too long, the program will exhaust its automatic storage (Usually causing a Stack Overflow) and become unstable. You've limited the size of the list you can handle unnecessarily and the only way you'll know you've exceeded the limit is when the program fails.
The access violation the Asker has been experiencing I have been unable to reproduce. I may have accidentally fixed it.
I don't think you want destructing a node to delete the entire list. You could but I think each node should be independent of the others - the linked list class is where list level things should happen.
Also, you don't want the destructor to contain the code to clear the list because you may want to clear the list at some arbitrary point - so the linked list should have a clear function that is called from the linked list destructor and can be called from other places too.
So the destructor would call this function to clear the list:
void LinkedList::clear() {
Node* next;
Node* temp = head;
while (temp != NULL) {
next = temp->next;
delete temp;
temp = next;
}
head = NULL;
}
The whole code would be:
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node* next;
Node() : data(0), next(NULL) {
cout << "Constructed default node\n";
}
Node(int data) : data(data), next(NULL) {
cout << "Constructed node: " << data << "\n";
}
~Node() {
cout << "Destructed node: " << data << "\n";
}
};
class LinkedList{
public:
LinkedList() { // constructor
head = NULL;
}
~LinkedList() {
clear();
}
void insert(int val);
void display();
void clear();
private:
Node* head;
};
// function to add node to a list
void LinkedList::insert(int val) {
Node* newnode = new Node(val);
if (head == NULL) {
head = newnode;
}
else {
Node* temp = head; // head is not NULL
while (temp->next != NULL) {
temp = temp->next; // go to end of list
}
temp->next = newnode; // linking to newnode
}
}
// function to delete the entire list
void LinkedList::clear() {
Node* next;
Node* temp = head;
while (temp != NULL) {
next = temp->next;
delete temp;
temp = next;
}
head = NULL;
}
// function to display the entire list
void LinkedList::display() {
if (head == NULL) {
cout << "List is empty!" << endl;
}
else {
Node* temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
}
int main() {
LinkedList list;
cout << "Creating List\n";
list.insert(999);
list.insert(200);
list.insert(300);
list.insert(700);
list.insert(500);
cout << "Linked List data:\n";
list.display();
cout << "Clearing list\n";
list.clear();
cout << "Creating List\n";
list.insert(400);
list.insert(600);
cout << "Linked List data:\n";
list.display();
cout << "NOT clearing list (should happen automatically\n";
return 0;
}
You can try it here: https://onlinegdb.com/HJlOT1ngqP
The output:
Creating List
Constructed node: 999
Constructed node: 200
Constructed node: 300
Constructed node: 700
Constructed node: 500
Linked List data:
999 200 300 700 500
Clearing list
Destructed node: 999
Destructed node: 200
Destructed node: 300
Destructed node: 700
Destructed node: 500
Creating List
Constructed node: 400
Constructed node: 600
Linked List data:
400 600
NOT clearing list (should happen automatically
Destructed node: 400
Destructed node: 600

C++ Linked list only print the first 3 nodes

When you run the code, it won't print anything unless when you run it with 3 appends. Why is that? Inside the code, I added cout statement to check if it ran and when I appended 4 things to the linked list, it only ran once in the append function. But when I ran it with only 3 things appended to the list, it displayed the cout statement 3x.
main.cpp:
#include <iostream>
#include "node.h"
using namespace std;
int main()
{
LL list;
list.append("jack","2");
list.append("jack","1");
list.append("jack","3");
list.append("jack","4");
//list.insertatBegin("notjack","0");
list.print();
}
node.cpp:
#include <iostream>
using namespace std;
#include "node.h"
LL::LL()
{
head = nullptr;
}
void LL::append(string pName,string phone)
{
Node *nodePtr;
if (head == nullptr)
{
head = new Node;
head->name = pName;
head->phoneNumber = phone;
head->next = nullptr;
}
else
{
nodePtr = head;
while(nodePtr->next !=nullptr)
{
nodePtr = nodePtr->next;
}
nodePtr->next = new Node;
nodePtr->next->name = pName;
nodePtr->next->phoneNumber = phone;
nodePtr->next->next = nullptr;
}
}
void LL::print()
{
//cout << "ran" <<endl;
Node *nodePtr;
nodePtr = head;
while (nodePtr == nullptr)
{
cout << nodePtr ->name << " " << nodePtr->phoneNumber <<endl;
nodePtr = nodePtr->next;
}
}
node.h:
#ifndef NODE_H
#define NODE_H
#include <iostream>
using namespace std;
class Node
{
public:
string name; //data
string phoneNumber;
Node* next; //pointer to next
};
class LL
{
private:
Node* head; // list header
public:
LL();
void append(string pName,string phone);
void insertatBegin(string pName,string phone);
void print();
};
#endif
There are 2 problems with your code:
append() has undefined behavior, because newNode is uninitialized. Its value is indeterminate, causing it to point at random memory. You are not pointing it to a valid new'ed instance of Node before trying to populate it.
print() is not looping through the list at all.
Try this:
void LL::append(string pName,string phone)
{
Node *newNode = new Node; // <-- notice 'new'!
// these assignments really should be handled by a constructor...
newNode->name = pName;
newNode->phoneNumber = phone;
newNode->next = nullptr;
if (head == nullptr)
// better: if (!head)
{
cout << "it ran" <<endl;
head = newNode;
}
else
{
cout << "it ran2" <<endl;
Node *nodePtr = head;
while (nodePtr->next != nullptr)
// better: while (nodePtr->next)
{
nodePtr = nodePtr->next;
}
nodePtr->next = newNode;
}
}
void LL::print()
{
//cout << "ran" <<endl;
Node *nodePtr = head;
while (nodePtr != nullptr) // <-- '!=', not '=='
// better: while (nodePtr)
{
cout << nodePtr ->name << " " << nodePtr->phoneNumber << endl;
nodePtr = nodePtr->next;
}
}
That said, append() can be simplified a bit more:
class Node
{
public:
string name; //data
string phoneNumber;
Node* next = nullptr; //pointer to next
Node(string pName, string phone) : name(pName), phoneNumber(phone) {}
};
void LL::append(string pName,string phone)
{
Node *newNode = new Node(pName, phone);
Node **nodePtr = &head;
while (*nodePtr)
{
nodePtr = &((*nodePtr)->next);
}
*nodePtr = newNode;
// Alternatively:
/*
Node **nodePtr = &head;
while (*nodePtr)
{
nodePtr = &((*nodePtr)->next);
}
*nodePtr = new Node(pName, phone);
*/
}
For starters your newNode pointer does not point to anything and you are assigning to uninitialized variables name, phonenumber and next.
Node *nodePtr;
newNode->name = pName;
newNode->phoneNumber = phone;
newNode->next = nullptr;

Can't assign to object in linked list

Head and tail are getting populated, and print out the values, but nodePtr stays empty for some reason. When I debug in VS2015, head and tail number is getting populated, while field this stays empty
Here's Linked_List
#ifndef _LINKED_LIST_
#define _LINKED_LIST_
#include <iostream>
class LinkedList
{
public:
struct Node
{
int number;
Node * next;
Node() : number(NULL), next(NULL) {};
Node(int number_, Node * next_ = NULL)
{
number = number_;
next = next_;
}
}*head, *tail, *nodePtr;
LinkedList();
~LinkedList();
void add(int num);
friend std::ostream& operator<<(std::ostream& out, LinkedList& list);
private:
int size;
};
#endif // _LINKED_LIST_
Implementation file
include "linkedlist.h"
#include <iostream>
using namespace std;
LinkedList::LinkedList() : head(NULL), tail(NULL), nodePtr(NULL)
{
nodePtr = new Node();
}
LinkedList::~LinkedList()
{
Node * curr, *temp;
curr = head;
temp = head;
while (curr != NULL)
{
curr = curr->next;
delete temp;
temp = curr;
}
}
void LinkedList::add(int num)
{
Node * newNode = new Node();
newNode->number = num;
cout << newNode->number;
if (head == NULL)
{
head = newNode;
tail = newNode;
size++;
}
else
{
tail->next = newNode;
newNode->next = NULL;
tail = newNode;
size++;
}
//cout << nodePtr->number; //empty, or some random
//just some tests
cout << head->number;
if (head->next != NULL)
{
cout << head->next->number;
}
cout << tail->number;
cout << endl;
}
std::ostream & operator<<(std::ostream & out, LinkedList & list)
{
out << list.nodePtr->number << endl;
return out;
}
Main.cpp
#include <iostream>
#include "linkedlist.h"
using namespace std;
int main()
{
int num;
LinkedList list;
list.add(1);
list.add(2);
list.add(3);
cout << list;
cout << "Press 1: ";
cin >> num;
return 0;
}
You're missing a fundamental concept here. nodePtr is not some magical node that knows about all your other nodes, or knows about linked lists, or can be used to print all their numbers.
When you do this:
out << list.nodePtr->number << endl;
All you are doing is outputting the value that you initialized when you allocated a new Node and stored a pointer in nodePtr:
nodePtr = new Node();
That called the default constructor for Node which set nodePtr->number to zero. (side-note, you initialized it to NULL, not 0 -- you should not mix integer types with pointer types, so change it to initialize the value to 0).
Its value stays 0 because you never modify it. And nodePtr always points at that single node because you never modified nodePtr.
What you're actually wanting to do is print out your list. Let me suggest the normal way to do this, by starting at head and following the node linkages:
std::ostream & operator<<(std::ostream & out, const LinkedList & list)
{
for( Node *node = list.head; node != nullptr; node = node->next )
{
out << node->number << std::endl;
}
return out;
}
And finally, I suggest you remove nodePtr from your class completely.
You only use nodePtr in the constructor, you never change it's values.

Linked list class

The purpose of my program is to read in data from a file and build a linked list with this data and then deallocate all the nodes used.
the program also needs to print out the address of nodes after they are created and then after that they are deleted
#include <iostream>
#include <string>
#include <fstream>
#include "BigHero.h"
using namespace std;
// Linked List Struct
struct Node{
BigHero data;
Node* Next;
};
// Funtion Prototypes
int countHeros(string,int&);
void createList(BigHero,int,Node*&,Node*&,Node*&);
void printList(Node*,Node*,Node*);
void deallocateList(Node*&,Node*&,Node*&);
int main()
{
// Program Variables
Node* head;
Node* currentPtr;
Node* newNodePtr;
string Filename = "ola5party.dat"; // File string varible
int charNumber = 0; // variable to hold number of Heroes
int i = 0; // Loop control varible
countHeros(Filename,charNumber); // Function call used to count number of Heros
ifstream inFile;
inFile.open(Filename.c_str());
if(!inFile){
cout << "Error in opening file" << endl;
return 0;
}
BigHero Hero;
while(inFile)
{
inFile >> Hero;
createList(Hero,charNumber,head,currentPtr,newNodePtr);
}
printList(head,currentPtr,newNodePtr);
deallocateList(head,currentPtr,newNodePtr);
inFile.close();
return 0;
}
int countHeros(string Filename,int& charNumber)
{
ifstream inFile;
inFile.open(Filename.c_str());
string aLineStr;
while (getline(inFile, aLineStr))
{
if (!aLineStr.empty())
charNumber++;
}
inFile.close();
return charNumber;
}
void createList(BigHero Hero, int charNumber,Node*& head, Node*& currentPtr, Node*& newNodePtr)
{
head = new Node;
head->data =Hero;
currentPtr = head;
newNodePtr = new Node;
cout << "Allocated # " << newNodePtr << endl;
newNodePtr->data = Hero;
currentPtr->Next = newNodePtr;
currentPtr = newNodePtr;
}
void printList(Node* head, Node* currentPtr, Node* newNodePtr)
{
if(head != NULL)
{
currentPtr = head;
while(currentPtr->Next != NULL)
{
cout << currentPtr->data << endl;
currentPtr = currentPtr->Next;
}
}
}
void deallocateList(Node*& head ,Node*& currentPtr,Node*& newNodePtr)
{
if( head != NULL)
{
currentPtr = head;
while( head -> Next != NULL)
{
head = head->Next;
cout << "Deleting # " << head << endl;
delete currentPtr;
currentPtr = head;
}
delete head;
head = NULL;
currentPtr = NULL;
}
}
the program like this runs without errors, but here is the problem it will input all the information required but since i only have one variable hero class it is constantly replacing the information.
i tried to make a class array (example hero[i]) but cant seem to get it right and am not even sure if that is the solution. Everything is fine but i cant get the desired number of class object and i always end up with one class
this is my desired output but i only get one class object
Allocated#0x8722178
Allocated#0x87221d0
Allocated#0x8722210
Allocated#0x8722230
Allocated#0x8722288
Allocated#0x87222c8
Hero:MacWarrior­Level134,(34,16,48)­Exp:13425
Hero:LinuxMage­Level149,(24,54,21)­Exp:14926
Hero:PCBard­Level122,(18,32,17)­Exp:12221
Hero:PythonThief­Level90,(24,18,61)­Exp:9001
Hero:CplusPaladin­Level159,(31,38,29)­Exp:15925
Deleting#0x8722178
Deleting#0x87221d0
Deleting#0x8722210
Deleting#0x8722230
Deleting#0x8722288
Deleting#0x87222c8
It seems you have misunderstood the basic idea behind a link listed. You are not supposed to overwrite head again and again when adding element. head shall only be changed when the list is empty.
Try something like this:
struct Node
{
BigHero data;
Node* next;
};
void addNewNode(Node*& head, ....)
{
if (head == nullptr)
{
// List empty so add new node as head
head = new Node;
head->next = nullptr;
return;
}
// Find last element in list (performance can be improved with a tail*)
Node* temp = head;
while (temp->next != nullptr) temp = temp->next;
// Add new element to end of list
temp->next = new Node;
temp->next->next = nullptr
return;
}
int main()
{
Node* head = nullptr;
addNewNode(head, ....);
return 0;
}
For performance it is often good to have a tail-pointer also.
Further you should not define head in main() but make a class/struct for it and put the relevant functions in the class. Like:
struct Node
{
BigHero data;
Node* next;
};
class ListOfNode
{
public:
ListOfNode() : head(nullptr), size(0) {}
~ListOfNode()
{
// Delete all nodes
}
void addNewNode(....)
{
// ....
++size;
}
size_t size() { return size; }
private:
Node* head; // Optional: Add a tail* for better performance
size_t size;
};
int main()
{
ListOfNode list;
list.addNewNode(....);
cout << list.size() << endl;
return 0;
}