It's been a week since i started learning about linked list and i only managed to learn about singly linked list. So today i implemented the linked list which i learned in c++ and while i tried to run it the code goes into an infinite loop of some random numbers. I tried debugging the code but i coudn't find whats so ever is wrong with the code. The code is below. Help is appreciated.Thanks
#include <iostream>
using namespace std;
struct node{
int data;
node * next;
};
class singly{
private:
node * head,*tail;
public:
singly(){
head=NULL;
tail=NULL;
}
void createNode(int value){
node * temp = new node;
temp->data=value;
temp->next=NULL;
if(head==NULL){
head=temp;
tail=temp;
temp=NULL;
}
else{
tail->next=temp;
tail=temp;
}
}
void display(){
node * temp = new node;
head=temp;
while(temp!=NULL){
cout << temp->data << "\t" << endl;
temp->next=temp;
}
}
void insert_end(int value){
node*newnode = new node;
node*temp = new node;
newnode->data=value;
newnode->next=NULL;
temp=head;
while(temp->next!=NULL){
temp = temp->next;
}
temp->next=newnode;
}
void delete_node(){
node*current = new node;
node*previous = new node;
current = head;
while(current->next!=NULL){
previous=current;
current=current->next;
}
tail=previous;
previous->next=NULL;
delete current;
}
};
int main(){
singly lists;
lists.createNode(32);
lists.createNode(654);
lists.createNode(34);
lists.createNode(234);
cout<<"\n--------------------------------------------------\n";
cout<<"---------------Displaying All nodes---------------";
cout<<"\n--------------------------------------------------\n";
lists.display();
cout<<"\n--------------------------------------------------\n";
cout<<"-----------------Inserting At End-----------------";
cout<<"\n--------------------------------------------------\n";
lists.createNode(55);
lists.display();
cout<<"\n--------------------------------------------------\n";
cout<<"-----------------Deleing At End-------------------";
cout<<"\n--------------------------------------------------\n";
lists.delete_node();
lists.display();
}
The member function display does not make sense.
It overwtites the data member head with uninitialized newly created temp.
node * temp = new node;
head=temp;
so the function invokes undefined behavior.
The function can look like
void display()
{
for ( node * temp = head; temp != nullptr; temp = temp->next )
{
cout << temp->data << "\t";
}
}
Or it is better to define it the following way
std::ostream & display( std::ostream &os = std::cout )
{
for ( node * temp = head; temp != nullptr; temp = temp->next )
{
os << temp->data << "\t";
}
return os;
}
The data member insert_end is also wrong. It does not take into account that head and tail can be equalto nullptr and does not change them.
The function can be defined the following way
void insert_end(int value)
{
node *newnode = new node { value, nullptr };
if ( tail == nullptr )
{
head = tail = newnode;
}
else
{
tail = tail->next = newnode;
}
}
The member function delete_node firstly does not make sense for a singly-linked list and again is wrong and invokes undefined behavior. The function should remove the first node from the list.
Nevertheless if you want to remove the last node from the list then the function can look like
void delete_node()
{
if ( head != nullptr )
{
tail = nullptr;
node *current = head;
while ( current->next )
{
tail = current;
current = current->next;
}
if ( tail == nullptr )
{
head = tail;
}
else
{
tail->next = nullptr;
}
delete current;
}
}
For starters, display() is wrong. You want the update to be temp = temp->next; and it can also be initialized as node * temp = head hence not requiring the second line.
Your delete_node() can be re-written to:
if (head->next == NULL) // handles the case that it consists of 1 element
{
delete head;
head = NULL;
}
else
{
node *nextToEnd = head;
node *end = head->next;
while (end->next != NULL)
{
nextToEnd = end;
end = end->next;
}
delete end;
nextToEnd->next = NULL;
}
As stated in the comments, review the use of the new keyword
Related
Fairly new to implementing stacks and was looking for some possible feedback. My code gives the correct output, but I know this doesn't always mean it is working as it is suppose to. I chose to take the approach that implementing a stack using a linked list was essentially the same as your regular linked list implementation except that all the operations are done on the end of the list. I was not too sure if this approach was correct, but it followed the first in last out approach, and has the same complexity for access & search (O(n)) and insertion and deletion O(1). Such as pop() would just be deleting a node from the end of the linked list, and push() would just be appending a node to the end of the linked list. I have pasted my code below with comments within them explaining what I am doing or trying to do (if it is incorrect).
#include <iostream>
struct Node{
int data;
Node* next;
};
bool isEmpty(Node** stack){
if(*stack == NULL){
return true;
}
return false;
}
void push(Node** stack, int data){
Node* new_node = new Node();
new_node->data = data;
new_node->next=NULL;
// stack similar to "head"
if(isEmpty(&(*stack))){
*stack = new_node;
return;
}
Node* temp = *stack;
while(temp->next != NULL){
temp = temp->next;
}
temp->next = new_node;
}
void pop(Node** stack){
// checking if stack is empty
if(isEmpty(&(*stack))){
std::cout<<"Stack underflow"<<std::endl;
return;
}
Node* deleteMe = *stack;
// if at the first element in the stack
if(deleteMe->next == NULL){
*stack = (*stack)->next;
delete deleteMe;
return;
}
while(deleteMe->next != NULL){
if(deleteMe->next->next==NULL){
// saving the current location of the node before the node which I want to delete
Node* temp = deleteMe;
// updating the deleteMe pointer to the node which I want to delete
deleteMe = deleteMe->next;
// setting the current node before the deleteMe node to point to NULL instead of the node which I want to delete
temp->next = NULL;
delete deleteMe;
return;
}
deleteMe = deleteMe->next;
}
}
void printList(Node* stack){
Node* temp = stack;
while(temp!=NULL){
std::cout<<temp->data<<" ";
temp = temp->next;
}
std::cout<<"\n";
}
int top(Node** stack){
Node* top = *stack;
while(top->next!=NULL){
top = top->next;
}
return top->data;
}
int main(){
Node* stack = NULL;
// testing implementation below
push(&stack,10);
std::cout<<top(&stack)<<std::endl;
push(&stack,20);
std::cout<<top(&stack)<<std::endl;
push(&stack,30);
push(&stack,40);
printList(stack);
std::cout<<top(&stack)<<std::endl;
pop(&stack);
pop(&stack);
push(&stack,40);
std::cout<<top(&stack)<<std::endl;
}
Your implementation looks fine, one additional improvement can be done by maintaining head and tail pointer so that you can remove 1st and last element as needed. Here is example c++ code.
#include <iostream>
using namespace std;
template <class T> class node {
public:
node<T>() {}
~node<T>() {}
T data;
node<T> *next;
};
template <class T> class linked_list {
public:
linked_list<T>() : head(NULL), tail(NULL) {}
~linked_list<T>() {}
virtual void addFirst(T data) {
node<T> *n = new node<T>();
if (head == NULL)
tail = n;
n->data = data;
n->next = head;
head = n;
size++;
}
virtual void addLast(T data) {
node<T> *n = new node<T>();
n->data = data;
if (tail == NULL) {
head = n;
} else {
tail->next = n;
}
n->next = NULL;
tail = n;
}
virtual void reverse() {
if ((head == NULL) || (head->next == NULL))
return;
node<T> *current = head;
node<T> *previous = NULL;
node<T> *next = current->next;
tail = current;
while (current) {
next = current->next;
current->next = previous;
previous = current;
current = next;
}
head = previous;
}
virtual void print_nodes() {
node<T> *temp = head;
while (temp) {
cout << temp->data << " " << flush;
temp = temp->next;
}
cout << endl;
}
virtual void removeLast() {
node<T> *temp = head;
while (temp->next->next) {
temp = temp->next;
}
tail = temp;
delete temp->next;
temp->next = NULL;
}
virtual void removeFirst() {
node<T> *temp = head;
head = head->next;
delete temp;
}
private:
node<T> *head;
node<T> *tail;
uint32_t size;
};
int main(int argc, const char *argv[]) {
linked_list<uint32_t> *llist = new linked_list<uint32_t>();
llist->addLast(1);
llist->addFirst(5);
llist->addFirst(10);
llist->addFirst(15);
llist->addFirst(20);
llist->addLast(30);
llist->addFirst(40);
llist->print_nodes();
llist->reverse();
llist->print_nodes();
llist->removeLast();
llist->print_nodes();
llist->removeFirst();
llist->print_nodes();
return 0;
}
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;
};
The following naive code implements a linked list, without printing all the elements in the main function, everything would be fine. However, the LinkedList::printll function will trigger a set fault(Gcc 5.3.0), the problem is related to the appropriate handling of the head node I suppose...
So, is there any way to make this code work with least modification of the printll function?
#include <iostream>
using namespace std;
struct Node{
int value;
Node* next;
};
struct LinkedList{
Node* head= NULL ;
void append(int);
void printll();
};
void LinkedList::append(int data){
Node* cur = head;
Node* tmp = new Node;
tmp->value = data;
tmp->next = NULL;
if(!cur){
cur = tmp; // cur-> head
}
else{
while(cur->next != NULL){
cur = cur->next;
}
cur->next = tmp;
}
std::cout<<cur->value<<std::endl; // cur-> temp
delete tmp; // comment out
}
void LinkedList::printll(){
Node* cur = head;
while(cur->next != NULL){ //
std::cout<<cur->value<<std::endl;
cur = cur->next;
}
}
int main(){
LinkedList LL;
LL.append(5);
LL.append(6);
LL.append(7);
LL.printll(); // --without this, the program is fine
return 0;
}
You have some bugs in append:
if(!cur){
cur = tmp;
}
This only assigns to the local copy. I assume you are trying to set head here, so do that: head = tmp;. Note that in this case, you can't print cur, since you haven't set it. You could print tmp->value though.
Then:
delete tmp;
You only just created it and assigned it into place - why are you deleting it? You know that there is still a pointer to it. Only delete it when you come to clean up the list when you are done with it (which you don't do at all at the moment).
Other than that, your printll won't print the last element - think about when it will stop:
A -> B -> C -> NULL
It will stop on node C, but never print C's value. You can just replace:
while(cur->next != NULL){
with
while(cur != nullptr){
(Also, I don't like endl).
See here for these changes running:
#include <iostream>
struct Node{
int value;
Node* next;
};
struct LinkedList{
Node* head = nullptr ;
void append(int);
void printll();
};
void LinkedList::append(int data){
Node* cur = head;
Node* tmp = new Node;
tmp->value = data;
tmp->next = nullptr;
if(!cur){
head = tmp;
}
else{
while(cur->next != nullptr){
cur = cur->next;
}
cur->next = tmp;
}
}
void LinkedList::printll(){
Node* cur = head;
while(cur != nullptr){
std::cout << cur->value << '\n';
cur = cur->next;
}
}
int main(){
LinkedList LL;
LL.append(5);
LL.append(6);
LL.append(7);
LL.printll();
}
1.you cann't
delete tmp;
cause tmp is a pointer, when you run delete tmp, you delete the object.
2.the print function should like this:
void LinkedList::printll(){
Node* cur = head;
while(cur->next != NULL){ // -> problems is here
std::cout<<cur->value<<std::endl;
cur = cur->next;
}
std::cout<<cur->value<<std::endl;
}
I am trying to build a linked list in C++. My understanding is that the code I have created should create a node and then progressively link 4 more onto the end. Unfortunately, while I would expect to see the cout results as "12 123 1234 12345" I'm seeing "12 12 12 12" and in my main I am unable to traverse the list - it just crashes.
I have the following code:
struct listNode {
int val;
listNode* next;
};
int nodeCount = 0;
listNode* addToEnd(listNode* node) {
listNode* newNode = new listNode;
newNode->val = ++nodeCount;
newNode->next = NULL;
if (node == NULL) {
return newNode;
}
listNode* current = node;
cout<<"\n\n";
do {
if (current->next == NULL) {
current->next = newNode;
}
cout<<current->val<<"\n";
current = current->next;
} while (current->next != NULL);
cout<<current->val<<endl;
}
int main()
{
listNode* first = addToEnd(NULL);
addToEnd(first);
addToEnd(first);
addToEnd(first);
addToEnd(first);
cout<<"Third: "<<first->next->next->val;
}
Any help is appreciated, as I am at wit's end!
It is obvious that function addToEnd is wrong
listNode* addToEnd(listNode* node) {
listNode* newNode = new listNode;
newNode->val = ++nodeCount;
newNode->next = NULL;
if (node == NULL) {
return newNode;
}
listNode* current = node;
cout<<"\n\n";
do {
if (current->next == NULL) {
current->next = newNode;
}
cout<<current->val<<"\n";
current = current->next;
} while (current->next != NULL);
cout<<current->val<<endl;
}
Let's assume that the list already contains two nodes and consider the do-while loop inside the function. At first current_next != null so the following statement is executed
current = current->next;
Now current points to the second node. Its data member next is equal to NULL. So the condition of the loop
} while (current->next != NULL);
will be false and no iteration will be repeated. So we added nothing.
Also the function returns nothing if node is not equal to NULL.
Rewrite the function the following way
listNode* addToEnd( listNode* node )
{
listNode* newNode = new listNode { ++nodeCount, NULL };
if ( node == NULL) return newNode;
listNode* current = node;
while ( current->next != NULL ) current = current->next;
current->next = newNode;
return newNode;
// or
//return node;
}
Take into account that this statement
cout<<"Third: "<<first->next->next->val;
outputs only the value of the third node.
If you want to output all the list you should write
for ( listNode *current = first; current; current = current->next )
{
std::cout << current->val << ' ';
}
std::cout << std::endl;
By the way using my function you could write in main for example the following way:)
listNode* first;
addToEnd( addToEnd( addToEnd( addToEnd( first = addToEnd( NULL ) ) ) ) );
Use a for loop to get you to the last node instead of a while, and then assign the new node OUTSIDE of the loop. Trying to do it inside will result in an infinite loop (and make the code harder to read):
listNode* current;
for(current = node; current->next != NULL; current = current->next) ;
current->next = newNode;
You're also forgetting to return newNode at the end of the function.
You're falling off the end of a function with non-void return type. The fact that you don't use the return value does not make that ok.
6.6.3 in the Standard says that:
Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
There is no return statement just in case the if condition that checks if(node==null) fails..
Is it against the rules to use recursive functions in your question?
Why not do...
void addToEnd(listNode* node){
if(node == NULL){
*node = new listNode;
node->next = NULL;
node->val = ++nodeCount;
}else{
addToEnd(node->next);
}
return;
}
int main(){
listNode* first = NULL;
addToEnd(first); // 1
addToEnd(first); // 2
addToEnd(first); // 3
addToEnd(first); // 4
addToEnd(first); // Linked list is now 5 long
}
This is how I would have coded adding five nodes to a linked list that holds a node count. If anyone has advice it is welcome.
#include <iostream>
#include <cstdlib>
using namespace std;
struct listNode{
int val;
listNode* next;
};
listNode* addToEnd(listNode*, int);
int main()
{
listNode* first = NULL;
listNode* temp;
int nodeCount = 1;
for(int i = 0; i < 5; i++){
first = addToEnd(first, nodeCount);
nodeCount++;
}
temp = first;
while(temp){
cout << temp->val << ' ';
temp = temp->next;
}
temp = first;
//Deallocate memory
while(temp){ //could do memory deallocation while displaying
nodeToDelete = temp; //the value of nodeCount but wanted to illustrate
//both methods individually
temp = temp->next;
delete nodeToDelete;
}
first = NULL; //eliminate hanging pointer
return 0;
}
listNode* addToEnd(listNode* node, int nodeCount)
{
listNode* newNode = new (nothrow) listNode;
listNode* current = node;
if(newNode){
newNode->val = nodeCount;
newNode->next = NULL;
if (node == NULL)
node = newNode;
else{
while (current->next != NULL)
current = current->next;
current->next = newNode;
}
}
else
cout << "error allocationg memory" << endl;
return node;
}