LinkedList/Stack/Queue - Help with Dequeuing - c++

I had to write a linked list, then turn it into a dynamic Stack, then turn that into a dynamic Queue. Well everything seems to work except the "dequeuing", right as the programs about to finish, it gives me an error: "An unhandled win32 exception occured in LinkedList_Stack_BNS11.exe [4972].".
I'm only assuming it's the dequeuing, because as I step through and/or run the program, it runs smoothly up till that part, so maybe I sent one of the pointers wrong or something?
Output:
Enquing 5 items....
// Finsihes
The values in the queue were (Dequeuing):
0
1
2
// Correct number in que but...
//Program gives that error right here. When it should finish and close.
If I included too much code let me know and I'll chop it down to just the "Dequeuing" (Which is in the very middle of all the stuff below)
Thanks in advance for the help!! I'm just not seeing what I did wrong. Thinking it maybe has something to do with where "head" is pointing? Idk.
Header File:
class NumberList
{
private:
//
struct ListNode
{
int value; // Value in this node
struct ListNode *next; // Pointer to the next node
};
ListNode *head; // List head pointer
ListNode *rear;
public:
//Constructor
NumberList()
{ head = NULL; rear = NULL; }
//Destructor
~NumberList();
//Stack operations
bool isEmpty();
//Queue operations
void enqueue(int);
void dequeue(int &);
};
#endif
List_Stack_Queue.cpp:
bool NumberList::isEmpty()
{
bool status;
if(!head)
status = true;
else
status = false;
return status;
}
void NumberList::enqueue(int num)
{
ListNode *newNode; // Point to a new node
// Allocate a new node and store num there.
newNode = new ListNode;
newNode->value = num;
//If there are no nodes in the list
// make newNode the first node.
if(isEmpty())
{
head = newNode;
rear = head;
//newNode->next = NULL;
}
else
{
rear->next = newNode;
rear = rear->next;
//newNode->next = head;
//head = newNode;
}
}
void NumberList::dequeue(int &num)
{
ListNode *temp;
if(isEmpty())
cout << "The queue is empty.\n";
else
{
num = head->value;
temp = head;
head = head->next;
delete temp;
}
}
MAIN:
const int MAX_VALUES = 3;
// Create a DynIntQueue object.
NumberList iQueue;
// Enqueue a series of numbers.
cout << "Enqueuing " << MAX_VALUES << " items...\n";
for (int x = 0; x < MAX_VALUES; x++)
iQueue.enqueue(x);
cout << endl;
//Dequeue and retrieve all numbers in the queue
cout << "The values in the queue were (Dequeuing):\n";
while(!iQueue.isEmpty())
{
int value;
iQueue.dequeue(value);
cout << value << endl;
}
return 0;

Last nodes's next element should be set to NULL in a linked list. So,
void NumberList::enqueue(int num)
{
// ...
if(isEmpty())
{
head = newNode;
head->next = NULL;
rear = head;
}
else
{
rear->next = newNode;
rear = rear->next;
rear->next = NULL; // Pointing the next node element to null.
}
}
To, me it seems some thing is wrong with Numberlist::isEmpty(); member function. How you are deciding whether the list is empty or not ? Show the definition of it.

Related

Problem with my doubly linked list insert function

I am trying to finish up a assignment for my data structures c++ class. I have to define a double linked list of functions(like insert() size() remove() ) that was provided by my instructor. The instructor also includes the main file which runs tests on my code to see if it works.
I'm receiving his error message:
* Starting dlist tests *
Checking empty list...
FAILED: size of empty list is != 0.
I tried to rewrite the definition of the size() and insert() function and Im not understanding why im getting his error.
my instructors test code:
bool test_empty() {
std::cout << "Checking empty list...\n";
dlist e;
if(!verify(e))
return false;
if(e.size() != 0) {
std::cout << "FAILED: size of empty list is != 0.\n";
return false;
}
if(!e.empty()) {
std::cout << "FAILED: empty list is not .empty().\n";
return false;
}
return true;
}
my code for implementations:
void insert(node *previous, int value){
if(previous == nullptr){
node* n = new node;
n->value = value;
n->prev = previous;
n->next = nullptr;
return;
}
node* n = _head; //made a pointer to start at the head
while( n!= previous )//make n go down the list until it hits previous
{n = n->next;}
node* store_next = n->next; //store the address of the prev pointer of the next node
node* a = new node;//create the node that will be inserted
a->value = value;
n->next = a;// the pointer n points to the new node
a->prev = n; //the prev in the new node points to the previous
a->next = store_next; //the next in the new node points to the next node
store_next->prev = a; //the next node's prev points to the new inserted node
}
int size() const{
node* n = _head;
int size = 0;
while(n != nullptr){
size++;
n = n -> next;
}
return size;
}
Heres my default constructor and double linked list struct that my professor requires I use
class dlist {
public:
dlist() {
}
struct node {
int value;
node* next;
node* prev;
};

How do I make my Linked List Print backwards in C++

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.

"Aborted (core dumped)" error in dequeue method of queue class

This queue class's dequeue method doesn't work properly and I'm not sure why. When I run it it says "* Error in `./a.out': double free or corruption (fasttop): 0x00000000018dfe50 *", followed by a backtrace and then "Aborted (core dumped)".
At first I was deleting the bottom node directly, but I thought that might be the problem so I switched to deleting them another way.
Here's the dequeue method:
int Queue::dequeue() {
if (isEmpty()) {
cout << "ERROR: Can't dequeue from empty Queue"<< endl;
return -1;
} else {
Node* n = top;
if (n == NULL){
bottom = top;
return 0;
}
if (n->next == NULL){
delete n;
bottom = top;
return 0;
}
while(n->next->next != NULL){
n = n->next;
}
bottom = n;
n = n->next;
delete n;
return 0;
}
}
And here's the whole file:
#include <iostream>
using namespace std;
struct Node {
int data;
Node *next;
};
class Queue {
public:
Queue(); //constructor
~Queue(); //destructor
void enqueue(int d); //enqueues node onto top of Queue
int dequeue(); //dequeues bottom node off of Queue -- returns integer dequeued
bool isEmpty(); //checks if Queue is empty
void print(); //print contents of Queue from top to bottom
private:
Node* top; //points to top node in Queue
Node* bottom; //points to bottom node in Queue
};
Queue::Queue() {
top = NULL;
bottom = NULL;
}
Queue::~Queue() {
while (!isEmpty())
dequeue();
}
void Queue::enqueue(int d) {
Node* temp = new Node;
temp->data = d;
temp->next = top;
top = temp;
if (temp->next == NULL){
delete bottom;
bottom = temp;
}
}
int Queue::dequeue() {
if (isEmpty()) {
cout << "ERROR: Can't dequeue from empty Queue"<< endl;
return -1; //error
} else {
Node* n = top;
if (n == NULL){
bottom = top;
return 0;
}
if (n->next == NULL){
delete n;
bottom = top;
return 0;
}
while(n->next->next != NULL){
n = n->next;
}
bottom = n;
n = n->next;
delete n;
return 0;
}
}
bool Queue::isEmpty() {
return (top==NULL);
}
//Print Queue from top to bottom
void Queue::print(){
Node* n = top;
while(n != NULL){
cout << n->data << endl;
n = n->next;
}
cout << endl;
}
int main(){
Queue* s = new Queue();
s->print();
s->enqueue(20);
s->enqueue(30);
s->print();
s->enqueue(40);
s->enqueue(12);
s->print();
s->dequeue();
s->print();
s->dequeue();
s->print();
s->dequeue();
delete s;
return 0;
}
Whenever you delete a node, you need to update all the pointers that point to the node being deleted. You need to do this in two places.
First, in the n->next == NULL case, the Queue only has one node. After you call delete n, top still points to this now deleted node, and you need to update top (to NULL or nullptr) before changing the value of bottom.
In the last case, where there is more than one node in the list, you delete the last node but the next pointer of the previous node still points to it. After the n = n->next expression, you need to set bottom->next to point to the node that n->next now points to (which, since n is the last node in the Queue, is NULL).

Unable to grow my linked list

Given below is my code snippet for linked list. I am not able to add number. Whenever I try to add to my list, numbers are getting replaced, so my list never grows. Can you please let me know what is wrong in this code. It would also be very helpful if you could comment on my coding fashion.
using namespace std;
struct node
{
int number;
std::shared_ptr<node> next;
};
bool isEmpty(std::shared_ptr<node> &head)
{
return (head == NULL);
}
void add(std::shared_ptr<node> &head, int number)
{
std:: shared_ptr<node> temp;
temp.reset(new node);
//temp = head;
cout<<"\n Adddress of head: "<<head.get();
// cout<<"\nAddress of temp: "<<temp.get();
if(isEmpty(head))
{
head.reset(new node);
head->number = number;
head->next = NULL;
cout<<"\nAdded first element";
}
else
{
cout<<"\nAdding element to exisiting list";
while(head->next!= NULL)
{
cout<<"\n traversing to next element----->"<<temp->number;
head = head->next;
}
shared_ptr<node> newNode;
newNode.reset(new node);
newNode->number = number;
newNode->next = NULL;
head->next = newNode;
cout<<"\n address of newNode: "<<newNode.get();
// head->next = temp;
}
//cout<<"\nExiting add";
}
int main()
{
int number;
std::shared_ptr<node> head(nullptr);
char choice;
add(head, number);
return 0;
}
Let's take a walk through the add function. I've tweaked the indentation for easier reading.
void add(std::shared_ptr<node> &head, int number)
{
std::shared_ptr<node> temp;
temp.reset(new node);
What are you using temp for? Nothing that I can see.
//temp = head;
cout << "\n Adddress of head: " << head.get();
// cout<<"\nAddress of temp: "<<temp.get();
if (isEmpty(head))
{
head.reset(new node);
head->number = number;
head->next = NULL;
cout << "\nAdded first element";
}
OK. That case looks good.
else
{
cout << "\nAdding element to exisiting list";
while (head->next != NULL)
{
cout << "\n traversing to next element----->" << temp->number;
head = head->next;
Whups! Just moved the head. You just lost that first node element. No one points at it anymore. Shared pointer prevents the leak by destroying it for you. Nice, but you've still lost the data. Fortunately head points to the former head->next, preventing destruction when the former head goes to its grave with next. Shared pointer saves your bacon, but injects a load of extra overhead.
}
shared_ptr<node> newNode;
newNode.reset(new node);
newNode->number = number;
newNode->next = NULL;
head->next = newNode;
cout << "\n address of newNode: " << newNode.get();
// head->next = temp;
}
//cout<<"\nExiting add";
}
On the coding style front, I would use a Linked List class to make this a bit easier to deal with:
#include <iostream>
class LinkedList // Ahhhr. Here be the class
{
struct node // node is a private member of the class hidden away from sight.
{
int number;
node * next;
};
node * head; // no shared pointer. We'll handle the memory ourselves.
public:
LinkedList(): head(nullptr) // construct and init LinkedList
{
}
// we need a copy constructor to be Rule of Three compliant
LinkedList(const LinkedList & src): head(nullptr) // copy constructor
{
node * cur = src.head;
while (cur != nullptr)
{
add(cur->number);
cur = cur->next;
}
}
~LinkedList() // free up the nodes
{
while (head->next != nullptr)
{
node *temp = head;
head = head->next;
delete temp;
}
delete head;
}
// Need assignment operator to be Rule of Three compliant
// OK this looks a bit weird. src is passed by reference which will
// trigger the copy constructor above to do the copy for us. Then we
// steal the head from the copy and null it so when src goes out of
// scope the destructor doesn't kill all the nodes we just took.
// This is called the Copy-and-Swap idiom.
LinkedList & operator=(LinkedList src)
{
head = src.head;
src.head = nullptr;
return *this;
}
bool isEmpty() // essentially unchanged. head is now a class member.
// No need for parameter
{
return (head == NULL);
}
void add(int number)
{
// removed dead code
if (isEmpty())
{
head = new node;
head->number = number;
head->next = NULL;
}
else
{
node * cur = head; // updates a temporary, not the head.
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = new node;
cur->next->number = number;
cur->next->next = NULL;
}
}
};
// and a quick tester
int main()
{
LinkedList list;
list.add(1);
list.add(2);
list.add(3);
return 0;
}
This allows the Linked List to easily be templated and saves trouble later.
More on the Rule of Three and Copy-and-Swap
Why are you using reset on shared pointer?
http://en.cppreference.com/w/cpp/memory/shared_ptr/reset
Check the following example:
https://codereview.stackexchange.com/questions/33136/singly-linked-list-with-smart-pointers

Circular linked list C++

I'm trying to create a queue using a circular linked list. I just took my existing linked list implementation (which already works) and changed where the nodes pointed but it doesn't seem to be that straightforward. I'm sure it's one small thing that I'm overlooking.
void enqueue(int q){
newNode=new node;
newNode->info = q;
newNode->link = first;
if(first->link==first){
first = last = newNode;
last->link=first;
}
else{
last->link = newNode;
last= newNode;
last->link = first;
}
}
int dequeue(){
int x;
if(first->link==first){
cout <<"The Queue is empty" <<endl;
return 0;
}
else{
dummy=first;
x=dummy->info;
first=first->link;
delete(dummy);
return(x);
}
}
I converted this to a class. For a circular list class, only a pointer to last node is needed, as first = last->next. Since no dummy node is used, an empty list is normally indicated by last == NULL;
#include<iostream>
class circq
{
typedef struct node_
{
struct node_ *next;
int info;
}node;
node *last; // ptr to last node of list
public:
circq() // constructor
{
last = NULL; // reset last
}
bool isempty()
{
return last == NULL;
}
void enqueue(int q)
{
node *newNode=new node; // new node
newNode->info = q;
if(last == NULL){ // if empty list
last = newNode; // create single node list
newNode->next = newNode;
return;
} // else
newNode->next = last->next; // append node to end list
last->next = newNode;
last = newNode;
}
int dequeue()
{
if(last == NULL){ // check for empty list
return 0;
}
node *first = last->next; // set ptr to first node
int x = first->info; // set return value
if(last->next == last) // if single node
last = NULL; // set list to empty
else // else
last->next = first->next; // advance first to next node
delete first; // delete node
return x;
}
~circq() // destructor
{
while(!isempty())
dequeue();
}
};
int main() // test circq
{
circq cq;
cq.enqueue(0);
cq.enqueue(1);
cq.enqueue(2);
cq.enqueue(3);
while(!cq.isempty())
std::cout << cq.dequeue() << std::endl;
return 0;
}