I'm having some issues when I call the print function for a linked list I created. I created three list objects, stored within them the ints 1,2,3 and then when I run the program, the data is printed out, followed by a hexadecimal number. Here is the output:
10x47e864
20x47e864
30x47e864
Process returned 0 (0x0) execution time : 0.026 s
Press any key to continue.
Here is the .h file:
#ifndef LIST_H
#define LIST_H
class List
{
public:
List();
void AddNode(int addData);
void DeleteNode(int delData);
void PrintList();
private:
typedef struct node{
int data;
node* next;
}* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
};
#endif // LIST_H
Here is the .cpp
#include "List.h"
#include <cstdlib>//for NULL const
#include <iostream>
using namespace std;
int main(){
List li;
li.AddNode(1);
li.AddNode(2);
li.AddNode(3);
li.PrintList();
}
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)//if a linked list exists
{
curr = head;
while(curr->next!=NULL){
//while not at end of list
curr=curr->next;//advances ptr until last node in list
}
curr->next=n;//make n point to last node;
}
else{//if list does not exist
head = n;
}
}
void List::DeleteNode(int delData){
nodePtr delPtr = NULL;
temp = head;
curr = head;
while(curr!=NULL && curr->data!= delData){
//to pass through list
temp = curr;
curr = curr->next;//traverse list until delData not found
}
if(curr==NULL)//passed through list, delData int not found
{
cout<<delData<<" was not in list\n";
delete delPtr;
}
else{
delPtr = curr;
curr == curr->next;//patching hole in list
delete delPtr;
cout<<"the value "<<delData<<" was deleted\n";
}
}
void List::PrintList(){
curr = head;
while(curr!=NULL){
cout<<curr->data<<cout<<endl;
curr=curr->next;//adv the curr ptr
}
}
Thank you all for the help!
You have an incorrect cout statement in the PrintList() remove the second cout from this line, i.e, change
cout<<curr->data<<cout<<endl;
to
cout << curr->data << endl;
Related
I tried appending multiple nodes in LinkedList c++ but it is just printing 1 node as I run it. Kindly review it, and help me fix it.
#include <iostream>
using namespace std;
//here is the node
struct Node {
int data;
struct Node* next;
};
// ------------here is linkedlist-----------
class LinkedList {
private:
Node* head;
public:
LinkedList()
{
head = NULL;
}
//----------- append function ------------
void appendNode(int d)
{
Node* newNode = new Node;
Node* nodePtr;
newNode->data = d;
newNode->next = NULL;
if (!head)
{
head = newNode;
}
else
{
nodePtr = head;
while (nodePtr->next)
{
nodePtr = nodePtr->next;
nodePtr->next = newNode;
}
}
}
//--------------- display function--------------
void display()
{
Node* nodePtr;
nodePtr = head;
while (nodePtr != NULL)
{
cout << nodePtr->data << endl;
nodePtr = nodePtr->next;
}
}
};
//-------------- main function -------------
int main()
{
LinkedList ll;
ll.appendNode(2);
ll.appendNode(21);
ll.appendNode(11);
ll.display();
}
Change your while loop from:
while (nodePtr->next)
{
nodePtr = nodePtr->next;
nodePtr->next = newNode;
...
}
to
while (nodePtr->next)
{
nodePtr = nodePtr->next;
...
}
nodePtr->next = newNode;
Also, in C++ use nullptr instead of NULL.
How do I make my program print the Linked List backwards? I got the printForward function working fine but the printBackwards function just doesn't seem to do anything. I think I'm on the right track but I'm a little stuck right now. I think the while loop isn't running because temp is NULL for some reason.
Any help would be great.
Thanks
List.h
#include <iostream>
using namespace std;
class LinkedList
{
private:
struct Node
{
int data;
Node * next;
Node * prev;
};
Node * head, *tail;
public:
LinkedList();
bool addAtBeginning(int val);
bool remove(int val);
void printForward() const;
void printBackward() const;
};
#endif
List.cpp
#include "List.h"
LinkedList::LinkedList()
{
head = NULL;
tail = NULL;
}
bool LinkedList::addAtBeginning(int val)
{
Node* temp;
temp = new Node;
temp->data = val;
temp->next = head;
head = temp;
return false;
}
bool LinkedList::remove(int val)
{
return false;
}
void LinkedList::printForward() const
{
Node* temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
void LinkedList::printBackward() const
{
Node* temp = tail;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->prev;
}
cout << endl;
}
app.cpp
#include "list.h"
int main()
{
LinkedList aList;
aList.addAtBeginning(3);
aList.addAtBeginning(10);
aList.addAtBeginning(1);
aList.addAtBeginning(7);
aList.addAtBeginning(9);
aList.addAtBeginning(12);
aList.printForward();
aList.printBackward();
system("pause");
return 0;
}
I find it a bit odd that you only have an addAtBeginning method, and no method to add at the end, the latter which I would consider to be normal use of a linked list. That being said, I think the immediate problem here is that you never assign the tail to anything. Try this version of addAtBeginning:
bool LinkedList::addAtBeginning(int val)
{
Node* temp;
temp = new Node;
temp->data = val;
temp->next = head;
if (head != NULL)
{
head->prev = temp;
}
if (head == NULL)
{
tail = temp;
}
head = temp;
return false;
`}
The logic here is that for the first addition to an empty list, we assign the head and tail to the initial node. Then, in subsequent additions, we add a new element to the head of the list, and then assign both the next and prev pointers, to link the new node in both directions. This should allow you to iterate the list backwards, starting with the tail.
Update addAtBeginning function with given:
bool LinkedList::addAtBeginning(int val)
{
Node* temp;
temp = new Node;
temp->data = val;
temp->prev = temp->next = NULL;
// If adding first node, then head is NULL.
// Then, set Head and Tail to this new added node
if(head == NULL){
// If this linked list is circular
temp->next = temp->prev = temp;
head = tail = temp;
}else{ // If we already have at least one node in the list
// If this linked list is circular
temp->prev = head->prev;
temp->next = head;
head->prev = temp;
head = temp;
}
return false;
}
But remember, if you copy this function with the parts that it makes this list circular, you will get an infinite loop. So, either change print function or dont copy that parts.
I am trying to display a doubly linked list backwards, but every time I try to run anything even remotely touching the "prev" pointer in the program I get a seg fault.
I've been trying to figure this out for about 4 hours now and I just can't seem to pin it down. I can't tell if the issue is coming from my print backwards function or from the actual prev pointers themselves.
#include <iostream>
#include "list.h"
LinkedList::LinkedList(){
head = NULL;
tail = NULL;
};
bool LinkedList::addAtBeginning(int val){
Node *upd8L = head; // This Node will update Last
Node *upd8 = head;; // This Node will update the previous pointers
Node *point = new Node(); // This Node will insert the new node at the beginning
point->data=val; // This sets the data in the new node
point->next=head; // This sets the next pointer to the same as head
head = point; // This sets the head to the new Node
while(upd8){
upd8 = upd8->next;
upd8->prev = upd8L;
upd8L=upd8L->next;
}
return true;
};
bool LinkedList::remove(int val){
Node *temp = head;
Node *trail = 0;
while(temp != NULL){
if(temp->data == val){
if(temp->next == head->next){
head = head->next;
}else{
trail->next = temp->next;
}
delete temp;
}
trail = temp;
temp = temp->next;
}
return true;
};
void LinkedList::printForward() const{
Node *temp;
temp = head;
while(temp){
cout << temp -> data << endl;
temp = temp->next;
}
};
void LinkedList::printBackward() const{
Node *temp = head;
while(temp){
temp = temp->next;
cout << temp->data << endl;
}
while(temp){
cout << temp->data;
cout << "Pop" << endl;
temp = temp-> prev;
}
};
If possible, I'd love an explanation as to what is bugging up my program rather than just a straight answer, I want to know what I'm doing wrong and why it's wrong.
Thank you!
edit
Here's list.h
#ifndef LIST_H
#define LIST_H
#include <iostream>
using namespace std;
class LinkedList
{
private:
struct Node
{
int data;
Node * next;
Node * prev;
};
Node * head, * tail;
public:
LinkedList();
bool addAtBeginning(int val);
bool remove(int val);
void printForward() const;
void printBackward() const;
};
#endif
The function printBackward() may cause a seg-fault in the last iteration of the loop. while(temp) means iterate till you get the element out of the list NULL. Then you assigning temp = temp->next where temp->next is NULL. Now when you are calling cout << temp->data << endl; you are trying to get data from NULL pointer. Try to change the order. First display the node data, then change the temp pointer. An example:
void LinkedList::printBackward() const{
Node *temp = head;
while(temp){
cout << temp->data << endl;
temp = temp->next;
}
What you are doing wrong is getting the data from a NULL pointer.
So, I figured it out after a ton of trial and error!
The biggest issue I was having that kept giving me segmentation errors was whenever I was removing elements of the list I was failing to update the "prev" part of the node, and as a result any time I tried to read the list backwards I was getting a seg error.
//put your implementation of LinkedList class here
#include <iostream>
#include "list.h"
LinkedList::LinkedList(){
head = NULL;
tail = NULL;
};
bool LinkedList::addAtBeginning(int val){
Node *point = new Node(); // This Node will insert the new node at the beginning
point->data=val; // This sets the data in the new node
point->next=head; // This sets the next pointer to the same as head
head = point; // This sets the head to the new Node
if(head->next != NULL){
Node *temp = head->next;
temp->prev = head;
}
return true;
};
bool LinkedList::remove(int val){
Node *temp = head->next;
Node *trail = head;
if(head->data ==val){
head = head->next;
head->prev = NULL;
delete trail;
}else{
while(temp != NULL){
if(temp->data == val){
if(temp->next != NULL){
trail->next = temp->next;
delete temp;
temp= temp->next;
temp->prev=trail;
}else{delete temp;
trail->next = NULL;
}
}
trail = temp;
temp = temp->next;
}
}
return true;
};
void LinkedList::printForward() const{
Node *temp;
temp = head;
while(temp){
cout << temp->data << endl;
temp = temp->next;
}
};
void LinkedList::printBackward() const{
Node *temp = head;
while(temp->next != NULL){
temp = temp->next;
}
while(temp->prev != NULL){
cout << temp->data << endl;
temp = temp->prev;
}
cout << head->data << endl;
};
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.
When I run my program, it works as intended, except the items in the list have no spaces between them when the displayList() function is called. I have 3 files. The main cpp file is ShoppingList.cpp. Then I have two other files for the linked list classification and implementation.
//ShoppingList.cpp
//Michael Hery
//COP 2001
//11/9/17
//Shopping List
#include <iostream>
#include <string>
#include "strList.h"
#include "strlist.cpp"
using namespace std;
int main()
{
//Define a NumberList object
StrList list;
string item;
string delItem;
int menuSelection;
//Ask the user how many items to
//put in the list
cout << "How many items would you like to put it the list? >> ";
cin >> menuSelection;
while (menuSelection < 1)
{
cout << "Please enter a valid number (greater than 0) >> ";
cin >> menuSelection;
}
for (int i = 0; i < menuSelection; i++)
{
cout << "Please enter item " << i + 1 << ": ";
cin >> item;
list.appendNode(item);
}
list.displayList();
cout << "Which item do you wish to delete from the list? >> ";
cin >> delItem;
while (delItem == "")
{
cout << "Please enter a valid item >> ";
cin >> delItem;
}
list.deleteNode(delItem);
list.displayList();
//Wait for user input to exit program
system("PAUSE");
return 0;
}
//strList.h
#ifndef STRLIST_H
#define STRLIST_H
#include <iostream>
#include <string>
namespace
{
class StrList
{
private:
struct ListNode
{
std::string value;
struct ListNode *next;
};
ListNode *head;
public:
//Constructor
StrList()
{
head = nullptr;
}
//Destructor
~StrList();
//Linked List Operations
void appendNode(std::string item);
void insertNode(std::string item);
void deleteNode(std::string item);
void displayList() const;
};
}
#endif
//strList.cpp
#ifndef STRLIST_CPP
#define STRLIST_CPP
#include <iostream>
#include <string>
#include "strList.h"
void StrList::appendNode(std::string item)
{
ListNode *newNode;
ListNode *nodePtr;
//Allocate a new node and store item there
newNode = new ListNode;
newNode->value = item;
newNode->next = nullptr;
//If there are no nodes in the list
//make newNode the first node
if (!head)
head = newNode;
else //Otherwise, insert newNode at the end
{
//Initialize nodePtr to head of the list
nodePtr = head;
//Find the last node in the list
while (nodePtr->next)
nodePtr = nodePtr->next;
//Insert newNode as the last node
nodePtr->next = newNode;
}
}
void StrList::insertNode(std::string item)
{
ListNode *newNode;
ListNode *nodePtr;
ListNode *previousNode = nullptr;
//Allocate a new node and store num there
newNode = new ListNode;
newNode->value = item;
//If there are no nodes in the list
//make newNode the first node
if (!head)
{
head = newNode;
newNode->next = nullptr;
}
else //Otherwise, insert newNode
{
//Position nodePtr at the head of list
nodePtr = head;
//Initialize previousNode to nullPtr
previousNode = nullptr;
//Skip all nodes whose values is less than num
while (nodePtr != nullptr && nodePtr->value < item)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
//If the new node is to be the 1st in the list,
//insert it before all the other nodes
if (previousNode == nullptr)
{
head = newNode;
newNode->next = nodePtr;
}
else //Otherwise insert after the previous node
{
previousNode->next = newNode;
newNode->next = nodePtr;
}
}
}
void StrList::deleteNode(std::string item)
{
ListNode *nodePtr; //To traverse the list
ListNode *previousNode = nullptr; //To point to the previous node
//If the list is empty, do nothing
if (!head)
return;
//Determine if the first node is the one
if (head->value == item)
{
nodePtr = head->next;
delete head;
head = nodePtr;
}
else
{
//Initialize nodePtr to head of list
nodePtr = head;
//Skip all nodes whose value member is
//not equal to num
while (nodePtr != nullptr && nodePtr->value != item)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
//If nodePtr is not at the end of the list,
//link the previous node to the node after
//nodePtr, then delete nodePtr
if (nodePtr)
{
previousNode->next = nodePtr->next;
delete nodePtr;
}
}
}
StrList::~StrList()
{
ListNode *nodePtr; //To traverse the list
ListNode *nextNode; //To point to the next node
//Position nodePtr at the head of the list
nodePtr = head;
//While nodePtr is not at the end of the list
while (nodePtr != nullptr)
{
//Save a pointer to the next node
nextNode = nodePtr->next;
//Delete the current node
delete nodePtr;
//Position nodePtr at the next node
nodePtr = nextNode;
}
}
void StrList::displayList() const
{
ListNode *display;
display = head;
std::cout << "**********************************" << std::endl;
std::cout << "**** Your Shopping List ****" << std::endl;
std::cout << "**********************************" << std::endl;
while (display)
{
std::cout << display->value;
display = display->next;
}
}
#endif
The problem lies in the displayList(); function towards the end of the file.
Add a separator for between your values.
char const* sep = "";
while (display)
{
std::cout << sep << display->value;
sep = " ";
display = display->next;
}