Deletion in array implementation of queues reduces capacity? - c++

In all queue array implementations I have seen, when they 'pop an element from front', they basically change the front tag of the queue to the next element. but then the capacity of the queue is technically reduced (since array is used). How hasn't this caused problems yet or how is this considered valid?
Edit : https://www.softwaretestinghelp.com/queue-in-cpp/
Take the illustration in this link under consideration. When we perform the dequeue operation, we change the pointer of front to the next element. From this point on, any operation we perform will be done with respect to the 2nd position of array as the front element. Now if we go on adding elements to the full capacity of queue, we would, the maximum no. of elements that we could fit in the queue would be 1 less than the capacity of the array (which we had defined earlier).

You are right with your concern about the C++ implementation given in the article https://www.softwaretestinghelp.com/queue-in-cpp/. With that implementation, basically when you dequeue an element, the pointer to the "first" of the queue shift 1 unit to the right (in the underlying array), and that reduce the capacity of the queue.
The correct way to implement such a queue should be similar to the Java implementation provided in that very article. As you can see, every array indices are pre-processed with % this.max_size. That makes the array accessing become "circular", i.e. when we access an index k >= this.max_size, the real array index is back to the range [0, this.max_size - 1]. As a result, all the slot in the underlying array are used, which makes the capacity of the queue remain the same after the dequeue or enqueue operation.
Here is the corrected version of the C++ implementation.
#include <iostream>
#define MAX_SIZE 5
using namespace std;
class Queue
{
private:
int myqueue[MAX_SIZE], front, rear;
public:
Queue ()
{
front = -1;
rear = -1;
}
bool isFull ()
{
if ((rear - front + MAX_SIZE) % MAX_SIZE == MAX_SIZE - 1)
{
return true;
}
return false;
}
bool isEmpty ()
{
if (front == -1)
return true;
else
return false;
}
void enQueue (int value)
{
if (isFull ())
{
cout << endl << "Queue is full!!";
}
else
{
if (front == -1)
front = 0;
rear++;
myqueue[rear % MAX_SIZE] = value;
cout << value << " ";
}
}
int deQueue ()
{
int value;
if (isEmpty ())
{
cout << "Queue is empty!!" << endl;
return (-1);
}
else
{
value = myqueue[front % MAX_SIZE];
if (front >= rear)
{ //only one element in queue
front = -1;
rear = -1;
}
else
{
front++;
}
cout << endl << "Deleted => " << value << " from myqueue";
return (value);
}
}
/* Function to display elements of Queue */
void displayQueue ()
{
int i;
if (isEmpty ())
{
cout << endl << "Queue is Empty!!" << endl;
}
else
{
cout << endl << "Front = " << front;
cout << endl << "Queue elements : ";
for (i = front; i <= rear; i++)
cout << myqueue[i % MAX_SIZE] << "\t";
cout << endl << "Rear = " << rear << endl;
}
}
};
int
main ()
{
Queue myq;
myq.deQueue (); //deQueue
cout << "Queue created:" << endl;
myq.enQueue (10);
myq.enQueue (20);
myq.enQueue (30);
myq.enQueue (40);
myq.enQueue (50); //enqueue 60 => queue is full
myq.enQueue (60);
myq.displayQueue ();
//deQueue =>removes 10, 20
myq.deQueue ();
myq.deQueue ();
//queue after dequeue
myq.displayQueue ();
myq.enQueue (70);
myq.enQueue (80);
myq.enQueue (90); //enqueue 90 => queue is full
myq.displayQueue ();
return 0;
}

Related

Queue realisation C++

My realization of queue works in a strange way: when I enqueue new elements - all is right, but when I start to dequeue - it removes the last added element despite the fact that at this moment my head is 1 and tail is bigger. What are the pecularities of indexing in C++? Why does it behave like this?
Here is my full code:
https://hastebin.com/odibusacuk.cpp
class Queue{
public:
int head=1;
int tail=1;
int q[MAX];
int Queue::enqueue(int x){
if (isFull()){
return 0;}
else {
q[tail]=x;
cout << tail << " here is a tail\n";
if (tail==sizeof(q)){
cout << tail << " this is tail\n" ;
tail=1;}
else {
tail=tail+1;
}
return x;
}
}
int Queue::dequeue(){
if(isEmpty()){
cout << " the queue is empty\n";
return 0;}
else {
int x=q[head];
if (head==sizeof(q)){
head=1;}
else {
head=head++;
return x;}
}
return 0;
}
The problem you are having is because when you do something like
cout << k.enqueue(4) << " " << k.enqueue(9) << ' ' << k.enqueue(6) << " " << k.enqueue(3) << " enqueued\n ";
it is not specified in what order these functions will be called.
In your example, they are being called from right to left.
This means your queue is actually
{ 0, 3, 6, 9, 4 }
0 is there since your are skipping element 0 and going directly to element 1.
Your head is pointing to 1, thus you will dequeue 3.
You can read more here.

C++ -Problems in Stacking an array

I've been trying to figure out why my code isn't working correctly for the past few hours. Everything looks perfectly fine to me unless it's something I don't know about. I have asked my professor, but he can't seem to figure it out either. This code will completely ignore the if else statement in the push member function and will keep pushing after reaching the limit (in this case it's 5 elements). When it goes over the 5th element, and I check for the top, it shows the first implementation (element 0). I tried changing around my code by switching the member functions outside the class via scope resolution, but it's still no use. A different set of eyes would be greatly appreciated.
#include <iostream>
#include <cctype>
using namespace std;
class Stack
{
private:
static const int size = 5;
double myarr[size];
int t;
public:
Stack() { t = -1; }
void push(double element);
void pop();
void top();
void menu();
};
void Stack::push(double element)
{
if (t < size) {
t++;
myarr[t] = element;
}
else
cout << "Stack Limit Reach !!!" << endl;
}
void Stack::pop()
{
if (t >= 0) {
cout << "Element : " << myarr[t] << " was popped off the Stack " << endl;
t--;
}
else
cout << "No more elemnts in the Stack !!!" << endl;
}
void Stack::top()
{
if (t >= 0) {
cout << "Element : " << myarr[t] << " is at the top of the Stack " << endl;
}
else
cout << "No more elemnts in the Stack !!!" << endl;
}
void Stack::menu()
{
char choice = 'y';
int pick;
double elem;
while (toupper(choice) == 'Y');//while(choice == 'y' || choice == 'Y');
{
cout << "1. Push" << endl;
cout << "2. Pop" << endl;
cout << "3. Top" << endl;
cout << "4. Exit" << endl;
cin >> pick;
switch (pick)
{
case 1:
cout << "Enter the element: ";
cin >> elem;
cout << endl;
push(elem);
break;
case 2:
pop();
break;
case 3:
top();
break;
case 4:
choice = 'N';
break;
default:
cout << "Please select 1-4" << endl;
}
system("pause");
}
}
int main()
{
Stack obj;
obj.menu();
};
In your example code, the stack's size is 5 (which means array myarr has valid indices 0 through 4).
void Stack::push(double element)
{
if (t < size) {
t++;
myarr[t] = element;
}
else
cout << "Stack Limit Reach !!!" << endl;
}
Consider the case when t here is 4. The if tests true, so the block to add to myarr is entered. First thing that happens is you increment t, which is now 5. Then you use that as the index to store the value into myarr, which is out of bounds.
Try something like:
void Stack::push(double element)
{
if (t < size) {
myarr[t++] = element;
}
else
cout << "Stack Limit Reach !!!" << endl;
}
You are allowing 6 elements to be pushed onto the stack, and there's only room for 5.
Change:
if (t < size) {
t++;
to:
if (t < size-1) {
t++;
I understood your problem when you are searching for the top element you are not getting because whenever the stack becomes full for ex:-
assume you are inserting(below mentioned code) 5th element in 4th index it will be inserted and the value of t get incremented to 5 due to t++.
void Stack::push(double element)
{
if (t < size) {
t++;
myarr[t] = element;
}
else
cout << "Stack Limit Reach !!!" << endl;
}
but at the same time when you call top() function it checks for the index, and obviously 5 is greater that 0 so it enters the loop but index 5 contains '\0'
Character so there is an ambiguity with compiler
void Stack::top()
{
if (t >= 0) {
cout << "Element : " << myarr[t] << " is at the top of the Stack " << endl;
}
else
cout << "No more elemnts in the Stack !!!" << endl;
}
So the change that is required for the above code is just put a if statement by saying the compiler that if the stack is full then decrement t value by 1
void Stack::top()
{
if (t >= 0) {
if(t==size){t--;}
cout << "Element : " << myarr[t] << " is at the top of the Stack " << endl;
}
else
cout << "No more elemnts in the Stack !!!" << endl;
}
This may give you correct result
You skip myarr[0] then 5th element is saved to myarr[5] that is 6th element in myarr! (Accessing to elements of an array by index is zero based in C++)
Change:
Stack() { t = -1; }
to:
Stack() { t = 0; }
and
if (t < size) {
t++;
myarr[t] = element;
to:
if (t < size) {
myarr[t++] = element;

Access Violation error when I debug my priority queue program

I am getting a access violation error in my code when I try run it. The program is a priority queue that inserts a value and prints the heap after each insertion and min extract.
Header File:
#pragma once
/*
Header file for the priority queue class
*/
#ifndef PRIORITYQUEUE_H
#define PRIORITYQUEUE_H
class priorityQueue
{
private:
int size;
int *data;
public:
static const int CAPACITY = 50;
priorityQueue();//constructor
~priorityQueue();//destructor
int getParent(int index);
int getLeftChild(int index);
int getRightChild(int index);
void swap(int &, int &);
void insert(int item); //enqueue - heap_insert
void printArray(int []);
void heapify(int index);
//remove and return the smallest item currently in the priority queue
int extractMin();//dequeue
bool empty() const;
int min() const; //return the smallest item
};
#endif
Main Code:
#include <iostream>
#include "priorityQueue.h"
using namespace std;
int main()
{
priorityQueue myqueue; //class object
if (myqueue.empty())
cout << "My priority Queue is empty\n" << endl; //prompt
myqueue.insert(59); //Insert value into queue
cout << "After inserting 59 Priority Queue has" << endl;
myqueue.insert(41);
cout << "After inserting 41 Priority Queue has" << endl;
myqueue.insert(25);
cout << "After inserting 25 Priority Queue has" << endl;
myqueue.insert(12);
cout << "After inserting 12 Priority Queue has" << endl;
myqueue.insert(91);
cout << "After inserting 91 Priority Queue has" << endl;
myqueue.min();
myqueue.extractMin();
cout << "After extracting the minimum value Priority Queue has" << endl;
myqueue.insert(34);
cout << "After inserting 34 Priority Queue has" << endl;
myqueue.insert(63);
cout << "After inserting 63 Priority Queue has" << endl;
myqueue.extractMin();
cout << "After extracting the minimum value Priority Queue has" << endl;
myqueue.insert(75);
cout << "After inserting 75 Priority Queue has" << endl;
myqueue.insert(85);
cout << "After inserting 85 Priority Queue has" << endl;
myqueue.extractMin();
cout << "After extracting the minimum value Priority Queue has" << endl;
cout <<"Minimum value is " ;
cout << myqueue.min() <<endl; //prints out heap min
system("pause");
return 0;
}
priorityQueue::priorityQueue() //constructor
{
size = CAPACITY;
&data[size];
}
priorityQueue::~priorityQueue() //destructor
{
}
int priorityQueue::getParent(int index) //finds parent
{
return (index - 1) / 2;
}
int priorityQueue::getLeftChild(int index) //finds left child
{
return (2 * index) + 1;
}
int priorityQueue::getRightChild(int index) //find right child
{
return (2 * index) + 2;
}
void priorityQueue::swap(int& item1, int& item2) //swaps value of two variables
{
int temp = item1;
item1 = item2;
item2 = temp;
}
void priorityQueue::heapify(int index) //heapifies the heap
{
int largest = index;
int l = getLeftChild(index);
int r = getRightChild(index);
if (l < size && data[l] > data[index])
{
largest = l;
}
if (r < size && data[r] > data[largest])
{
largest = r;
}
if (largest != index)
{
swap(data[index], data[largest]);
heapify(data[size]);
}
}
void priorityQueue::printArray(int []) //prints array
{
for (int i = 0; i < CAPACITY; i++)
{
cout << data[i] << ", ";
}
}
int priorityQueue::extractMin() //finds min and removes it
{
int min = data[0];
data[0] = data[size - 1];
size - 1;
heapify(data[size]);
return min;
}
int priorityQueue::min() const // finds min
{
return data[0];
}
bool priorityQueue::empty() const // checks if heap is empty
{
if (data == NULL)
{
return true;
}
else
{
return false;
}
}
void priorityQueue::insert(int Item) //inserts values into heap
{
size += 1;
int i = size - 1;
while (i > 0 && data[getParent(i)] < Item)
{
data[i] = data[getParent(i)];
i = getParent(i);
}
data[i] = Item;
}
In your constructor, &data[size]; does nothing. You need to allocate some memory for it, possibly using new - data = new int[size] - or use a smart pointer.

C++ delete error

I'm new to C++ and I'm trying to code a linked-list based queue. My test program worked fine until I added delete to the dequeue function. Then I get the error:
malloc: *** error for object 0x7f8a61403a00: pointer being freed was not allocated
Any help would be appreciated.
#include <string>
#include "queue.h"
#include <iostream>
using namespace std;
Queue::Queue() { // Constructs a new empty queue.
current_size = 0; // number of elements in queue
front_p = NULL; // first element in queue
back_p = NULL; // last element in queue
}
Queue::Queue( const Queue& q ) {// Copy constructor.
// nothing to copy if queue empty
if (q.current_size == 0) {
return;
}
// queue not empty
else {
node * p = q.front_p;
node * n;
// assign front pointer
n = new node(p -> data, NULL);
front_p = n;
p = p -> next;
// middle elements
while (p -> next != NULL) {
n -> next = p;
n = new node(p -> data, NULL);
p = p -> next;
}
// assign back pointer
n = new node(p -> data, NULL);
back_p = n;
current_size = q.current_size;
}
}
void Queue::enqueue( int item ) { // Enqueues <item> to back
node * n = new node(item, NULL);
// first item in queue, front & back ptrs point to same element
if (back_p == NULL) {
front_p = n;
back_p = n;
}
else {
back_p -> next = n;
back_p = n;
}
current_size++;
}
int Queue::dequeue() { // removes and returns the front item.
// empty queue
if (current_size == 0) {
return -1;
}
int item = front();
node * p = front_p;
if (current_size == 1) {
front_p = NULL;
back_p = NULL;
delete p;
current_size--;
return item;
}
else {
front_p = front_p -> next;
delete p;
current_size--;
return item;
}
}
test file
//test file
#include <iostream>
#include "queue.h"
using namespace std;
int main(void) {
Queue q1;
cout << "Create a new queue q1" << endl;
cout << "Size of q1 \t" << q1.size() << endl;
cout << "Is q1 empty? \t" << q1.empty() << endl;
cout << endl << endl;
cout << "enqueue \t1,2,3,4,5" << endl;
q1.enqueue(1);
q1.enqueue(2);
q1.enqueue(3);
q1.enqueue(4);
q1.enqueue(5);
cout << "front of q1 \t" << q1.front() << endl;
cout << "size of q1 \t" << q1.size() << endl << endl;
cout << "q2 is a deep copy of q1" << endl;
Queue q2(q1);
cout << "front of q2 \t" << q2.front() << endl;
cout << "size of q2 \t" << q2.size() << endl << endl;
cout << "removed 4 from q1" << endl;
q1.remove(4);
cout << "removed 2 from q2" << endl;
q2.remove(2);
cout << endl;
cout << "print out remaining elements of q1" << endl;
int N = q1.size();
for(int i=0; i < N; i++) {
cout << q1.dequeue() << " ";
}
cout << endl << endl;
cout << "print out remaining elements of q2" << endl;
N = q2.size();
for(int i=0; i < N; i++) {
cout << q2.dequeue() << " ";
}
cout << endl;
}
header file
class Queue
{
public:
Queue(); // Constructs a new empty queue.
Queue( const Queue& q );// Copy constructor.
~Queue();// Destructor.
void enqueue( int item ); // Enqueues <item>.
int dequeue(); // Dequeues the front item.
int front(); // Returns the front item without dequeuing it.
bool empty(); // Returns true iff the queue contains no items.
int size(); // Returns the current number of items in the queue.
bool remove(int item); // If <item> occurs in the queue, removes the
// first occurrence of <item> and returns true; otherwise returns false.
private:
class node // node type for the linked list
{
public:
node(int new_data, node * next_node){
data = new_data ;
next = next_node ;
}
int data ;
node * next ;
};
node * front_p ; // pointer to the (node containing the) next item
// which to be dequeud, or NULL if the queue is empty.
node * back_p ; // pointer to the (node containing the) last item
// which was enqueued, or NULL if the queue is empty.
int current_size ; // current number of elements in the queue.
};
There are other issues with the code, but the most immediate one is that your copy-constructor is broken.
In this cycle
while (p -> next != NULL) {
n -> next = p;
n = new node(p -> data, NULL);
p = p -> next;
}
p is a pointer to an element of a source queue q. Meanwhile, n is an element of the new queue. By doing n -> next = p; you are making the new queue nodes to link into the source queue node chain. This creates a completely nonsensical node linkage structure, which falls apart later.

C++: First character in queue is wrong

I'm currently working on an assignment for school that says I should create a Queue. It seems to be working. The only problem is that there is an unexpected char at the beginning of my Queue. I use class CQueue to push and pop values from the queue. It is essential that I use this class instead of something like std::queue or deque.
class CQueue
{
private:
char *bottom_;
char *top_;
int size_;
public:
CQueue(int n = 20){
bottom_ = new char[n];
top_ = bottom_;
size_ = n;
}
void push(char c){
*top_ = c;
top_++;
}
int num_items() {
return (top_ - bottom_ );
}
char pop(){
bottom_++;
return *bottom_;
}
void print(){
cout << "Queue currently holds " << num_items() << " items: " ;
for (char *element=top_; element > bottom_; element--) {
cout << " " << *element;
}
cout << "\n";
}
This is my main method:
int main(){
CQueue q(10);
q.push('s');q.push('t');q.push('a');q.push('c');q.push('k');
q.print();
cout << "Popped value is: " << q.pop() << "\n";
q.print();
q.push('!');
q.push('?');
cout << "Popped value is: " << q.pop() << "\n";
q.print();
while (!q.empty()) q.pop();
if (q.num_items() != 0) {
cout << "Error: Stack is corrupt!\n";
}
q.print();
cout << "End of program reached\n"<< endl;
return 0;
When I run this code the queue gets filled but *bottom_ is replaced with a '=' symbol. This is my output:
Queue currently holds 5 items: ═ k c a t
Popped value is: t
Queue currently holds 4 items: ═ k c a
Popped value is: a
Queue currently holds 5 items: ═ ? ! k c
Queue currently holds 0 items:
End of program reached
I've been banging my head over this one for a while now so I hope that maybe you can shed some light on this problem!
As your push() is defined, *top_ is NOT in queue. It is one element after the end of queue. Therefore, you should define your print() to iterate from top_ - 1.
Also as #stellarossa mentioned, you should return the character pointed by bottom_ before increment. That is,
char pop() { return *(bottom_++); }
char pop(){
bottom_++;
return *bottom_;
}
you're incrementing your pointer and then returning the value. it should be the other way around.
Are you using an array or linked list?
Keep it simple and use an array with a count variable.
#include <iostream>
using namespace std;
class CQueue
{
private:
char * q;
int size_;
int count;
public:
CQueue(int n = 20){
q = new char[n];
size_ = n;
count = 0;
}
void push(char c){
assert(count != size);
q[count] = c;
count++;
}
int num_items() {
return count;
}
char pop() {
assert(count != 0);
char ret = q[count-1];
count--;
return ret;
}
void print(){
cout << "Queue currently holds " << num_items() << " items: " ;
for (int i = 0; i < count; i++) {
cout << " " << q[i];
}
cout << "\n";
}
At least two bugs my friend.
1) The print() method starts printing *top which is 1 past the last member. Should be:
for (char *element=top_-1; element >= bottom_; element--) {
cout << " " << *element;
}
2) The pop() method is wrong:
should be:
char pop(){
return (top_ > bottom_) ? *top_-- : 0;
}