Pop front and back in deque - c++

I'm trying to implement a deque with some functions: front(),
back(), push_front(), push_back(), pop_front(), pop_back(). If I have one element in the queue and I try to pop it I get an "read access violation" in print function, however I check if a first element exists in deque.
#include<iostream>
#include<cstdlib>
using namespace std;
struct Nod {
int info;
Nod* next, *back;
};
void create_queue(Nod*& p, Nod*& u)
{
Nod *c = new Nod;
cout << "c->info: "; cin >> c->info;
if (!p)
{
p = c;
p->back = NULL;
p->next = NULL;
u = p;
}
else
{
u->next = c;
c->back = u;
u = c;
u->next = NULL;
}
}
void print_queue(Nod* p, Nod* u)
{
if (p) {
Nod *c = p;
while (c) {
cout << c->info << " ";
c = c->next;
}
}
else
cout << "Deque is empty";
}
int front(Nod *p) {
return p->info;
}
int back(Nod *u) {
return u->info;
}
void push_front(Nod*& p, Nod*& u) {
Nod *c = new Nod;
cout << "Push front c->info "; cin >> c->info;
c->next = p;
p->back = c;
c->back = NULL;
p = c;
}
void push_back(Nod*& p, Nod*& u) {
Nod *c = new Nod;
cout << "Push back c->info "; cin >> c->info;
c->back = u;
u->next = c;
u = c;
u->next = NULL;
}
void pop_front(Nod*& p, Nod*& u) {
if (p) {
Nod *c = p;
if (p->next != NULL) {
p->next->back = NULL;
p = p->next;
}
delete c;
}
else
{
cout << "Can't pop, deque is empty";
}
}
void pop_back(Nod*& p, Nod*& u) {
if (u){
Nod *c = u;
if (u->back != NULL) {
u->back->next = NULL;
u = u->back;
}
delete c;
}
else
{
cout << "Can't pop, deque is empty";
}
}
int main()
{
int n, i = 1;
Nod *p, *u = new Nod;
p = NULL;
u = NULL;
cout << "Nr nod: "; cin >> n;
while (i <= n){
create_queue(p, u);
i++;
}
pop_front(p, u); //problems if there is only one element in deque
print_queue(p, u);
system("Pause");
}

When there's only one node, you delete it but it's never set to nullptr, thus you still access the memory there causing a runtime error. Here I've written a modified pop_front and pop_back. In particular pop_back now sets the next pointer of the tail's previous element to nullptr. If there is only one element in the deque (head == tail) we do a pop_front, which will set head to nullptr by assigning it to its next element.
void pop_front(Nod*& head, Nod* tail) {
if (head) {
Nod* nodePtr = head;
head = head->next;
delete nodePtr;
}
}
void pop_back(Nod*& head, Nod*& tail) {
if (head == tail) {
return pop_front(head, tail);
}
Nod* prev = tail->back;
prev->next = NULL;
delete tail;
tail = prev;
}

Related

Runtime polymorphism and operator overload

The problem is that in main function pointer to abstract class list calls operator+ of this class. But how can I call overloaded operators from child classes (queue and stack) with pointer to parent class list
#include <iostream>
#include <cstdlib>
#include <time.h>
using namespace std;
class list
{
public:
list* head;
list* tail;
list* next;
int num;
virtual ~list() {}
list() { head = tail = next = NULL; num = 0; }
virtual list operator+(int i) { return *this; };
virtual int operator-() { return 0; };
};
class queue : public list
{
public:
list operator+(int i);
int operator-();
};
class stack : public list
{
public:
list operator+(int i);
int operator-();
};
int main()
{
srand(time(NULL)); rand();
list* p;
queue q_ob;
stack s_ob;
char ch;
for (;;)
{
cout << "Enter something else to stop.\nStack, Queue or ULL? (S/Q): \n";
cin >> ch;
ch = tolower(ch);
if (ch == 'q')
p = &q_ob;
else if (ch == 's')
p = &s_ob;
else break;
p + (rand() % 100);
}
cout << "Enter T to terminate\n";
for (;;)
{
cout << "Remove from Stack, Queue or ULL? (S/Q):";
cin >> ch;
ch = tolower(ch);
if (ch == 'q')
p = &q_ob;
else if (ch == 's')
p = &s_ob;
else break;
cout << -(*p) << '\n';
}
return 0;
}
list queue::operator+(int i)
{
list* item;
item = new queue;
if (!item)
{
cout << "Allocation error.\n";
exit(1);
}
item->num = i;
// put on end of list:
if (tail)
tail->next = item;
tail = item;
item->next = NULL;
if (!head)
head = tail;
return *this;
}
int queue::operator-()
{
int i;
list* p;
if (!head)
{
cout << "List empty.\n";
return 0;
}
// remove from start of list
i = head->num;
p = head;
head = head->next;
delete p;
return i;
}
list stack::operator+(int i)
{
list* item;
item = new stack;
if (!item)
{
cout << "Allocation error.\n";
exit(1);
}
item->num = i; // put on front of list
// for stack - like operation
if (head)
item->next = head;
head = item;
if (!tail)
tail = head;
return *this;
}
int stack::operator-()
{
int i;
list* p;
if (!head)
{
cout << "List empty.\n";
return 0;
}
// remove from start of list:
i = head->num;
p = head;
head = head->next;
delete p;
return i;
}

how to save a value in a pointer with a function?

I'm making a simple linked list with a classic functions. The elements in this list should not be repeated and should be in an order. The function find recieves two parameters: The valor that should be finded and the pointer to save the node that has it. Everything is going well, but the pointer keeps being nullptr because is not saving the current memory address. I can't understand why my pointer is not pointing to the current node. Please Help me.
template <class T>
class simpleNode {
public:
T data;
simpleNode<T>* next = NULL;
simpleNode(T newData) {
data = newData;
}
};
template <class T, class C>
class simpleLinkedListOnePointer {
public:
simpleNode<T>* head;
C comparator;
simpleLinkedListOnePointer <T, C>() {
head = NULL;
}
bool find(T x, simpleNode<T>*& p) {
p = head;
while (p && comparator(p->data, x))
p = p->next;
return p?true:false;
}
bool insert(T x) {
simpleNode<T>* ptr;
if (find(x, ptr)) {
return false;
}
simpleNode<T>* ptrAdd = new simpleNode<T>(x);
if (!ptr) {
ptrAdd->next = head;
head = ptrAdd;
return true;
}
else {
cout << "ESTE ES EL NODO APUNTADO POR PTR: " << ptr->data << endl;
ptrAdd->next = ptr->next;
ptr->next = ptrAdd;
return true;
}
}
bool remove(T x) {
return 1;
}
void print() {
simpleNode<T>* p = head;
while (p) {
cout << p->data << "->";
p = p->next;
}
cout << endl;
}
};```

How to remove a certain node from a linked list by the data its holding?

We are suppose to enter a string, and then find where the string is in the linked list and remove that node
when i insert to the front of the list, so i enter data values a, b, c , d, when i print it it comes up as d,c,b,a. Now i insert to the rear of it, entering f and g, and the list now looks, d,c,b,a,f,g. I want to remove f but it just use the remove function it does not and still output the same list
using namespace std;
struct node {
string data;
node* next;
};
node* addFront(node* s);
node* addRear(node* s);
void remove(node* head, string abc);
void print(node* head);
int main() {
node* head = NULL;
cout << "Enter 5 data strings\n";
cout << "This will be inserted from the back\n";
for (int i = 0; i < 5; i++) {
head = addFront(head);
}
print(head);
cout << "Enter 3 strings and this will be inserted from the back of the orignal string\n";
for (int i = 0; i < 3; i++) {
head = addRear(head);
}
print(head);
cout << "Removing the head node\n";
string n;
cout << "Enter a string to remove\n";
cin >> n;
remove(head, n);
print(head);
}
node* addFront(node* s)
{
node* person = new node;
cin >> person->data;
person->next = s;
s = person;
return s;
}
node *addRear(node*s ) {
node* person = new node;
cin >> person->data;
person->next = NULL;
if (s == NULL) {
return person;
}
else {
node* last = s;
while (last->next != NULL) {
last = last->next;
}
last->next = person;
}
return s;
}
void remove(node* head, string a) {
node* previous = NULL;
node* current = head;
if (current == NULL) {
cout << "Value cannot be found\n";
return;
}
else {
while (previous != NULL) {
if (current->data == a) {
previous->next = current->next;
delete current;
break;
}
current = current->next;
}
}
}
void print(node * head)
{
node* temp = head;
while (temp != NULL) // don't access ->next
{
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
In remove function, previous is most certainly NULL when you hit that while loop.
Perhaps consider a do-while loop instead (with better handling of previous).
You may be better off handling the first node in a different manner since the holder of its previous is essentially the root pointer.

How to delete node from linked list?

Adding integers to list works fine, but there's something wrong with deleting and printing.
I'm not friendly with debugger yet, but I found out that there is error from node pointer 'first'. Its value is -17891602. I don't know what happened...
#include <iostream>
using namespace std;
class nodeList;
class node {
friend class nodeList;
private:
int data;
node* link;
public:
node() { //constructor
data = 0;
link = NULL;
}
node(int d) { //constructor
data = d;
link = NULL;
}
node(int d, node* l){ //constructor
data = d;
link = l;
}
};
class nodeList {
private:
node* first;
int num = 0;
node* nt;
public:
nodeList() {
first = new node();
}
node* end(node* t){ //return pointer of last element
t = first;
for (int i = 0; i < num; i++){
t = t->link;
}
return t;
}
void add(int a){ //add 'a' at the end of the list
node* x = new node(a);
node* y = this->end(nt);
y->link = x;
num++;
}
void del(int n){ //n : data of element that you want to delete from list
node* temp = first;
node* pretemp = NULL;
node* x;
int i;
for (i = 0; i <= this->num; i++){ //loop to find 'n'
pretemp = temp;
temp = temp->link;
if (n == temp->data){
break;
}
}
temp = first;
for (int j = 0; j<i; j++){ //i : where 'n' is,
temp = temp->link;
}
x = temp->link;
pretemp->link = x;
delete temp;
num--;
}
void printList(){
node* temp = first;
temp = temp->link;
for (int i = 0; i<this->num; i++){
cout << temp->data << endl;
temp = temp->link;
}
}
};
int main(){
nodeList *l = new nodeList();
int a;
int select;
while (1){
cout << "1. ADD 2. DELETE 3. PRINT" << endl;
cin >> select;
if (select == 1){
cout << "Enter an integer: ";
cin >> a;
if (cin.fail()) {
cout << "Wrong input" << endl;
break;
}
l->add(a);
l->printList();
}
if (select == 2){
cout << "Enter the data of the element you want to delete: ";
cin >> a;
if (cin.fail()) {
cout << "Wrong input" << endl;
break;
}
l->del(a);
l->printList();
}
if (select == 3){
l->printList();
}
}
}
Your del function deletes pretemp node (node that was before the one that you need to delete).
Here's possible fix:
//n : data of element that you want to delete from list
void del(int n)
{
//loop to find 'n'
for (node *tmp = first; tmp->link; tmp = tmp->link)
{
if (n == tmp->link->data)
{
node *x = tmp->link;
tmp->link = tmp->link->link;
delete x;
num--;
break;
}
}
}
Also, was your del supposed to delete all nodes with data == n?
These functions are a bit complicated. Here is a simpler idea:
void del(int n){
node* pretemp = first, *temp = first->link;
if(pretemp->data == n) { //handle the deleting of the first node
first = first->link;
delete pretemp;
return;
}
while(temp != NULL && temp->data != n) { //find the node with the data member "n"
pretemp = temp;
temp = temp->link;
}
if(temp != NULL) { //if you found the node, delete it
pretemp->link = temp->link;
delete temp;
}
--num;
}
Your code is a bit over-complicated for what it needs.
Try something more like this instead:
#include <iostream>
#include <limits>
using namespace std;
class nodeList;
class node
{
friend class nodeList;
private:
int data;
node* link;
public:
node(int d = 0) //constructor
: data(d), link(NULL)
{
}
};
class nodeList
{
private:
node* first;
int num;
public:
nodeList()
: first(NULL), num(0)
{
}
~nodeList()
{
node *n = first, *t;
while (n)
{
t = n->link;
delete n;
n = t;
}
}
void add(int data) //add 'data' at the end of the list
{
node* n = new node(data);
if (!first)
first = n;
else
{
node *t = first;
while (t->link)
t = t->link;
t->link = n;
}
++num;
}
void del(int data) //data : data of element that you want to delete from list
{
node* n = first;
node* prev = NULL;
while (n) //loop to find 'data'
{
if (data == n->data)
{
if (prev)
prev->link = n->link;
if (n == first)
first = n->link;
delete n;
--num;
return;
}
prev = n;
n = n->link;
}
}
void printList()
{
for(node* n = first; n != NULL; n = n->link)
cout << n->data << endl;
}
};
int main()
{
nodeList l;
int input;
bool keepGoing = true;
do
{
cout << "1. ADD 2. DELETE 3. PRINT 4. EXIT" << endl;
if (!(cin >> input))
{
cout << "Wrong input" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
}
else
{
switch (input)
{
case 1:
cout << "Enter an integer: ";
if (!(cin >> input))
{
cout << "Wrong input" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
}
else
{
l.add(input);
l.printList();
}
break;
case 2:
cout << "Enter the data of the element you want to delete: ";
if(!(cin >> input))
{
cout << "Wrong input" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
}
else
{
l.del(input);
l.printList();
}
break;
case 3:
l.printList();
break;
case 4:
keepGoing = false;
break;
default:
cout << "Wrong input" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
break;
}
}
}
while (keepGoing);
return 0;
}
If you add an extra node* member to your nodeList class, you can simplify and speed up your add() method:
class nodeList
{
private:
node* first;
node* last;
int num;
public:
nodeList()
: first(NULL), last(NULL), num(0)
{
}
~nodeList()
{
node *n = first, *t;
while (n)
{
t = n->link;
delete n;
n = t;
}
}
void add(int data) //add 'data' at the end of the list
{
node* n = new node(data);
if (!first)
first = n;
if (last)
last->link = n;
last = n;
++num;
}
void del(int data) //data : data of element that you want to delete from list
{
node* n = first;
node* prev = NULL;
while (n) //loop to find 'data'
{
if (data == n->data)
{
if (prev)
prev->link = n->link;
if (n == first)
first = n->link;
if (n == last)
last = prev;
delete n;
--num;
return;
}
prev = n;
n = n->link;
}
}
void printList()
{
for(node* n = first; n != NULL; n = n->link)
cout << n->data << endl;
}
};
And if you can change your list to be a double-linked list instead of a single-linked list, you can simplify your del() method as well:
#include <iostream>
#include <limits>
using namespace std;
class nodeList;
class node
{
friend class nodeList;
private:
int data;
node* prev;
node* next;
public:
node(int d = 0) //constructor
: data(d), prev(NULL), next(NULL)
{
}
};
class nodeList
{
private:
node* first;
node* last;
int num;
public:
nodeList()
: first(NULL), last(NULL), num(0)
{
}
~nodeList()
{
node *n = first, *t;
while (n)
{
t = n->next;
delete n;
n = t;
}
}
void add(int data) //add 'data' at the end of the list
{
node* n = new node(data);
if (!first)
first = n;
if (last)
last->next = n;
n->prev = last;
last = n;
++num;
}
void del(int data) //data : data of element that you want to delete from list
{
for(node* n = first; n != NULL; n = n->next) //loop to find 'data'
{
if (data == n->data)
{
if (n->prev)
n->prev->next = n->next;
if (n->next)
n->next->prev = n->prev;
if (n == first)
first = n->next;
if (n == last)
last = n->prev;
delete n;
--num;
return;
}
}
}
void printList()
{
for(node* n = first; n != NULL; n = n->next)
cout << n->data << endl;
}
};

C++ create and print deque

I'm tring to create a deque and list the elements in it. I've made two functions for this: create_queue and print_queue. I've sent the pointers (head and tail) as reference so I don't have to declare them globally.
#include<iostream>
using namespace std;
struct Nod {
int info;
Nod* next, *back;
};
void create_queue(Nod*& p, Nod*& u)
{
Nod *c = new Nod;
cout << "c->info: "; cin >> c->info;
if (!p)
{
p = c;
p->back = NULL;
p->next = NULL;
u = p;
}
else
{
u->next = c;
c->back = u;
u = c;
u->next = NULL;
}
}
void print_queue(Nod*& p, Nod*& u)
{
Nod *c = p;
while (c) {
cout << c->info << " ";
c = c->next;
}
}
int main()
{
int n, i = 1;
Nod *p, *u = new Nod;
cout << "Nr nod: "; cin >> n;
while (i <= n){
create_queue(p, u);
i++;
}
print_queue(p, u);
getchar();
}
From what I understand from the debugger, I'm not able to access p->info.
What is the problem?
To pass an object that can be modified to a function you don't need that ugly Nod*& (address of a reference!) type. Use a common pointer Nod* instead.