Implementing an Enqueue At Offset Method for a CircularQueue - c++

I am currently working on a project to simulate Traffic Flow around a Roundabout and in order to do this I have built 2 data structures "LinearQueue" and "CircularQueue" both implemented using Linked List struct nodes.
My CircularQueue class has methods to enqueue and dequeue as is typical of any circular queue type structure, however as I have 4 (well 8 actually given roads going in both directions) LinearQueue objects that will need to link at quarter capacity intervals of the CircularQueue (roundabout) object I require a method to enqueue items at an offset from the rear or front of the queue and I am unsure of how to implement this properly.
Here is my CircularQueue::enqueue(Type) method:
Type enqueue(Type& item) {
// if the currentSize is greater than the maximum allowed capacity,
// throw a CircularQueueException
if (this->currentSize == this->maxCapacity) {
throw CircularQueueException("Circular queue is full, cannot enqueue any more objects!");
}
// if the front of this CQ object is null, assign first element of circularQueue array to
// front of queue and set the rear to the front (single-element queue)
if (this->front == 0) {
this->front = this->circularQueue[0];
this->front->head = item;
this->rear = this->front;
}
// else if the front is not-null, assign the tail of the rear of this CQ object
// to a new CQNode with head = item, and shift the new rear to tail of old rear
else {
this->rear->tail = new CQNode(item);
this->rear = this->rear->tail;
// if the currentSize of the queue is 1 less than the maximum capacity, then
// point to tail of the rear to the front of the queue
if (this->currentSize == (this->maxCapacity - 1))
this->rear->tail = this->front;
}
// increment the currentSize of this CircularQueue instance by 1 indicating enqueue successful
this->currentSize++;
return item;
}
where currentSize and maxCapacity are integer field variables storing the current filled queue size and maximum allowed capacity, respectively. Front and rear are pointers to the following node structure:
struct CQNode {
Type head;
CQNode* tail;
CQNode() {
//this->head = 0;
this->tail = 0;
}
CQNode(Type& head, CQNode* tail = 0) {
this->head = head;
this->tail = tail;
}
};
And Type is a typename given in the template of the class.
I currently only have the following for my offset enqueue method:
Type enqueue(Type& item, int offset) {
// if the offset given is 0, then simply call overloaded enqueue with just the item
if (offset == 0) {
return enqueue(item);
}
Type* itemPtr = &item;
if (itemPtr == 0) {
throw std::invalid_argument("Item to be enqueued onto Circular Queue cannot be null!");
}
if (this->currentSize == this->maxCapacity) {
throw CircularQueueException("Circular queue is full, cannot enqueue any more items.");
}
}
I'm just struggling to find where to start with the method, as I can see plenty of problems with null pointers by enqueuing and dequeuing objects at different offsets in my CircularQueue.

Related

Selection sort in single linked list without using swap

I have been trying to solve the selection sort in single linked list without using swap nodes. Using a temp list to store nodes and assign the current list with a new one
//my addlastnode function
void AddLastNODE(LIST &mylist, NODE *p)
{
//Check the list is empty or not
if(isEmpty(mylist))
mylist.pHead = mylist.pTail = p;
else
mylist.pTail->pNext = p;
mylist.pTail = p;
}
void selectionSort(LIST &mylist)
{
//Initialize a temp list to store nodes
LIST mylisttemp;
IntList(mylisttemp);
//Create node
NODE *p;
NODE *i;
//Create min node
NODE *min;
//Check if list is empty or has one node
if(mylist.pHead == mylist.pTail)
return;
//Traverse the list till the last node
for(p=mylist.pHead; p->pNext!=NULL && p!=NULL; p = p->pNext)
{
min=p;
for(i=p->pNext; i!=NULL;i=i->pNext)
{
////Find the smallest data in list
if(i->data < min->data)
min=i;
}
////Add the smallest to a new list
AddLastNODE(mylisttemp, min);
}
//Fill the current list to the new list
if(!isEmpty(mylisttemp))
mylist = mylisttemp;
}
Your code does not reduce the list you are selecting nodes from: the selected node should be removed from it. To make that happen, you need a reference to the node before the selected node, so that you can rewire the list to exclude that selected node.
There is also a small issue in your AddLastNODE function: it does not force the tail node to have a null as pNext pointer. This may be a cause of errors when the function is called with a node that still has a non-null pNext pointer. Secondly, the indentation is off around the else block. It does not lead to a bug in this case, but still it is better to avoid the confusion:
void AddLastNODE(LIST &mylist, NODE *p)
{
if(isEmpty(mylist))
mylist.pHead = p;
else
mylist.pTail->pNext = p;
mylist.pTail = p; // indentation!
p->pNext = nullptr; // <--- better safe than sorry!
}
Then to the main algorithm. It is quite tedious to work with a previous node reference when looking for the node with the minimum value. It helps a bit when you temporarily make the input list cyclic:
void selectionSort(LIST &mylist) {
if (mylist.pHead == mylist.pTail) return;
// Make list temporarily cyclic
mylist.pTail->pNext = mylist.pHead;
LIST mytemplist;
IntList(mytemplist);
while (mylist.pHead != mylist.pTail) {
// Select node:
NODE * beforemin = mylist.pTail;
for (NODE * prev = mylist.pHead; prev != mylist.pTail; prev = prev->pNext) {
if (prev->pNext->data < beforemin->pNext->data) {
beforemin = prev;
}
}
NODE * min = beforemin->pNext;
// Extract selected node:
if (min == mylist.pTail) mylist.pTail = beforemin;
if (min == mylist.pHead) mylist.pHead = min->pNext;
beforemin->pNext = min->pNext;
// And insert it:
AddLastNODE(mytemplist, min);
}
// Move last remaining node
AddLastNODE(mytemplist, mylist.pHead);
// Copy back
mylist = mytemplist;
}
As a side note: You might even want to always keep your list cyclic. This will mean some changes in other functions you may have, as there will be no pNext pointers that are null then.

why java AbstractQueuedSynchronizer next link is not atomically set as part of insertion

As Doug Lea point in the [The java.util.concurrent Synchronizer Framework
][1]http://gee.cs.oswego.edu/dl/papers/aqs.pdf that
But because there are no applicable techniques for lock-free atomic insertion of double-linked list nodes using compareAndSet, this link is not atomically set as part of insertion; it is simply assigned.
pred.next = node;
after the insertion. This is reflected in all usages. The next link is treated only as an optimized path. If a node's successor does not appear to exist (or
appears to be cancelled) via its next field, it is always possible to start at the tail of the list and traverse backwards using the pred field to accurately
check if there really is one.
the add node to sync queue code snippet is, copied form AbstractQueuedSynchronizer source code :
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
my question is, in the sourcecode, the next field of a Node class is a volatile object, if compareAndSetTail success, then the next field of t must not be null, why there may be a null situation. the code snippet is:
static final class Node {
//....ignored
volatile Node next;
volatile Node prev;
//.... ignored
}
Also, I don't quite understand hasQueuedPredecessors. If h != t, then h's next filed should not be null, why h.next == null also means hasQueuedPredecessors?
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}

Conversion errors? (i.e '!=' no conversion FDHPolynomial from 'nullptr' to 'int')

I was making this add function definition but I keep getting these conversion errors and I think I called a class or function wrong but I do not really understand or can find what's causing the errors. (Sorry about the long function, I tried to cut it down)
template<class ItemType>
bool FDHPolynomial<ItemType>::add(const ItemType& newCoefficient, const ItemType& newExponent)
{
if (newCoefficient == 0)//not wasting memory to store 0
{
return false;//no node added
}
else if (isEmpty())//if this is the first node added
{
FDHNode<ItemType>* newNodePtr = new FDHNode<ItemType>();//create new node
newNodePtr->setCoeffi(newCoefficient);//set contents
newNodePtr->setExpon(newExponent);
newNodePtr->setNext(nullptr);//since this is the only node, next value is nullptr
headPtr = newNodePtr;//first node is the head node
itemCount++;
}
else if (contains(newExponent))//if a node of this degree exists, add to its exponent
{
FDHNode<ItemType>* nodeToModifyPtr = getPointedTo(newExponent);//find the existing node
ItemType sumCoefficient = newCoefficient + nodeToModifyPtr->getCoeffi();//add new coefficient to existing coefficient
if (sumCoefficient == 0)//if added value cancels out a value
{
remove(newExponent);
}
else
{
nodeToModifyPtr->setCoeffi(sumCoefficient);//apply sum of coefficients
}
//itemCount does not increment
}
else if (newExponent > degree())//if new exponent is greater than any existing exponents
{
FDHNode<ItemType>* newNodePtr = new FDHNode<ItemType>();//create new node
newNodePtr->setCoeffi(newCoefficient);//set contents
newNodePtr->setExpon(newExponent);
newNodePtr->setNext(headPtr);//place at front of the chain
headPtr = newNodePtr;//new node is now the head node
itemCount++;
}
else//if new node needs to be inserted somewhere after the head node
{
FDHNode<ItemType>* newNodePtr = new FDHNode<ItemType>();//create new node
newNodePtr->setCoeffi(newCoefficient);//set contents
newNodePtr->setExpon(newExponent);
FDHNode<ItemType>* curPtr = headPtr;//this pointer will cycle through nodes until either a node with a degree smaller than newExponent is found or the last node is reached
while ((curPtr->getExpon() > newExponent) && (curPtr->getNext() != nullptr))
{
curPtr = curPtr->getNext();//advance curPtr
}

Dequeue function not outputting proper values

There seems to be an issue with my dequeue function within a queue class that I have. My dequeue function which is part of the position class, is not returning the correct values that have been enqueued into the list.
The values that have been enqueued are which is a position object, are 2,1 and -1, but when I dequeue that object i get 2,506216, and -1; When I assign the *pos ponter to an object I am left with the default values;The enqueue function seems to be working correctly for when I check the ptr values they are correct.
//position constructor
front = back = &header;
struct Posnode
{
Position *pos;
Posnode *next;
};
class Position
private:
Posnode *front,*back,header;
void Position::dequeue(Position&p)
{
Posnode *ptr=front->next;
front->next = ptr->next;
p = *ptr->pos;
p.geta();//checking for values but am left with the default
if (back == ptr)
{
back = front;
}
delete ptr;
}
v
oid Position::enqueue(Position n) //assigning Position object to end of queue
{
Posnode *ptr = new Posnode;
ptr-> pos = &n;
back->next = ptr;
back = ptr;
return;
}
Position copy,intial(5);
copy = intial;
if (copy.ismovelegal(posmoves, r))
{
copy.makemove(posmoves, r);
if (intial.solved(copy))
{
cin.get();
}
else
{
p.enqueue(copy);
}
}
copy.free();//clearing object private memebers
}
intial.free();
p.dequeue(o);//copy that was previous enqued is not enqued
o.geta();
Just Check out the Implementation of Deque first and then try your own. If its some syntax or semantic error post minimal code that reproduces your code.
this link might help you. Deque Implementation

Queue appending more then one entry

I keep getting the first entry appended 4 times instead of one time.. when I append my first entry to the Queue it appends it 4 times..I thought this might be the problem..but it looks like it isn't. I can't find where the problem is..
I also created a print function for the nodes, and it showes that there are 4 of the same entries in the queue, so it is not a printing problem. And it doesn't look like it's in the read function. Maybe it's in the logic of the append function?? Still working on it..
This is the output: 3X^2 + 3X^2 + 3X^2 + 3X^2 + 1 but it should be 3X^2 + 1
This is my append function:
//Append(Add) item to back of queue.
Error_code Extended_queue::append(const Queue_entry &item) {
Node<Queue_entry> *new_rear = new Node<Queue_entry>(item);
if(rear == nullptr){
front = new_rear; // I also tried rear = new_rear; front = rear; rear = new_rear;
}
else {
rear->next = new_rear;
rear = new_rear;
}
return success;
}
And here is the code that prints the output:
This is the node code declaration:
#ifndef NODE_H
#define NODE_H
enum Error_code{success,underflow,overflow}; // Used in node containing classes
template <class Node_entry> // Template to allow for more varience
// Part of a linked structure
struct __declspec(align(1)) Node{
Node_entry entry; // Data contained in the node
Node *next; //Pointer to next node
//constructors
Node(); // Creates empty node
Node(Node_entry item, Node *add_on = nullptr); // Creates node with specified data and pointer to next node
};
/* Post: The Node is initialized to contain nothing, and to have a null pointer.*/
template <class Node_entry>
Node<Node_entry>::Node()
{
entry = nullptr;
next = nullptr;
}
/* Post: The Node is initialized to contain item, and to point to add_on.*/
template <class Node_entry>
Node<Node_entry>::Node(Node_entry item, Node *add_on)
{
entry = item;
next = add_on;
}
#endif
It looks like the copy constructor had bad logic. After I fixed th constructor, the driver only returned the first term as front and rear entry. So I had to fix up the overloaded = operator as well.
New Code(for copy constructor):
Extended_queue::Extended_queue(const Extended_queue &original){
Node<Queue_entry> *temp_node, *original_node = original.front;
if(original.empty()){ //original queue is empty, set new to NULL
front = nullptr;
rear = nullptr;
}
else
{
front = temp_node = new Node<Queue_entry>(original_node->entry,nullptr);
while(original_node->next != nullptr)
{
original_node = original_node->next;
//needed to change next and still incriment
temp_node->next = new Node<Queue_entry>(original_node->entry, nullptr);
temp_node = temp_node->next;
//rear->next = temp_node;
//rear = temp_node;
}
rear = temp_node->next;
}
}