We were given two structs, one representing a Player and another one representing a Task that the player can later implement after it has been assigned to him. Each player has a list of tasks sorted in ascending order. Initially we had to implement a circular doubly linked list with sentinel for the Players list and a singly sorted linked list with sentinel for the tasks (using the tasks_head & tasks_sentinel fields of the Players struct).
Once the data structures are set, we need to distribute the tasks from a given General tasks list (pointed to by Head_GL) to the players using a round robin algo (don't know if my solution is correct, haven't researched the algorithm so that i can try solving the problem on my own first).
The issue is that for some unknown to me reason, the program seems to hang when the isTaskListEmpty(..) is called and then the program stops just like that, without printing anything after cout<<"istasklist empty called";.
Any ideas on what i'm doing wrong?
P.S. I've never worked with c++ on anything other than simple hello world programs so my experience with pointers is beyond limited.
Header file declarations for the structs and some global variables:
/**
* Structure defining a node of the players double linked list
* tree
*/
struct Players
{
int pid; /*Player's identifier*/
int is_alien; /*Alien flag*/
int evidence; /*Amount of evidence*/
struct Players *prev; /*Pointer to the previous node*/
struct Players *next; /*Pointer to the next node*/
struct Tasks *tasks_head; /*Pointer to the head of player's task list*/
struct Tasks *tasks_sentinel; /*Pointer to the sentinel of player's task list*/
};
/**
* Structure defining a node of the tasks sorted linked list
*/
struct Tasks
{
int tid; /*Task's identifier*/
int difficulty; /*Task's difficulty*/
struct Tasks *next; /*Pointer to the next node*/
};
struct Head_GL
{
int tasks_count[3]; /*Count of tasks*/
struct Tasks *head; /*Pointer to the head of general list*/
};
/* Global variable, pointer to the head of the players list */
struct Players *players_head;
/* Global variable, pointer to the head of the tasks list */
struct Head_GL *tasks_head;
/* Global variable, pointer to the top of the completed task's stack */
struct Head_Completed_Task_Stack *tasks_stack;
/* Global variable, counter of the total num of tasks in the general tasks list */
int Total_Tasks;
Main.cpp:
/**
* #brief Optional function to initialize data structures that
* need initialization
*
* #return 1 on success
* 0 on failure
*/
int initialize() {
// players list init
players_head = (struct Players*) malloc(sizeof(struct Players));
players_head->evidence = -1;
players_head->is_alien = -1;
players_head->pid = -1;
players_head->next = NULL;
players_head->prev = NULL;
players_head->tasks_head = NULL;
players_head->tasks_sentinel = NULL;
// General Tasks List init
tasks_head = (struct Head_GL*) malloc(sizeof(struct Head_GL));
tasks_head->tasks_count[0] = 0;
tasks_head->tasks_count[1] = 0;
tasks_head->tasks_count[2] = 0;
tasks_head->head = NULL;
// Completed Tasks stack init
tasks_stack = (struct Head_Completed_Task_Stack*) malloc(sizeof(struct Head_Completed_Task_Stack));
tasks_stack->count = 0;
tasks_stack->head = NULL;
Total_Tasks = 0;
return 1;
}
/**
* #brief Distribute tasks to the players
* #return 1 on success
* 0 on failure
*/
int distribute_tasks() {
if(isDLLEmpty() || isGenTaskListEmpty()) return 0;
// round robin algo
int tasksToAssign;
struct Players* player = players_head->next; // start with the 1st player
struct Tasks* task = tasks_head->head; // start with the 1st task
// There's only one player and he's an impostor so exit
if(player->is_alien == 1 && player->next == NULL) return 0;
for(tasksToAssign = Total_Tasks; tasksToAssign > 0; tasksToAssign--) {
if(player->is_alien == 1 || player == players_head) {
tasksToAssign++;
player = player->next; // go to the next player
continue; // skip impostors
}
sortedInsertTaskList(&player,task->tid,task->difficulty);
player = player->next; // go to the next player
task = task->next; // go to the next task to assign
}
return 1;
}
// Beginning of General Tasks list implementation (Sorted singly linked list)
bool isGenTaskListEmpty() {
return (tasks_head->head == NULL);
}
int sortedInsertGenTaskList(int tid, int difficulty) {
// increment the list's difficulty counter
if (difficulty == 1) tasks_head->tasks_count[0]++;
else if (difficulty == 2) tasks_head->tasks_count[1]++;
else tasks_head->tasks_count[2]++;
Total_Tasks++; // increment the num of total tasks
struct Tasks *node = (struct Tasks*) malloc(sizeof(struct Tasks)); // could return null if not enough mem
if(node == NULL) return 0; // not enough memory exit
// add data to the new node
node->tid = tid;
node->difficulty = difficulty;
node->next = NULL;
if(isGenTaskListEmpty()) {
tasks_head->head = node;
return 1;
}
// insert the new node without breaking the sorting of the list
Tasks *curr = tasks_head->head;
while(curr->next != NULL && curr->next->difficulty < difficulty) {
curr = curr->next;
}
node->next = curr->next;
curr->next = node;
return 1;
}
void printGenTasksList() {
cout << "{" << tasks_head->tasks_count[0] << "," << tasks_head->tasks_count[1] << "," << tasks_head->tasks_count[2] << "}" << endl;
Tasks* curr = tasks_head->head;
do {
cout << "Task#" << curr->tid << ":" << curr->difficulty << endl;
curr = curr->next;
} while (curr != NULL);
}
// End of General Tasks list implementation (Sorted singly linked list)
// Beginning of Tasks List implementation (Sorted Singly Linked List w/sentinel)
bool isTaskListEmpty(struct Tasks* head) {
cout<<"istasklist empty called";
return (head->next == NULL);
}
int sortedInsertTaskList(struct Players** player, int tid, int difficulty) {
struct Tasks* node = (struct Tasks*) malloc(sizeof(struct Tasks)); // could return null if not enough mem
if(node == NULL) return 0;
// add data to the new node
node->tid = tid;
node->difficulty = difficulty;
node->next = NULL;
cout << "sortedInsert before is empty";
if (isTaskListEmpty((*player)->tasks_head)) { // if the list is empty, make the head and sentinel point to the new node
cout << "list was empty";
(*player)->tasks_head->next = node;
(*player)->tasks_sentinel->next = node;
return 1;
}
// check if the new node can be added to the end of the list
if ((*player)->tasks_sentinel->next->difficulty <= difficulty) {
(*player)->tasks_sentinel->next->next = node; // place new node at the end of the list
(*player)->tasks_sentinel->next = node; // update sentinel
return 1;
}
// insert the new node without breaking the sorting of the list
struct Tasks* curr = (*player)->tasks_head->next;
while (curr->next != NULL && curr->next->difficulty < difficulty) {
curr = curr->next;
}
node->next = curr->next;
curr->next = node;
return 1;
}
// End of Tasks List implementation (Sorted Singly Linked List w/sentinel)
// Beginning of players list implementation (circular doubly linked list w/ Sentinel)
bool isDLLEmpty() {
return (players_head->next == NULL);
}
int dllInsert(int pid, int isAlien) {
// allocate memory and initialize fields
struct Players* player = (struct Players*) malloc(sizeof(struct Players)); // could return null if not enough mem
if(player == NULL) return 0; // not enough memory, exit
player->pid = pid;
player->is_alien = isAlien;
player->evidence = 0;
player->prev = players_head;
player->tasks_head = NULL;
player->tasks_sentinel = NULL;
// check if the list is empty
if (isDLLEmpty()) {
player->next = players_head;
players_head->next = player;
players_head->prev = player;
return 1;
}
// insert the new player at the beginning of the list
players_head->next->prev = player;
player->next = players_head->next;
players_head->next = player;
return 1;
}
// End of players list implementation (circular doubly linked list w/ Sentinel)
Related
To find set of all nodes that are visible from left side of binary tree.
vector<int> getLeftView(TreeNode<int> *root)
{
static vector<int> res;
// Your code here
if(root){
res.push_back(root->data);
if(root->left)
getLeftView(root->left);
else
getLeftView(root->right);
}
return res;
}
For a single test case at a time it works fine. But when multiple test cases are run, the previous values in the vector is appended by the new values. How do I clear the vector before running the next test case?
You used static because you need a single instance of the vector to be used across the recursion. But static is not the way; it causes there to be just one instance of the vector in the entire program as such.
There are various solutions, one of which is to split the function into the API and recursive part:
void getLeftViewRec(TreeNode<int> *root, vector<int> &res)
{
if(root){
res.push_back(root->data);
if(root->left)
getLeftView(root->left, res);
else
getLeftView(root->right, res);
}
return res;
}
vector<int> getLeftView(TreeNode<int> *root)
{
vector<int> res;
getLeftViewRec(root, res);
return res;
}
Now what happens is that every time getLeftView is called, a new vector res is instantiated as a local variable. It then calls the recursive function getLeftViewRec which receives res by reference, and passes it to itself through the recursive calls, so the recursion is working with a single vector, accumulating into it.
Using queue and a null pointer to mark the first element of each level. we insert a null pointer in the first and as reach that null pointer we mark bool as true and take the next element as our left view element,
// C++ Code for the above iterative approach
#include <bits/stdc++.h>
using namespace std;
// Tree Node Structure contains data, left and right
// pointer
struct Node {
int data;
struct Node *left, *right;
};
// A utility function to
// create a new Binary Tree Node
struct Node* newNode(int item)
{
struct Node* temp
= (struct Node*)malloc(sizeof(struct Node));
temp->data = item;
temp->left = temp->right = NULL;
return temp;
}
// function to get the left view of binary tree in vector
vector<int> leftView(Node* root)
{
// store the left view
vector<int> ans;
// Base Case : Empty Tree
if (!root)
return ans;
// Create an empty queue and enque root node and null
queue<Node*> q;
q.push(root);
q.push(NULL);
bool ok = true;
// Traverse till queue is not empty
while (!q.empty()) {
// get the front node and dequeue it from queue
auto it = q.front();
q.pop();
// if the front node is null do following steps
if (it == NULL) {
if (ok == false)
ok = true;
if (q.size() == 0)
break;
else
q.push(NULL);
}
// else do the following steps
else {
if (ok) {
ans.push_back(it->data);
ok = false;
}
if (it->left)
q.push(it->left);
if (it->right)
q.push(it->right);
}
}
// return the left view
return ans;
}
// driver code to test above code on a test case
int main()
{
/*
Input :
10
/ \
2 3
/ \ / \
7 8 12 15
/
14
Output : 10 2 7 14
*/
// let's build above shown tree
Node* root = newNode(10);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(7);
root->left->right = newNode(8);
root->right->right = newNode(15);
root->right->left = newNode(12);
root->right->right->left = newNode(14);
// call leftview function and store output in vec
vector<int> vec = leftView(root);
// traverse on left view and print each element
for (int x : vec)
cout << x << " ";
cout << endl;
return 0;
}
I am trying to delete the odd numbers that are randomly generated (see oddsOnly), and then print the list in reverse order. I can delete odds that may pop up at the beginning of the list, but I cannot find a way to delete anything after that.
I have tried various forms of if and while loops. Too many different ways for me to remember or list them all.
#include<iostream>
#include<ctime>
#include<fstream>
using namespace std;
struct Node
{
int element;
Node *next;
Node *previous;
};
// Function headers
int takeNumber(int);
int writeFile(int);
struct Node *readFile(Node *&, int);
void printBackward(Node *);
struct Node *oddsOnly(Node *&, int);
void deleteList(Node *);
// Main
int main(int argc, char *argv[])
{
// Check to see if the user passed us the size to make the list.
if (argc == 2)
{
// Check to see if what the user passed us is in fact a valid number.
// Here we attempt to assign what was passes in to us to an int variable
int Size = atoi(argv[1]);
// Now we check a few things. If the !Size tells us whether or not the
// assignment above was successful. If the size is less than 20 or
// greater than 100, the input did not follow the instructions. In
// either case we ask the user to enter another number with the printed
// instructions of it must be between 20 and 100.
if (!Size || Size < 20 || Size > 100)
{
Size = takeNumber(Size);
}
// Create the pointer for Head. This is used to keep track of the beginning
// of the list.
Node *Head = new Node;
if (Head == NULL)
{
cout << "fatal error: could not create Head node." << endl;
return(1);
}
Head = NULL;
// If we are here, the head node was created successfully. As this is
// currently also the last node in the list, set the pointer to NULL.
//Head->next = NULL;
writeFile(Size);
readFile(Head, Size);
// When you allocate memory with new or malloc, you should always clean
// free up the memory when you are through.
deleteList(Head);
}
else
{
int Size = 0;
Size = takeNumber(Size);
// Create the pointer for Head. This is used to keep track of the beginning
// of the list.
Node *Head = new Node;
if (Head == NULL)
{
cout << "fatal error: could not create Head node." << endl;
return(1);
}
Head = NULL;
// If we are here, the head node was created successfully. As this is
// currently also the last node in the list, set the pointer to NULL.
//Head->next = NULL;
writeFile(Size);
readFile(Head, Size);
oddsOnly(Head, Size);
// When you allocate memory with new or malloc, you should always clean
// free up the memory when you are through.
deleteList(Head);
}
system("pause");
return 0;
}
// Function to take input (size) from the user
int takeNumber(int Size)
{
while (Size < 20 || Size > 100)
{
// Output specific instructions to the user.
cout << endl << "Please inter a number between 20 and 100 (inclusive). " << endl;
// Take a given input from the user.
cin >> Size;
// Set a while loop so that if the incorrect input is given, the user will
// be asked to enter a different input untill it fits the given discription
// in the instructions.
if (cin.fail() || Size < 20 || Size > 100)
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
// Print error message and ask for another input.
cout << "Input is not between 20 and 100 (inclusive). " << endl;
cout << "Please try again. " << endl << endl;
}
}
// Return the input.
return Size;
}
// Function to write random numbers to a binary file
int writeFile(int size)
{
// Create and open the file you will write to.
ofstream WriteFile;
WriteFile.open("numbers.bin", ios::out | ios::binary);
// Make sure to print an error message if the file was not created.
if (!WriteFile)
{
cout << "Could not create/open binary file for writing. " << endl << endl;
return (1);
}
// Seed the random fuction with the time from the computer.
srand(int(time(NULL)));
// create a variable to store the random variable gernerated.
int number = 0;
// Create a loop to generate some random data and store it in
// the number variable. Then write the number to the to the binary
// file.
for (int i = 0; i < size; i++)
{
// Generate a random number between 0 and 99.
number = (rand() % 100);
// Write the number to the binary file.
WriteFile.write(reinterpret_cast<const char *>(&number), sizeof(int));
}
WriteFile << endl;
// Close the binary file.
WriteFile.close();
return(0);
}
// Function to read the binary file and create a linked list.
struct Node *readFile(Node *&Head, int Size)
{
// Create and open a read binary file
ifstream ReadFile;
ReadFile.open("numbers.bin", ios::in | ios::binary);
// Check to make sure file has been created and opened.
if (!ReadFile)
{
cout << "Could not open the binary file for reading. " << endl << endl;
}
int Data = 0;
int counter = 1;
while (ReadFile)
{
ReadFile.read((char*)&Data, sizeof(int));
if (ReadFile.eof())
{
break;
}
if (Head == NULL)
{
Node *tmp = new Node;
if (tmp == NULL)
{
cout << "fatal error: could not create tmp node" << endl;
}
tmp->element = Data;
tmp->next = NULL;
tmp->previous = NULL;
Head = tmp;
counter = counter + 1;
}
else if (Head != NULL)
{
Node *current = new Node;
if (current == NULL)
{
cout << "fatal error: could not create current node" << endl;
}
current = Head;
while (current->next != NULL)
{
current = current->next;
}
struct Node *temp = new Node;
if (temp == NULL)
{
cout << "fatal error: could not create temp node" << endl;
}
temp->element = Data;
temp->next = NULL;
temp->previous = current;
current->next = temp;
counter = counter + 1;
}
}
cout << endl;
// Close the file
ReadFile.close();
oddsOnly(Head, Size);
printBackward(Head);
cout << endl;
return Head;
}
// Function to read the numbers.bin file and put numbers in reverse order
void printBackward(Node *Head)
{
// We now have a list. We can traverse the list and print the elements.
// We have the head, we create a current or tmp node pointer to set it
// equal to head.
Node *temp;
temp = Head;
while (temp->next != NULL)
{
temp = temp->next;
}
// We can use a counter to format the output on the console
int counter = 1;
// This is our loop to traverse the list. We start at head, and go until
// we reach the null pointer of the last node.
while (temp != NULL)
{
// This prints the number in the node, then a tab separator to the
// console.
cout << temp->element << "\t";
// This is used for formatting the output on the screen. In this case,
// after every five nodes have been printed, we insert a newline and
// reset the counter to 0.
if (counter % 5 == 0)
{
cout << endl;
counter = 0;
}
// We advance the tmp or current pointer to the next value and increment the counter.
temp = temp->previous;
counter = counter + 1;
}
}
// Function to weed out the odd numbers in the list
struct Node *oddsOnly(Node *&Head, int size)
{
int counter = 1;
while (Head->element % 2 == 0)
{
struct Node *temp = Head;
Head = Head->next;
Head->previous = NULL;
delete(temp);
return Head;
counter = counter + 1;
}
Node *tmp = Head;
while (tmp != NULL)
{
Node *current = Head;
while (current->element % 2 != 0 && current->next->next != NULL)
{
current = current->next;
tmp = current->next;
}
current->previous->next = current->next;
current->next->previous = current->previous;
delete(current);
struct Node *current1 = Head;
while (current1->next != NULL)
{
current1 = current1->next;
}
if (current1->element % 2 == 0)
{
current1->previous->next = NULL;
delete(current1);
}
tmp = tmp->next;
}
cout << endl;
return Head;
}
// Function to delete the link list.
void deleteList(Node *Head)
{
Node *tmp;
// Loop through the list, deleting one node at a time. We set tmp equal
// to the node after head, delete head and then set head equal to tmp.
while (Head != NULL)
{
tmp = Head->next;
delete(Head);
Head = tmp;
}
}
I am looking for a list that allows 5 integers before starting a new line, and that has only odd values from the linked list.
I have gotten a lot of error messages displaying 0xDDDDDDDD in the oddsOnly function. at this point though, I am only seeing that it is not deleting the evens after the first node in the list.
Refer to the following diagram:
To delete node B from the list, set A.Next to A.Next.Next, set C.Prev to C.Prev.Prev, and free node B.
To delete node D from the list, set C.Next to C.Next.Next (which is null), and free node D.
Make sure you write a function that does this. Your code suggests that you're not fully taking advantage of the encapsulation and "divide and conquer" strategy that functions provide.
Further Reading
Delete a node in a Doubly Linked List
Stealing Roberts great picture
I don't quite agree with his description (it is correct though just a bit complicated when written in English).
Node* x = findNodeToDelete();
if (x == nullptr) { // Check to make sure you have an actual node to delete.
return;
}
if (x->next != nullptr) {
x->next->prev = x->prev;
}
if (x->prev != nullptr) {
x->prev->next = x->next;
}
else {
Head = x->next;
}
// Now you have unlinked the node from the list.
x->next = nullptr; // Optional if node has a complex destructor may be worth it.
x->prev = nullptr; // Optional
// Now release the node you are deleting.
delete x;
As you know there are 3 situations in deleting being
1 - head
2 - middle
3- end
I think you covered the first one lest proceed to the second one
lets say you are in a traversing loop
while( cur != NULL ){
...
cur = cur -> next;
let's look at the middle of the node for second case
For deletion in the middle, you should know the previous node and the next node of to deleted node and you should bind them together. Luckily you both have previous and next in doubly linked list.
so lets add a statement to a code
if ( cur -> data == oddNumber ){
Node* prev = cur -> prev;
Node* next = cur -> next;
prev -> next = cur -> next;
delete cur;
cur = cur -> next;
}
that was for the middle, and for the end (3 rd case) you can simply check if the next node of the node is NULL and delete it peacefully.
I have written the program in which I am making the adjacency list of a graph, which is working perfectly:
class graph {
private:
Q q;
int v; //no of vertixes
struct node* array; //array of vertixes
public:
...
};
Now I want to find the number of components in that graph. I have written this code, but it gives me a segmentation fault error at run time when it try to run findingcomponent() function.
void findingcomponents()
{
int compcount = 0;
int noOfcomp = 0;
node* curr;
for (int i = 0; i < v; i++)
{
curr = array[i].head;
if (curr->next != NULL)
{
while (curr)
{
//while loop for the connected nodes traversel
while (curr)
{
compcount++;
//loop for inner loop traversal and for enque data
if (curr->next->visited != true) //if the next loop of this parent loop is not visited.
{
q.EnQ(curr->next->nodeno);
curr->next->visited = true;
curr = curr->next;
}
else
{
curr = curr->next;
}
}
curr = array[q.deQ()].head;
}
noOfcomp++;
}
}
cout << endl << "There Are : " << noOfcomp << "components in this graph.";
}
Additional infos:
The nodes are defined as follows:
struct node {
int nodeno;
bool visited;
struct node* next;
struct node* head;
};
I use a Q class for managing a queue.
class Q
{
private:
node* front;
node* roar;
public:
...
int deQ()
{
node * temp = new node;
if (front == NULL){
cout << endl << "\t Queue is Empty";
return NULL;
}
else
{
temp = front;
front = front->next;
return temp->nodeno;
}
}
...
};
First problem:
When you look at the head of the adjacency list, here:
curr = array[i].head;
you can't be sure that the list is not empty (i.e. head is nullptr).
So when you write on the next line:
if (curr->next != NULL)
You might dereference a null pointer, which is undefined behaviour and hence might trigger a rutime error (when you're lucky). This happens whenever you have a node which has no edge.
Next problem:
In the inner while loop, you can be sure that curr != nullptr. This time dereferencing is ok, but you can't be sure that curr->next is not null. So when you write
if (curr->next->visited != true)
you might again dereference a null pointer and have undfined behaviour (for example a segfault, if you're lucky).
With the dataset that you've provided, this happens at the first node: the loop goes through the adjacency list, and on the last element the error is triggered.
Other potential problem
I have not analysed in depth your algorithm, as there is important code missing. But it is not clear to me how it is ensured that all enqueued values are dequeued, and that q.deQ() is not called when not called when the queue is empty.
Well, with the additional code provided, in your deQ() you return 0 (NULL) if the queue is empty. But you also return 0 when encountering the node 0. So you don't process correctly the end of the queue, risking to loop for ever.
Therefore you have to change this function to:
int deQ()
{
node * temp = new node;
if (front == nullptr) {
cout << endl << "\t Queue is Empty";
return -1; // <======!!!! Normally you should declare a constant for this
}
else {
temp = front;
front = front->next;
return temp->nodeno;
}
}
Wrapping it together: correction of your function
void findingcomponents()
{
int compcount = 0;
int noOfcomp = 0;
node* curr;
for (int i = 0; i < v; i++) {
curr = array[i].head;
if (curr == nullptr) { // make sure you don't hit isolated nodes
cout << "isolated node";
}
else if (curr->next != nullptr) {
while (curr) { //while loop for the connected nodes traversel
while (curr) {
compcount++;
//loop for inner loop traversal and for enque data
if (curr->next != nullptr && curr->next->visited != true) //!!!!!!if the next loop of this parent loop is not visited.
{
q.EnQ(curr->next->nodeno);
curr->next->visited = true;
}
curr = curr->next; //!!! this was called at the end of the if, and in an else: just call it systematically.
}
int nodeid = q.deQ(); //!!! here deque and
if (nodeid == -1) //!!! check if a node was found in the quue
curr = nullptr; //!!! if not
else curr = array[nodeid].head;
}
noOfcomp++;
}
}
cout << endl << "There Are : " << noOfcomp << "components in this graph.";
}
Please verify however if the number of components is correct. I suspect that you increase the counter in a wrong manner. But you have now 3 hours left to address it.
I've been trying to get a way to sort my Nodes (doubly linked) based on their "Priority" value/variable. However I keep getting stuck at an "Illegal Indirection" error, and not sure what it means (despite looking around).
Any help would be greatly appreciated, here is the code, it was taken from another answered question similar to mine on stackOverflow, so it may be implemented wrongly, but I've supplied part of my Node Class, and the function that uses the Sorting function (within a 'Queue Class');
I've highlighted the error (well pointed it out) in the "Sorting Function" block, any help is appreciated.
NODE CLASS
class Node
{
public:
Node *next; //Pointer to the next node
Node *prev; //Pointer to the previous node
Node(N i, int s, Node *nextptr, Node *prevptr = NULL, int currentPriority = 0, int currentId = 0) //Defines the components that make up the Node Class/Objects
{
val = i; //Value/Data input by the user upon creation of the Node.
priority = currentPriority; //Priority setting of the Node set by the user
processId = currentId; //Unique ID of the Node differentiating it from all other nodes
size = s; //Total number of Nodes.
next = nextptr; //Pointer to the Next Node (Down the Queue)
prev = prevptr; //Pointer to the previous Node (Up the Queue)
}
private:
N val; //Template variable of a value input by the user
int size; //Size variable of the total number of nodes
int priority; //Variable input by the user to determine where in the queue the node is placed
int processId; //Variable automatically set when the node is created. Unique to each Node.
};
Function that Calls it
void Queue::Display(void)
{
bubbleSort(front);
cout << '\n';
}
SORTING FUNCTION
void bubbleSort(Node<T> *&start)
{
int size = back->getProcessId();
int i = 0;
Node<T> *lastSwapped = NULL;
while (size--)
{
Node<T>
*current = start,
*prev = NULL,
*currentSwapped = NULL;
while (current->getPrev() != NULL)
{
Node<T> *after = current->getPrev();
ERROR IS HERE >>> if (*current->getPriority() > *after->getPriority())
{
current->next = after->next;
after->next = current;
if (prev == NULL)
start = after;
else
prev->next = after;
prev = after;
currentSwapped = current;
}
else
{
prev = current;
current = current->getPrev();
}
}
if (currentSwapped == NULL)
break;
else
lastSwapped = currentSwapped;
}
}
I am trying to implement a "priority" queue of strings with an unsorted doubly linked list but I am totally stuck on the dequeue method (at the bottom of the code / there might be issues before however). By priority queue I mean a queue in which the first element to be dequeued is the minimum element.
Would you mind having a look at my code and give me few hints on where I am wrong?
Thanks a lot for your help.
matt
/*************************************************************
* File: pqueue-doublylinkedlist.cpp
*
* Implementation file for the DoublyLinkedListPriorityQueue
* class.
*/
#include "pqueue-doublylinkedlist.h"
#include "error.h"
/* Implementation notes: DoublyLinkedListPriorityQueue constructor
* ----------------------------------------------------------------
* This function initializes an empty priority queue represented as a doubly
* linked-list.
*/
DoublyLinkedListPriorityQueue::DoublyLinkedListPriorityQueue() {
listHead = new Cell;
listHead = NULL;
count = 0;
}
/* Implementation notes: DoublyLinkedListPriorityQueue destructor
* --------------------------------------------------------------
* This function deletes every cell in the priority queue.
*/
DoublyLinkedListPriorityQueue::~DoublyLinkedListPriorityQueue() {
Cell *temp, *link;
temp = link = new Cell;
temp = listHead;
while (temp != NULL) {
link = temp->next;
delete temp;
temp = link;
}
count = 0;
}
/* Implementation notes: DoublyLinkedListPriorityQueue size
* --------------------------------------------------------
* Returns the size of the priority queue.
*/
int DoublyLinkedListPriorityQueue::size() {
return count;
}
/* Implementation notes: DoublyLinkedListPriorityQueue isEmpty
* -----------------------------------------------------------
* Returns true if there is no cell within the list.
*/
bool DoublyLinkedListPriorityQueue::isEmpty() {
return (count == 0);
}
/* Implementation notes: DoublyLinkedListPriorityQueue enqueue
* -----------------------------------------------------------
* Enqueues the new Cell into the chain just after the head Cell.
*/
void DoublyLinkedListPriorityQueue::enqueue(string value) {
Cell *newOne = new Cell;
newOne->str = value;
newOne->prev = NULL;
newOne->next = listHead;
listHead = newOne;
count++;
}
/* Implementation notes: DoublyLinkedListPriorityQueue peek
* --------------------------------------------------------
* Returns the string value of the next node to be dequeued.
*/
string DoublyLinkedListPriorityQueue::peek() {
if (isEmpty()) error("peek an empty list");
curr = new Cell;
curr = listHead;
string result = listHead->str;
for (curr = listHead; curr != NULL; curr = curr->next) {
if (curr->str != "" && curr->str < result) {
result = curr->str;
}
}
return result;
}
/* Implementation notes: DoublyLinkedListPriorityQueue dequeueMin
* --------------------------------------------------------------
* Deletes the node with the smallest string and returns this string value.
*/
string DoublyLinkedListPriorityQueue::dequeueMin() {
if (isEmpty()) error("dequeueMin an empty list");
Cell *temp;
temp = curr = new Cell;
temp = curr = NULL;
string result = listHead->str;
// find the node to delete and store a pointer on it
for (curr = listHead; curr != NULL; curr = curr->next) {
if (curr->str != "" && curr->str < result) {
result = curr->str;
temp = curr;
}
}
// first position (if: node to delete prev == NULL)
if (temp->prev == NULL) {
temp = listHead->next;
delete listHead;
listHead = temp;
// delete from last position (else if: node to delete next == NULL)
} else if (temp->next == NULL) {
curr = temp->prev;
curr->next = NULL;
delete temp;
// other position (else)
} else {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
delete temp;
}
count--;
return result;
}
Implementing a priority queue as a doubly-linked list (or, indeed, implementing one at all) is pretty unusual, since there's an STL implementation available to use:
#include <iostream>
#include <queue>
#include <functional>
int main(void) {
std::priority_queue<std::string, std::vector<std::string>,
std::greater<std::string> > pq;
pq.push("foo");
pq.push("bar");
pq.push("quux");
while( !pq.empty() ) {
std::cout << pq.top() << std::endl;
pq.pop();
}
return 0;
}
I'm posting this on the assumption that, perhaps, you simply didn't know that this functionality was available, rather than there there is a real reason why you want to do your own implementation and do it in a rather odd way.
If I'm wrong, and the above pointer is no use to you, I'd recommend adapting your implementation to the interface of the standard version (as much as you can) and explaining why you don't want to use the STL version, as these steps will increase the familiarity of your code for StackOverflow users (both those who might answer your question better than I can, and future users with similar questions).