Enqueue for priority queue not working properly C++ - c++

For my Computer Science class I am implementing a templated Priority Queue class and I am struggling to implement the enqueue function. I know the error is in the if(value < back) block of the function.
Here is the Function:
template<class T>
bool PriorityQueue<T>::enqueue(T& value){
if(!isEmpty()){
if(value < back()){
Node<T>* curr = f_ptr;
Node<T>* prev = NULL;
while(value > curr->data() && curr != NULL){
prev = curr;
curr = curr->m_next;
}
if(curr != NULL && value == curr->data()){
prev = curr;
curr = curr->m_next;
}
Node<T>* tmp = new Node<T>(value,curr);
prev->m_next = tmp;
return true;
}else{
b_ptr->m_next = new Node<T>(value);
b_ptr = b_ptr->m_next;
}
}else{
f_ptr = new Node<T>(value);
b_ptr = f_ptr;
return true;
}
}
The Helper functions are all functioning properly. Please explain what part of my logic is incorrect.

Related

How to pass a pointer from a void function to another C++

Consider the following piece of code:
void List::insertFront(int key)
{
Node *tmp_node = new Node;
tmp_node->key = key;
tmp_node->next = head->next;
tmp_node->prev = head;
head->next = tmp_node;
_size++;
}
This function adds an element to the beginning of a list and I want to catch the first element of the list in another function and delete it. For this purpose I have written the following piece of code:
bool List::getFront(int &key)
{
if (head->next->key == key)
{
Node *tmp_node = new Node;
head->next = tmp_node->next;
delete tmp_node;
delete head->next;
_size--;
return true;
}
else return false;
}
As you can see each time I am creating a new node which utilizes a fresh empty list, but I want to use the list that was created in the previous function.
How can I pass the node from insertFront() to getFront()?
Your getFront() code is all wrong. You need something more like this instead:
bool List::popFrontIfMatches(int key)
{
Node *tmp_node = head->next;
if ((tmp_node) && (tmp_node->key == key))
{
if (tmp_node->next)
tmp_node->next->prev = tmp_node->prev;
if (tmp_node->prev)
tmp_node->prev->next = tmp_node->next;
head->next = tmp_node->next;
delete tmp_node;
_size--;
return true;
}
else
return false;
}
That being said, why are you treating head->next as the 1st node in the list, and not head itself as is the usual common practice?
void List::insertFront(int key)
{
Node *tmp_node = new Node;
tmp_node->key = key;
tmp_node->next = head;
tmp_node->prev = NULL;
head = tmp_node;
_size++;
}
bool List::popFrontIfMatches(int key)
{
Node *tmp_node = head;
if ((tmp_node) && (tmp_node->key == key))
{
if (tmp_node->next)
tmp_node->next->prev = tmp_node->prev;
if (tmp_node->prev)
tmp_node->prev->next = tmp_node->next;
head = tmp_node->next;
delete tmp_node;
_size--;
return true;
}
else
return false;
}

LinkedList using initializer_list

So, i'm trying to initialize a LinkedList class using an initializer_list.
template<typename T>
SortedList<T>::SortedList(initializer_list<T> e){
head_= new Node<T>(*e.begin());
long intcheck = 0;
T old;
for (auto x : e){
if(intcheck > 0){
Node<T>* curr = new Node<T>(old);
if(head_ == curr){
head_->next_ = new Node<T>(x);
}
curr->next_ = new Node<T>(x);
}
old = x;
intcheck = 1;
}
}
I get a seg fault when trying to print head_->next_ (nothing wrong with my print function)
I'm assuming that you actually want the SortedList to be sorted. If so, this will accomplish that goal. It bails out early if the initializer_list is empty, but still leaves the object in a rational state.
template<typename T>
SortedList<T>::SortedList(initializer_list<T> e) : head_{nullptr} {
if (e.size() == 0)
return;
auto it = e.begin();
for (head_ = new Node<T>(*it); it != e.end(); ++it) {
Node<T> *n = new Node<T>(*it);
Node<T> *curr;
for (curr = head_; curr->next_ && curr->next_->data_ < *it; curr = curr->next_)
continue;
if (*it < curr->data_) {
n->next_ = curr;
head_ = n;
} else {
n->next_ = curr->next_;
curr->next_ = n;
}
}
}
For completeness, here's the destructor I used to test:
template<typename T>
SortedList<T>::~SortedList() {
while (head_->next_) {
Node<T> *t = head_->next_;
head_->next_ = t->next_;
delete t;
}
delete head_;
}
Your code says that head_->next_ will always be it's default value (we can't see the Node constructor so I can't say what that is).
for (auto x : e){
if(intcheck > 0){
Node<T>* curr = new Node<T>(old);
if(head_ == curr){
head_->next_ = new Node<T>(x);
}
It's OK do send your initializer list into the for loop this way. If it's empty you will just exit the loop immediately.
However your curr pointer is allocated right there, while your head_ pointer was allocated above. They will therefore never be equal because you are comparing two pointers that you are allocating in the same function.

How to solve error in code and interpret error message

So I'm working on a project using linked lists. The program basically takes in numbers until -999 is inputted and then does operations on it. The two operations I am having problems with are deleteAll, where all the same values are deleted from the list, and deleteSmallest, where the smallest value in the list is deleted. The code that calls both functions is as follows:
int num;
cout << "Enter a number you would like deleted from the whole list: ";
cin >> num;
uList.deleteAll(num);
cout << "New list: " << uList << endl;
uList.deleteSmallest();
cout << "After deleting the smallest number, the list now is: " << uList << endl;
The code for deleteAll is as follows:
template <class Type>
void UnorderedLinkedList<Type>::deleteAll(const Type& deleteItem)
{
NodeType<Type>* curr;
NodeType<Type>* p = NULL;
NodeType<Type>* q = NULL;
curr = first;
if(first == NULL)
throw std::runtime_error("Cannot delete from an empty list");
else
{
for(int i = 0; i < count; i++)
{
if(curr->info == deleteItem)
{
p = curr;
q = p->link;
p->link = q->link;
delete q;
}
curr = curr->link;
}
}
delete p;
delete curr;
}
The code for deleteSmallest is as follows:
template <class Type>
void UnorderedLinkedList<Type>::deleteSmallest()
{
NodeType<Type>* curr;
NodeType<Type>* p;
NodeType<Type>* q;
NodeType<Type>* r;
curr = first;
if (first == NULL)
throw std::runtime_error("Cannot delete from an empty list");
else
{
for(int i = 0; i < count; i++)
{
if(curr->link->info < curr->info)
{
int smallest = curr->link->info;
p = curr;
q = curr->link;
}
curr = curr->link;
}
}
r = q->link;
p->link = q->link;
delete q;
}
The error that I get is:
1 [main] Project 5 4044 cygwin_exception::open_stackdumpfile: Dumping stack trace to Project 5.exe.stackdump
Sorry to post a large question, but can someone explain what the error means in this situation and what I'm doing that is causing this to come up? Thank you!
For deleteAll() you should be doing something like this:
else
{
for (Node* prev = curr; curr != NULL; prev = curr, curr = curr->link)
{
if (curr->info == deleteItem)
{
NodeType<Type>* temp = curr;
curr = curr->link;
if (prev)
prev->next = curr;
delete temp;
}
}
}
The way you had it before was not deleting curr at all. You should also remove the delete p and delete curr at the bottom as they are redundant.
And for deleteSmallest(), you need to keep a pointer pointing to the smallest node (and a previous node pointing to the one before it) so when the loop finishes you know what delete:
else
{
Node* prev = NULL, **smallest;
for (Node** curr = smallest = head, *back(*head); *curr != NULL; back = *curr, curr = &(*curr)->link)
{
if ((*curr)->info < (*smallest)->info)
{
prev = back;
smallest = curr;
}
}
Node* temp = *smallest;
*smallest = (*smallest)->link;
if (prev)
prev->link = *smallest;
delete temp;
}

Linked List Priority Queue with addition conditions

I have tired coding the normal priority. Now i would want to add in 1 or 2 more conditions into my code.
Here's my current normal priority code:
void queue::addToQueueList(int newPriority, double newFare, int custID)
{
node* newnode= new node;
newnode->priority= newPriority;
newnode->fare = newFare;
newnode->cusID = custID;
newnode->next= NULL;
if (front == NULL || newnode->priority < front->priority)
{
newnode->next = front;
front = newnode;
}
else
{
node* q = front;
node* p;
while (q->next != NULL && q->next->priority <= newnode->priority)
{
q=q->next;
}
newnode->next = q->next;
q->next = newnode;
}
}
how can i add in addition condition example if found priority same, compare the fare. the highest of the fare will be priority.
Thanks
If I have correctly understood you need the following
#include <utility>
//...
void queue::addToQueueList(int newPriority, double newFare, int custID)
{
node* newnode= new node;
newnode->priority= newPriority;
newnode->fare = newFare;
newnode->cusID = custID;
newnode->next= NULL;
auto p = std::make_pair( newPriority, newFare );
if (front == NULL || p < std::make_pair( front->priority, front->fare ) )
{
newnode->next = front;
front = newnode;
}
else
{
node* q = front;
while (q->next != NULL &&
std::make_pair( q->next->priority, q->next->fare ) <= p)
{
q=q->next;
}
newnode->next = q->next;
q->next = newnode;
}
}
Also it seems that statement
node* p;
may be removed from the function.
This is what i did:
void queue::addToQueueList(int newPriority, double newFare, int custID)
{
node* newnode= new node;
newnode->priority= newPriority;
newnode->fare = newFare;
newnode->cusID = custID;
newnode->next= NULL;
if (front == NULL || newnode->priority < front->priority)
{
newnode->next = front;
front = newnode;
}
else
{
node* q = front;
node* p;
while (q->next != NULL && q->next->priority <= newnode->priority)
{
p=q;
q=q->next;
}
bool chk = compare(q,newnode);
if(chk)
{
p->next = newnode;
newnode->next = q;
}
else
{
newnode->next = q->next;
q->next = newnode;
}
}
}
bool queue::compare(node* const& n1, node* const& n2)
{
bool check = false;
if(n1->priority == n2->priority)
{
if(n2->fare > n1->fare)
{
check = true;
}
}
return check;
}

Reverse doubly-link list in C++

I've been trying to figure out how to reverse the order of a doubly-linked list, but for some reason, in my function void reverse() runs while loop once and then crashes for some reason. To answer some questions ahead, I'm self-teaching myself with my brothers help. This isn't all of the code, but I have a display() function which prints all nodes chronologically from start_ptr and a switch which activates certain functions like
case 1 : add_end(); break;
case 2 : add_begin(); break;
case 3 : add_index(); break;
case 4 : del_end(); break;
case 5 : del_begin(); break;
case 6 : reverse(); break;
This is the geist of my code:
#include <iostream>
using namespace std;
struct node
{
char name[20];
char profession[20];
int age;
node *nxt;
node *prv;
};
node *start_ptr = NULL;
void pswap (node *pa, node *pb)
{
node temp = *pa;
*pa = *pb;
*pb = temp;
return;
}
void reverse()
{
if(start_ptr==NULL)
{
cout << "Can't do anything" << endl;
}
else if(start_ptr->nxt==NULL)
{
return;
}
else
{
node *current = start_ptr;
node *nextone = start_ptr;
nextone=nextone->nxt->nxt;
current=current->nxt;
start_ptr->prv=start_ptr->nxt;
start_ptr->nxt=NULL;
//nextone=nextone->nxt;
while(nextone->nxt!= NULL)
{
pswap(current->nxt, current->prv);
current=nextone;
nextone=nextone->nxt;
}
start_ptr=nextone;
}
}
Try this:
node *ptr = start_ptr;
while (ptr != NULL) {
node *tmp = ptr->nxt;
ptr->nxt = ptr->prv;
ptr->prv = tmp;
if (tmp == NULL) {
end_ptr = start_ptr;
start_ptr = ptr;
}
ptr = tmp;
}
EDIT: My first implementation, which was correct but not perfect.
Your implementation is pretty complicated. Can you try this instead:
node * reverse(Node * start_ptr)
{
Node *curr = start_ptr;
Node * prev = null;
Node * next = null;
while(curr)
{
next = curr->nxt;
curr->nxt = prev;
curr->prv = next;
prev = curr;
curr = next;
}
return start_ptr=prev;
}
Here is my updated solution:
node * reverse()
{
node *curr = start_ptr;
node * prev = NULL;
node * next = NULL;
while(curr)
{
next = curr->nxt;
curr->nxt = prev;
curr->prv = next;
prev = curr;
curr = next;
}
return start_ptr=prev;
}
The logic was correct. But the issue was that I was accepting in input argument start_ptr. Which means that I was returning the local copy of it. Now it should be working.
You can simplify your reverse() quite a bit. I'd do something like this:
void reverse()
{
if(start_ptr == NULL)
{
cout << "Can't do anything" << endl;
}
else
{
node *curr = start_ptr;
while(curr != NULL)
{
Node *next = curr->next;
curr->next = curr->prev;
curr->prev = next;
curr = next;
}
start_ptr = prev;
}
}
Explanation: The basic idea is simply to visit each Node and swap the links to previous and next. When we move curr to the next Node, we need to store the next node so we still have a pointer to it when we set curr.next to prev.
Simple solution. reverses in less than half a number of total iterations over the list
template<typename E> void DLinkedList<E>::reverse() {
int median = 0;
int listSize = size();
int counter = 0;
if (listSize == 1)
return;
DNode<E>* tempNode = new DNode<E>();
/**
* A temporary node for swapping a node and its reflection node
*/
DNode<E>* dummyNode = new DNode<E>();
DNode<E>* headCursor = head;
DNode<E>* tailCursor = tail;
for (int i = 0; i < listSize / 2; i++) {
cout << i << "\t";
headCursor = headCursor->next;
tailCursor = tailCursor->prev;
DNode<E>* curNode = headCursor;
DNode<E>* reflectionNode = tailCursor;
if (listSize % 2 == 0 && listSize / 2 - 1 == i) {
/**
* insert a dummy node for reflection
* for even sized lists
*/
curNode->next = dummyNode;
dummyNode->prev = curNode;
reflectionNode->prev = dummyNode;
dummyNode->next = reflectionNode;
}
/**
* swap the connections from previous and
* next nodes for current and reflection nodes
*/
curNode->prev->next = curNode->next->prev = reflectionNode;
reflectionNode->prev->next = reflectionNode->next->prev = curNode;
/**
* swapping of the nodes
*/
tempNode->prev = curNode->prev;
tempNode->next = curNode->next;
curNode->next = reflectionNode->next;
curNode->prev = reflectionNode->prev;
reflectionNode->prev = tempNode->prev;
reflectionNode->next = tempNode->next;
if (listSize % 2 == 0 && listSize / 2 - 1 == i) {
/**
* remove a dummy node for reflection
* for even sized lists
*/
reflectionNode->next = curNode;
curNode->prev = reflectionNode;
}
/**
* Reassign the cursors to position over the recently swapped nodes
*/
tailCursor = curNode;
headCursor = reflectionNode;
}
delete tempNode, dummyNode;
}
template<typename E> int DLinkedList<E>::size() {
int count = 0;
DNode<E>* iterator = head;
while (iterator->next != tail) {
count++;
iterator = iterator->next;
}
return count;
}
I suggest maintaining a link to the last node.
If not, find the last node.
Traverse the list using the "previous" links (or in your case, prv).
There is no need to actually change the links around. Traversing using the prv pointer will automatically visit the nodes in reverse order.
Look at
valuesnextone=nextone->nxt->nxt;
Here nextone->nxt can be null.
Apart from that, try to use pointers to pointers in the swap function.
Your pswap function is wrong
your should swap the pointer not try to create temporary objects and swap them.
Should be like that (there might be other mistake later)
void pswap (node *&pa, node *&pb)
{
node* temp = pa;
pa = pb;
pb = temp;
return;
}
A very simple and O(n) solution using two pointers:
start = head of the doubly LL
struct node *temp, *s;
s = start;
while(s != NULL){
temp = s->prev;
s->prev = s->next;
s->next = temp;
s = s->prev;
}
//if list has more than one node
if(current != NULL){
start = temp->prev;
}
My code for reversing doubly linked list,
Node* Reverse(Node* head)
{
// Complete this function
// Do not write the main method.
if(head != NULL) {
Node* curr = head;
Node* lastsetNode = curr;
while(curr != NULL) {
Node* frwdNode = curr->next;
Node* prevNode = curr->prev;
if(curr==head) {
curr->next = NULL;
curr->prev = frwdNode;
lastsetNode = curr;
}
else {
curr->next = lastsetNode;
curr->prev = frwdNode;
lastsetNode = curr;
}
curr = frwdNode;
}
head = lastsetNode;
}
return head;
}
I thought I'd add a recursive solution here.
node* reverse_and_get_new_head(node* head) {
if (head == nullptr) { return nullptr; }
// This can be avoided by ensuring the initial,
// outer call is with a non-empty list
std::swap(head->prev, head->next);
if (head->prev == nullptr) { return head; }
return reverse_and_get_new_head(head->prev);
}
void reverse() {
start_ptr = reverse_and_get_new_head(start_ptr);
}