Sorting a queue - C/C++ - c++

I have created a queue that in each node there are three information. I want to create a member function in class that sorts the queue when called. I wish to have the queue sorted by time? (it is an int and a member of q_node). This queue needs to be sorted in such a way that the lowest value of 'time' is in the front and it is sorted in increasing order.
My code for my Queue is found below:
typedef struct Qnode{
int time;
char name[10];
char value;
struct Qnode *q_next;
struct Qnode *q_prev;
} q_node;
class Queue{
private:
q_node *q_rear;
q_node *q_front;
int number;
public:
Queue();
void enqueue(int time, char *s, char value);
q_node *q_top(){
return q_front;
}
void dequeue();
void display();
void queueSort();
bool isEmpty();
};
Queue::Queue(){
q_rear = NULL;
q_front = NULL;
number = 0;
}
bool Queue::isEmpty(){
if (q_front == NULL)
return true;
else
return false;
}
void Queue::enqueue(int t, char *n, char v){
q_node *q_temp = new q_node;
q_temp->time = t;
strcpy(q_temp->name , n);
q_temp->value = v;
q_temp->q_next = NULL;
if(q_front == NULL){
q_front = q_temp;
}
else{
q_rear->q_next = q_temp;
}
q_rear = q_temp;
number++;
}
void Queue::dequeue(){
q_node *q_temp = new q_node;
q_temp = q_front;
q_front = q_front -> q_next;
number--;
delete q_temp;
}
void Queue::display(){
q_node *p = new q_node;
p = q_front;
while(p!=NULL){
cout<< "\ntime: " << p->time;
cout<< "\nname: " << p->name;
cout<< "\nvalue: " << p->value;
cout << endl;
p = p->q_next;
}
}
void Queue::queueSort(){
//Code for sorting
}

One way is to dump the queue into an array or vector by using dequeue, use std::sort and then rebuild the queue from scratch by using your enqueue function. This is clean and avoids messing up with pointers. This is also optimal because running time is dominated by time it takes to sort.
Something like:
v = vector of nodes
while(Q.isEmpty() == false)
{ v.push_back(*Q.top());
Q.dequeue();
}
sort(v.begin(), v.end(), cmp);
for(int i = 0; i < v.size(); i++)
{ Q.enqueue(v[i].time, v[i].name, v[i].value);
}
Where cmp compares nodes by time.

Find the node with the smallest time field, remove it from the list and make it the head of a new list. Then continue to do this, appending the nodes to the new list, in a loop while the original list is not empty. When the original list is empty, take the new (sorted) list and make it the new queue.
It might not be especially efficient, but should work fine.

Related

why does my dynamically allocated array implementation of queue data structure NOT update on the second call?

I'm learning Data Structures as required of me by my university. I've implemented the Queue DS using Dynamic Array but it somehow doesn't work. It updates the value on the first enqueue method call but from the second call onward, it does nothing.
MY CODE
#include <iostream>
#define MAXSIZE 8
class Queue
{
private:
int *arr;
int front;
int rear;
int itemsCount;
public:
Queue()
{
arr = new int[MAXSIZE];
front = -1;
rear = -1;
itemsCount = 0;
}
~Queue()
{
delete[] arr;
}
int dequeue()
{
int x = arr[front];
front = (front + 1) % MAXSIZE;
itemsCount--;
return x;
}
void enqueue(int x)
{
if (empty())
{
front++;
}
rear = (rear + 1) % MAXSIZE;
arr[rear] = x;
itemsCount++;
}
bool full() const
{
if (itemsCount == MAXSIZE)
return true;
return false;
}
bool empty() const
{
if (itemsCount == 0)
return true;
return false;
}
};
int main(int argc, char const *argv[])
{
Queue myQ;
myQ.enqueue(11);
myQ.enqueue(22); // This doesn't update the array at 1th index
myQ.enqueue(33);
myQ.enqueue(44);
myQ.enqueue(55);
myQ.enqueue(66);
myQ.enqueue(77);
myQ.enqueue(88);
std::cout << myQ.dequeue() << std::endl;
return 0;
}
P.S I know the implementation is incomplete and I haven't handled all the edge cases yet. That's because I couldn't get the normal case to work.
P.P.S It works with Static Array. But not with Dynamically allocated one.
Apparently, the array was being updated and the program was running as it should have when I performed the dequeue operations and displayed the values on screen. But the debugger somehow was only showing the value at the first index of the dynamically allocated array.
array pointer

C++ Data Strutures Queue: Find the largest element in the queue using for loop

I need to find the largest element in an unsorted queue, remove it and store it in an auxiliary queue, then place it back as the first element in the main queue, WITHOUT using the standard queue functions from C++.
I tried to use a for loop to go through the queue and search for the largest element, but it didn't work. Any suggestion on how to do it properly?
//The queue was created as a class as follows:
class Queue{
private:
int arrayqueue[size];
int start, end, counter;
public:
Queue();
bool empty();
bool full();
bool insert(int item);
bool remove();
bool front(int &item);
int counter_size();
void copy(Queue &F);
bool equal(Queue &F);
void print();
int largest_value(Queue &F,int n);
};
Queue::Queue(){
counter = 0;
start = 0;
end = size -1;
}
This is the function I tried to build to find the largest element in the queue and store in the auxiliary queue:
//Create an auxiliary queue
//Find the largest element in the main queue, then remove it and insert it in the aux queue
int Queue::largest_value(Queue &F,int n){
//int *Queue;
// n is the size of the queue
Queue aux;
int largest = Queue[0];
for(int i = 1;i <n; i++) {
if(largest < Queue[i])
largest = Queue[i];
}
F.remove();
aux.insert(largest);
return largest;
}
Function to verify if it's empty:
bool Queue::empty(){
if(counter == 0)
return true;
else
return false;
}
The function to remove elements:
bool Queue::remove(){
if(empty()==true)
return false;
if(start==size-1)
start = 0;
else
start++;
counter--;
return true;
}
Try something more like this:
class Queue{
private:
int arrayqueue[size];
int ... counter;
public:
...
bool remove_largest_value(int &value);
};
...
bool Queue::remove_largest_value(int &value) {
if (counter == 0)
return false;
int largest = 0;
for(int i = 1; i < counter; ++i) {
if (arrayqueue[largest] < arrayqueue[i])
largest = i;
}
value = arrayqueue[largest];
for(int i = largest + 1; i < counter; ++i) {
arrayqueue[i-1] = arrayqueue[i];
}
--counter;
return true;
}
Then you can do this:
Queue main;
// populate main as needed...
Queue aux;
int item;
if (main.remove_largest_value(item))
{
aux.insert(item);
...
main.insert(item);
}

Bus error c++ Run correctly with small array, run time error with big array

Can anyone help me? The printAll(), listprintAll() and sizeLL() work correctly when hashSize is small but didn't work with big number, like number 9973.
printAll() and hashStats() are both method in Class Table, printALL() calls listprintAll() and hashStats() calls sizeLL() from another Structure.
All functions work correctly with give small hashSize.
Sorry about the pic and confused. first time here.. I'm using MacBook to do this work.
In list.h
struct Node{
string key;
int value;
Node *next;
Node(const string &theKey, int theValue);
Node(const string &theKey, int theValue, Node *n);
};
typedef Node * ListType;
In Table.h
class Table {
public:
static const int HASH_SIZE = 9973; // a prime number
// create an empty table, i.e., one where numEntries() is 0
// (Underlying hash table is HASH_SIZE.)
Table();
// create an empty table, i.e., one where numEntries() is 0
// such that the underlying hash table is hSize
Table(unsigned int hSize);
unsigned int hashSize; // size of the hash table
ListType * data; // (used in hashCode method above)
}
In list.cpp
void listprintAll(ListType list){
if(list ==NULL) {
cout << "[ ]" <<endl;
return;}
else{
Node * p=list;
while(p!= NULL){
cout << p->key << " " << p->value << ",";
p=p->next;
}
cout <<endl;
return;
}
}
int sizeLL(ListType list){
if(list ==NULL) {
return 0;}
else{
int count=0;
Node * p=list;
while(p!= NULL){
p=p->next;
count++;
}
return count;
}
In Table.cpp
Table::Table() {
hashSize=HASH_SIZE;
data = new ListType[hashSize];
}
Table::Table(unsigned int hSize) {
hashSize=hSize;
data = new ListType[hashSize];
}
void Table::printAll() const {
for(int i=0;i<hashSize;i++){
listprintAll(data[i]);
}
}
void Table::hashStats(ostream &out) const {
out << "number of buckets: "<< hashSize <<endl;
int number = numEntriesOfTable();
out << "number of entries: "<< number <<endl;
int countN0=0;
int longest=0;
int temp;
if(number!=0){
for(int i=0;i<hashSize;i++){
temp=sizeLL(data[i]);
if(temp!=0){
countN0++;
if(temp > longest){
longest=temp;
}
}
}
}
out << "number of non-empty buckets: "<< countN0 << endl;
out << "longest chain : "<< longest << endl;
}
You're allocating memory for data in your constructors but not initializing it. This leaves all your pointers with indeterminate values in them, which could be 0/NULL or could be some other random pointer value. When you try to dereference these you get the crash.
You'll want to zero out your allocated memory in the constructor, using a loop, memset, or something along those lines.

Heap memory corruption c++ templated class

I'm just a humble student looking to further my knowledge about the C++ language. My professor isn't helping! I think the title along with comments in-code explain my issues clearly.
#ifndef H_Htable
#define H_Htable
//****************************************************************
// Author: D.S. Malik
//
// This class specifies the members to implement a hash table as
// an ADT. It uses quadratic probing to resolve collisions.
//****************************************************************
#include <iostream>
#include <cassert>
using namespace std;
template <class elemType>
class hashT
{
public:
void insert(int hashIndex, const elemType& rec);
//Function to insert an item in the hash table. The first
//parameter specifies the initial hash index of the item to
//be inserted. The item to be inserted is specified by the
//parameter rec.
//Postcondition: If an empty position is found in the hash
// table, rec is inserted and the length is incremented by
// one; otherwise, an appropriate error message is
// displayed.
//sequential search
bool search(int& hashIndex, const elemType& rec, bool found = false) const;
//Function to determine whether the item specified by the
//parameter rec is in the hash table. The parameter hashIndex
//specifies the initial hash index of rec.
//Postcondition: If rec is found, found is set to true and
// hashIndex specifies the position where rec is found;
// otherwise, found is set to false.
bool isItemAtEqual(int hashIndex, const elemType& rec) const;
//Function to determine whether the item specified by the
//parameter rec is the same as the item in the hash table
//at position hashIndex.
//Postcondition: Returns true if HTable[hashIndex] == rec;
// otherwise, returns false.
void retrieve(int hashIndex, elemType& rec) const;
//Function to retrieve the item at position hashIndex.
//Postcondition: If the table has an item at position
// hashIndex, it is copied into rec.
void remove(int hashIndex, const elemType& rec);
//Function to remove an item from the hash table.
//Postcondition: Given the initial hashIndex, if rec is found
// in the table it is removed; otherwise, an appropriate
// error message is displayed.
void print() const;
//Function to output the data.
//provide for both int and string data types in the hash table
hashT(int size = 101, bool isIntTable = true);
//constructor
//Postcondition: Create the arrays HTTable and indexStatusList;
// initialize the array indexStatusList to 0; length = 0;
// HTSize = size; and the default array size is 101.
~hashT();
//destructor
//Postcondition: Array HTable and indexStatusList are deleted.
private:
elemType *HTable; //pointer to the hash table
int *indexStatusList; //pointer to the array indicating the
//status of a position in the hash table
int length; //number of items in the hash table
int HTSize; //maximum size of the hash table
};
template <class elemType>
void hashT<elemType>::insert(int hashIndex, const elemType& rec)
{
int pCount;
int inc;
pCount = 0;
inc = 1;
while (indexStatusList[hashIndex] == 1
&& HTable[hashIndex] != rec
&& pCount < HTSize / 2)
{
pCount++;
hashIndex = (hashIndex + inc) % HTSize;
inc = inc + 2;
}
if (indexStatusList[hashIndex] != 1)
{
HTable[hashIndex] = rec;
indexStatusList[hashIndex] = 1;
length++;
}
else
if (HTable[hashIndex] == rec)
cerr << "Error: No duplicates are allowed." << endl;
else
cerr << "Error: The table is full. "
<< "Unable to resolve the collision." << endl;
}
//sequential search
template <class elemType>
bool hashT<elemType>::search(int& hashIndex, const elemType& rec, bool found) const
{
for (int i = 0; i < HTSize; i++) {
if (HTable[i] == rec) { //assuming no repeat data
found = true;
hashIndex = i;
break;
}
}
return found;
}
template <class elemType>
bool hashT<elemType>::isItemAtEqual(int hashIndex, const elemType& rec) const
{
//first make sure the item has not been removed
if (indexStatusList[hashIndex] != -1) {
//make equality comparison
if (HTable[hashIndex] == rec)
return true;
else
return false; //comparison fails
}
else
{
std::cerr << "isItemEqual(): Item has been removed" << endl;
return false;
}
}
template <class elemType>
void hashT<elemType>::retrieve(int hashIndex, elemType& rec) const
{
if (indexStatusList[hashIndex] != -1)
rec = HTable[hashIndex];
else
std::cerr << "retrieve(): item has been removed" << endl;
}
template <class elemType>
void hashT<elemType>::remove(int hashIndex, const elemType& rec)
{
//make sure the item hasn't already been removed
if (indexStatusList[hashIndex] != -1) {
bool isInList = hashT<elemType>::search(hashIndex, rec);
//update the status
if (isInList)
{
indexStatusList[hashIndex] = -1;
length--; //decrement length
}
else
std::cerr << "hasT::remove() could not remove the specified item" << endl;
}
else
{
std::cerr << "remove(): Item has already been removed from the table" << endl;
}
}
template <class elemType>
void hashT<elemType>::print() const
{
std::cout << "Hash Table Data: " << endl;
for (int i = 0; i < (length - 5); i++) {
elemType item = HTable[i];
//std::cout << item << " ";
}
}
template <class elemType>
hashT<elemType>::hashT(int size, bool isIntTable)
{
HTable = new elemType[]; //is this right? HTable is an array just like indexStatusList
HTSize = size;
length = 0;
indexStatusList = new int[0]; //I think this one works?
}
template <class elemType>
hashT<elemType>::~hashT() //deleting always causes heap errors!!!
//says writing to unallocated memory -- debugging shows otherwise
{
//delete[] HTable;
//delete[] indexStatusList; //still causing errors -- error now not associated with any particular line (of my code)
}
#endif
I've kept increasing my bounds checking security when instantiating hashT in main. I'm convinced it is because my data members are being initialized incorrectly. This is one error message I get after trying a few things: "Unhandled exception at 0x773F627C (ntdll.dll) in exercise7Chap9.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77426480)."
finally, here's main just in case:
#include <iostream>
#include "hashT.h"
int main() {
//add one item and test for equality
//hashT<int> ht = hashT<int>(20);
//ht.insert(0, 1);
//bool itemInsertSuccess = ht.isItemAtEqual(0, 1);
//if (itemInsertSuccess)
// std::cout << "first test has succeeded" << endl;
//else
// std::cout << "first test has failed" << endl;
////remove item and make sure isItemEqual returns false
//ht.remove(0, 1);
//bool itemRemoved = ht.isItemAtEqual(0, 1);
//if (!itemRemoved)
// std::cout << "second test passed" << endl;
//else
// std::cout << "second test failed" << endl;
//add many items then make sure search() works
hashT<int> ht1 = hashT<int>(51);
for (int i = 0; i < 10; i++)
ht1.insert(i, i);
int indx = -1;
ht1.search(indx, 0);
if (indx == 25)
std::cout << "Test 3 has passed" << endl;
else
std::cout << "Test 3 has failed" << endl;
//print data then test retrieve() and print a single item
/*ht1.print();
int item = -1;
ht1.retrieve(10, item);
if (item != -1) {
std::cout << item << endl;
std::cout << "test 4 has passed" << endl;
}
else
std::cout << "test 4 has failed" << endl;
hashT<int> HtRetrieve = hashT<int>(10);
HtRetrieve.insert(0, 0);
int it = -1;
HtRetrieve.retrieve(0, it);
std::cout << it << endl;*/
char stop;
std::cin >> stop;
//return 0;
}
In your case here, scrap the variable isIntTable. Templates are a compile-time construct and run-time values won't influence how the template is compiled into a class in any way.
Then, in your constructor, just use the template type as the one you are allocating.
template <class elemType>
hashT<elemType>::hashT(int size)
{
HTable = new elemType[size];
length = 0;
indexStatusList = new int[0];
}
However, this could be much better. Consider using initialisation instead of assignation:
hashT<elemType>::hashT(int size) :
HTable{new elemType[size]},
length{size},
indexStatusList{int[size]} { /* empty constructor */ }
And it can be even better. Consider using smart pointer instead of raw owning pointers and vectors instead of dynamic allocated array:
template<typename T>
struct hashT {
// using the right type for size
hashT(std::size_t size) : pointerToOneT{std::make_unique<T>()}, HTable(size) {}
// make_unique is the `new` for unique pointers
// no need for destructors, the vector and unique_ptr are freeing themselves
private:
std::unique_ptr<T> pointerToOneT;
std::vector<T> HTable;
std::vector<int> indexStatusList;
};
If you don't want to use std::vector, you can always use std::unique_ptr<T[]>, which is a dynamically allocated array that free itself.
template<typename T>
struct hashT {
// using the right type for size
hashT(std::size_t size) :
HTable{std::make_unique<T[]>(size)},
indexStatusList(std::make_unique<int[]>(size)) {}
private:
std::unique_ptr<T[]> HTable;
std::unique_ptr<int[]> indexStatusList;
};
EDIT
In your actual destructor, the problem is that you initialized the int* with the new[] but you are using delete. To delete an array, you must use delete[]
template <class elemType>
hashT<elemType>::~hashT()
{
delete HTable;
delete[] indexStatusList;
}
Turns out this heap corruption was caused by my lack of understanding dynamic arrays in C++.
My incorrect initialization of the arrays HTable and indexStatusList were: Htable = new elemType();, HTable = new elemType[]; and indexStatusList = new int[0];
I simply needed to add the size as an argument (never seen a size argument passed in brackets before!)
Here is the working constructor:
//constructor
template <class elemType>
hashT<elemType>::hashT(int size)
{
HTable = new elemType[size]; // pass size so the compiler knows what to allocate and deallocate
HTSize = size;
length = 0;
indexStatusList = new int[size];
}
working destructor:
template <class elemType>
hashT<elemType>::~hashT()
{
delete[] HTable;
delete[] indexStatusList;
}

C++ Circular queue class with a length of 100

I've got some questions on how to create and use a circular queue class in C++. The questions are in the code as comments because I am looking for general pointers on how to see if I'm on the right track.
Edit:
Adding the specific questions here for clarity:
Do I need a pointer for both the head and the tail of the queue?
Do I initialize a queue like this or is there a better way?
How do I dequeue and return the correct value?
The code:
#include <iostream>
#include <stdexcept>
using namespace std;
class Queue{
private:
int maxSize;
int *data; // Do I maybe need one for head and one for tail?
int counter; // Used to count the amount of elements in the queue.
public:
Queue();
Queue(int max=100);
~Queue();
void clear();
bool empty() const;
bool full() const;
int dequeue() throw (length_error);
void enqueue(int value) throw (length_error);
int length();
};
Queue :: Queue() // Is this the correct way to initialize the queue?
{
data[100];
counter = 0;
maxSize = 100;
}
void Queue::clear()
{
data = NULL;
}
bool Queue::empty()const
{
if(counter == 0)
return true;
return false;
}
bool Queue::full()const
{
if(counter == 100)
return true;
return false;
}
int Queue::length()
{
return counter;
}
int Queue::dequeue() throw (length_error) // How do I get the correct element and then return it.
{
if(counter >= 0)
{
counter--;
return counter;
}
return counter;
}
void Queue::enqueue(int value) throw(length_error)
{
if(counter < maxSize)
{
data[counter] = value;
counter++;
cout << "Adds the number at the end if there is room for it." << endl;
}
else
;// throw(length_error);
}
int main()
{
Queue minQueue;
minQueue.enqueue(10);
minQueue.enqueue(12);
minQueue.enqueue(14);
minQueue.enqueue(16);
minQueue.enqueue(18);
cout << "Empty: " << minQueue.empty() << endl;
cout << "Full: " << minQueue.full() << endl;
cout << "Length: " << minQueue.length() << endl;
minQueue.dequeue();
minQueue.clear();
system("pause");
}
Your code has some issues.
class Queue{
// ...
public:
// Queue(); // deleted this line, since it collides with the next ctor declation.
// A ctor with one optional argument includes a ctor with no arguments
Queue(int max=100);
~Queue();
}
//...
Queue::Queue(int max) // argument required!
{
data = new int[max]; // this is probably what you want
counter = 0;
maxSize = max;
}
void Queue::clear()
{
delete[] data; // see above, must match the allocation
}
int Queue::dequeue() throw (length_error)
{
if(counter > 0) // !!!! dont't decrease when 0
{
counter--;
return data[counter];
}
else
throw(length_error()); // an exception class length_error must exist!
}
These are a few starting points, fill the remaining gaps by yourself.