Malfunctioning priority queue - c

I've been working on some project with queue and priority queue, but I can't find a solution to a problem with priority queue. When a priority queue gets big it does not return me all the values I ask (to totalRegWait). I cut out the part where I only work with queue.
Any help regarding this question would be greatly appreciated.
Main
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "header.h"
int main()
{
ADT *attend; //Attendants
LINK *pQueue; //Priority queue
ADT *temp1; //Temporary
LINK *temp2; //Temporary
int regP; //Regular probability
int vipP; //VIP probability
int regA; //Regular attendants
int vipA; //VIP attendants
int sumA; //Combined attendants
int regT; //Regular time
int vipT; //VIP time
int bankT; //Bank working time
int i;
int attWait=0, attWait2=0; //Attendants wait time
int overtime=0, overtime2=0; //Attendants overtime
int totalRegWait=0, totalRegWait2=0; //Total regular client waiting time
int regCount=0; //Regular person count
int vipWait=0, vipWait2=0; //Maximum VIP waiting time
int vipCount=0; //Amount of VIP
getArguments(&regP, &vipP, &regA, &vipA, &regT, &vipT, &bankT);
sumA=regA+vipA;
create(&attend);
for(i=0;i<sumA;i++){
enq(&attend, 0);
}
createEmpty(&pQueue);
srand(time(NULL));
for(i=0;i<bankT;i++){
if(rand()%100<regP){
regCount++;
add(&pQueue, 0, 0);
}
if(rand()%100<vipP){
vipCount++;
add(&pQueue, 1, 0);
}
//1st method
first(&attend, &pQueue, vipT, regT, &vipWait, &totalRegWait, &attWait);
}
printf("%d %d\n", regCount, vipCount);
printf("%d %d\n", totalRegWait, totalRegWait2);
//Printing results
printf("First method:\n");
printResults(attWait, overtime, totalRegWait, regCount, vipWait, vipCount);
return 0;
}
Functions
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
void createEmpty(LINK **head) {
(*head)=NULL;
}
void add(LINK **head, int p, DATA v){
LINK *curr=(*head);
LINK *beforeCurr=(*head);
LINK *newElement;
newElement=(LINK*)malloc(sizeof(LINK));
if(newElement==NULL){
printf("Error. Not enough memory to allocate.\n");
}
newElement->priority=p;
newElement->value=v;
newElement->next=NULL;
if((*head)==NULL){
(*head)=newElement;
}
else if(p<(*head)->priority){
newElement->next=curr;
(*head)=newElement;
}
else{
while(p>(curr->priority) && curr->next!=NULL){
beforeCurr=curr;
curr=curr->next;
}
if(curr->next==NULL && p>(curr->priority))
(curr->next)=newElement;
else if(curr==(*head)){
newElement->next=curr;
(*head)=newElement;
}
else{
beforeCurr->next=newElement;
newElement->next=curr;
}
}
}
void pop(LINK **head, int *p, DATA *v, int *error){
LINK *curr=(*head);
LINK *currB=(*head);
if(*head==NULL){
(*error)=1;
}
else if(curr->next==NULL){
(*p)=curr->priority;
(*v)=curr->value;
free(curr);
(*head)=NULL;
}
else{
while(curr->next!=NULL) {
currB=curr;
curr=curr->next;
}
(*p)=curr->priority;
(*v)=curr->value;
free(curr);
currB->next=NULL;
}
}
int checkIfEmpty(LINK *head){ //Working
if(head==NULL)
return 1;
else
return 0;
}
//-------------------------------
void create(ADT **front){ //Working
*front = NULL;
}
void enq(ADT **front, QDATA variable){ //Should be good
ADT *temp;
ADT *rear = (ADT *)malloc(sizeof(ADT));
if(rear==NULL){
printf("Error. Not enough memory to allocate.\n");
}
if(*front == NULL)
{
*front = (ADT *)malloc(sizeof(ADT));
if(*front==NULL){
printf("Error. Not enough memory to allocate.\n");
}
(*front)->var = variable;
(*front)->next = NULL;
}
else
{
temp = *front;
while(temp->next != NULL){
temp = temp->next;
}
rear->var = variable;
rear->next = NULL;
temp->next = rear;
}
}
//--------------------------------
void first(ADT **attend, LINK **pQueue, int vipT, int regT, int *vipWait, int *totalRegWait, int *attWait){
ADT *temp1;
LINK *temp2;
int priority;
DATA value;
int error=0;
if(checkIfEmpty(*pQueue)==1){ //If client's queue is empty, time is changed to attenders and increased att. waiting time
temp1=(*attend);
while(temp1 != NULL){
if((temp1->var)>0){
(temp1->var)--;
}
else{
(*attWait)++;
}
temp1 = temp1->next;
}
}
else{ //If there are clients, look for not occupied attenders
temp1=(*attend);
temp2=(*pQueue);
while(temp1 != NULL){ //While loop which goes through all the attenders
if((temp1->var)>0){ //If attender is busy
(temp1->var)--; //Yes, then it's value is decreased by 1
}
else{ //If attender value is not busy
if(checkIfEmpty(*pQueue)==1){ //Check if priority line is empty
(*attWait)++; //If yes, waiting time for attenders is added
}
else{ //If priority line is not empty
pop(&(*pQueue), &priority, &value, &error); //Client is removed from queue
printf("%d %d\n", priority, value);
if(error==1){ //If pop fails it shows an error and quit
printf("Error\n");
return 0;
}
else{ //If pop does not fail
if(priority==1){ //Check if client is VIP
temp1->var=vipT; //If yes, then attender is given VIP time to his value
if((*vipWait)<value){ //If VIP client's waiting time is higher than earlier value
(*vipWait)=value; //Earlier VIP waiting time is changed
}
}
if(priority==0){ //If client is regular
temp1->var=regT;
(*totalRegWait)=(*totalRegWait)+value; //Removed client's waiting value is added to a total value
(temp1->var)--;
}
(temp1->var)--; //Attender time is lowered by 1 (end of minute)
}
}
}
temp1 = temp1->next; //Going for another attender
}
if(checkIfEmpty(*pQueue)==0){ //Check if priority queue is empty
while(temp2!=NULL) {
(temp2->value)++; //Waiting time to a client is added
temp2 = temp2->next; //Next client
}
}
}
}
Header
#ifndef HEADER_H_
#define HEADER_H_
typedef int DATA;
typedef int QDATA;
typedef struct priorityQueue{
int priority;
DATA value;
struct priorityQueue *next;
}LINK;
typedef struct list
{
QDATA var;
struct list *next;
}ADT;
void enq(ADT **front, QDATA variable);
void create(ADT **front);
//PRIORITY QUEUE FUNCTIONS
void createEmpty(LINK **head);
void add(LINK **head, int p, DATA v);
void pop(LINK **head, int *p, DATA *v, int *error);
int checkIfEmpty(LINK *head);
//END OF PRIOR. QUEUE FUNCTIONS
void first(ADT **attend, LINK **pQueue, int vipT, int regT, int *vipWait, int *totalRegWait, int *attWait);
#endif

Related

Maintaining a queue using structures in C

If I input 'E 5' I need to enqueue 5 onto the queue with no output. If I input 'D' I need to print the dequeued element.
Below is my code:
#include<stdio.h>
#include <stdlib.h>
typedef struct queue{
int start;//first element index
int end;//last element index
int size;//length of queue
int *ptr;//actual queue
}queue;
queue* createQueue(int x){
queue* Q=(queue*)malloc(sizeof(queue));
Q->start=0;
Q->end=0;
Q->size=1;
Q->ptr[0]=x;
return Q;
}
void enqueue(int x, queue*qptr, int i){
qptr->size++;//increase size
qptr->end++;//increase index of last element
qptr->ptr[i]=x;
return;
}
void dequeue(queue*qptr){
if(qptr->size==0){
printf("Empty\n");
return;
}
printf("%d\n",qptr->ptr[qptr->start]);
qptr->start++;
qptr->size--;
}
int main(){
char a; int i=0;int j;queue* qptr;
while(scanf("%c",&a)!=-1){
if(a=='E'){
if(i==0){
scanf("%d",&j);
qptr =createQueue(j);
i++;
}
else{
scanf("%d",&j);
enqueue(j, qptr, i);
i++;
}
}
else if(a=='D'){
if(i==0){printf("Empty\n");}
else {dequeue(qptr);i++;}
}
}
return 0;
}
I don't understand what are my errors because it seems correct to me but the code doesn't compile. Please help me.

I was trying to create a Queue ADT in C but something is wrong in my code... can Anyone Fix this?

A Program to implement Queue ADT using C
Declaring the headers in .c file or header file doesn't change anything in the errors
1) Header File (queue.h)
#ifndef QUEUE
#define QUEUE
#include <stdio.h>
#include <stdlib.h>
typedef struct QNodeType
{
char ch;
struct QNodeType *next;
}QNode;
typedef struct QueueType
{
QNode *head,*tail;
}Queue;
Queue **Create_Queue(); // Initialize the queue
void ClearQueue(); // Remove all items from the queue
int Enqueue(Queue **q,char ch); // Enter an item in the queue
char Dequeue(Queue **q); // Remove an item from the queue
int isEmpty(Queue **q); // Return true if queue is empty
int isFull(Queue **q); // Return true if queue is full
// Define TRUE and FALSE if they have not already been defined
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#endif
2) .c File for defining the queue functions
#include "queue.h"
Queue** Create_Queue()
{
Queue **q;
(*q)->head = (*q)->tail = NULL;
return q;
}
void ClearQueue(Queue **q)
{
QNode *temp;
while((*q)->head != NULL)
{
temp = (*q)->head;
(*q)->head = (*q)->head->next;
free(temp);
}
(*q)->head = (*q)->tail = NULL; // Reset indices to start over
}
int Enqueue(Queue **q,char ch)
{
QNode *temp;
if(isFull(q)) return FALSE;
temp = (QNode *)malloc(sizeof(QNode));
temp->ch = ch;
temp->next = NULL;
if((*q)->head == NULL)
(*q)->head = (*q)->tail = temp;
else
{
(*q)->tail->next = temp; // Insert into the queue
(*q)->tail = temp; // Set tail to new last node
}
return TRUE;
}
char Dequeue(Queue **q)
{
char ch;
QNode *temp;
if(isEmpty(q)) return '\0';
else
{
ch = (*q)->head->ch;
temp = (*q)->head;
(*q)->head = (*q)->head->next;
free(temp);
if(isEmpty(q))
{
(*q)->head = (*q)->tail = NULL;
}
}
return ch;
}
int isEmpty(Queue **q)
{
return ((*q)->head == NULL);
}
int isFull(Queue **q)
{
return FALSE;
}
3) Driver program or the main code
#include "queue.h"
int main()
{
char testString[27];
int i;
char ch;
Queue **q=Create_Queue();
Enqueue(q,'A');
printf("Enqueued: %c\n", Dequeue(q));
strcpy(testString, "abcdefghijklmnopqrasuvwxyz");
i = 0;
printf("Testing enqueuing of string: %s\n", testString);
while(testString[i] != '\0')
{
if(!Enqueue(q,testString[i]))
{
printf("Queue is full. Unable to enqueue %c\n", testString[i]);
}
i++;
}
printf("Dequeued letters are...\n");
while((ch = Dequeue(q)) != '\0') // Dequeue returns null terminator
printf("%c", ch); // when queue is empty
printf("\nEnd of queue encountered...\n");
return 0;
}
The above program shows segmentation fault when run on Linux and an arbitrary return value when run on dev c++.
But when I run the code without the QUEUE Structure(basically this means declaring a *head and *tail pointer of static type in the queue.c file which allows for only one queue to be created at a time. And thus the CreateQueue function will be of void type and other functions doesn't require an argument of type Queue**)) it ran without any bugs.
I think that the problem is in create_Queue() you are not allocating any memory in it, after that in void ClearQueue() you are using free().

Finding path between nodes using BFS in C language

I'm new to C language and it's been harder for me to work with pointers after working in Java😥
I was trying to write a code of finding a path (not necessary minimum) between two nodes in a graph using breadth-first-search.
Here is my code :
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 200
void push(int a);
int pop(void);
void bfs(int a,int b,int len);
int nextnode(int a);
typedef struct node{
int data;
struct node* next;
}node;
int res[MAXSIZE];
int visited[MAXSIZE];
int rear,front;
node* graph[MAXSIZE];
int len;
int path[MAXSIZE];
int nextnode(int a)
{
if(graph[a]==NULL)
return -1;
else
{
struct node* c=graph[a];
while(visited[c->data]!=1 && c!=NULL)
{
c=c->next;
}
if(c==NULL)
return -1;
else
return c->data;
}
}
void push(int a)
{
path[rear]=a;
rear++;
}
int pop()
{
if(front==rear)
return -1;
int num=path[front];
front++;
return num;
}
int main()
{
rear=0;
len=0;
front=0;
int n,e;
int i,a,b;
printf("%s\n%s", "Inputting Graph... ","Enter number of nodes and edges: ");
scanf("%d %d",&n,&e);
printf("%s %d %s\n", "Graph Created with",n,"nodes without any edge.");
printf("%s\n","Enter the edges in 1 2 format if an edge exist from Node 1 to Node 2" );
for(i=1;i<=n;i++)
{
graph[i]=NULL;
visited[i]=0;
}
struct node* new = (struct node*)malloc(sizeof(struct node));
for(i=0;i<e;i++)
{
scanf("%d %d",&a,&b);
new->data=b;
new->next=NULL;
struct node* curr=graph[a];
if(curr==NULL)
{
graph[a]=new;
}
else
{
while(curr->next!=NULL)
{
curr=curr->next;
}
curr->next=new;
}
}
printf("%s\n", "Graph Created Successfully.");
printf("%s", "Enter the node numbers between which the path is to be found between: ");
scanf("%d %d",&a,&b);
bfs(a,b,0);
printf("Length is %d\n",len);
for(i=1;i<=len;i++)
{
printf("%d\n",res[len]);
}
}
void bfs(int a,int b,int len)
{
int c;
visited[a]=1;
int flag=0;
while(a!=-1)
{
c=nextnode(a);
while(c!=-1)
{
c=nextnode(a);
if(c==b)
{
flag=1;
break;
}
push(c);
visited[c]=1;
}
len++;
res[len]=a;
if(flag==1)
{
res[len]=b;
break;
}
a=pop();
}
}
I know it's huge, but please mind going through it once. The problem I'm getting is Segmentation Fault after I input all the values, and before dfs() function call! Please Help.
For understanding: I have used array of Lists. Each array index denotes a node and the list denotes all the edges it is connected to. eg: if my Graph has 1->2, 1->3, 2-3 edges;
graph[1] will have a list 2->3->NULL. And graph[2] will have 3->NULL.
Thank you.
EDIT
As pointed out by Aditi, the error was in the line where nextnode function ran the while loop. After changing the code to
while(c != NULL && visited[c->data] == 1 )
the program ran flawlessly.
Thanks!
I think what you are trying to do is not graph[i] = NULL but graph[i]->next = NULL

Traversing and printing a queue in C behaves differently when input is given by the user

I apologise if this concept has been explained on SOF before! I believe my case is slightly different and couldn't find a similar question in the website.
Here's the problem:
I'm trying to store char arrays (strings) in a Queue structure that I'm trying to implement.
The structure and its functions seem to work fine when I hardcode the data myself like this:
#include "Time.h"
#include <unistd.h>
int main(void){
struct Queue* q = CreateQueue();
Enqueue(q, "element1");
Enqueue(q, "element2");
Enqueue(q, "element3");
Enqueue(q, "element4");
PrintAll(q->first); // this outputs all elements and the time they've been in the queue.
return 0;
}
The output is as expected, a list of all 4 elements.
However, as soon as I put a simple menu together, to capture the data from the user instead of it being hardcoded as above, the PrintAll() function outputs a duplicate of the very last element enqueued. You also notice that I am timing each node to keep a track on when it was added to the queue and that seem to work fine. Although the ouput shows the last element entered duplicated N times (N being the size of the queue) the timer seems to show correctly for each node!
I am suspecting it's to do with the stdin stream that is not being cleaned but I thought I handled that with a block of code that is shown in main() function.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void){
char name[31];
char c;
int option;
int ch;
struct Queue* q = CreateQueue();
do
{
printf("\n 1. Add a an element to the queue");
printf("\n 2. Print all elements");
printf("\n 0. Exit");
printf("\n Please select an option");
while(scanf("%d", &option)!=1){
puts("Value non good");
ch=getchar();
while(ch!=EOF && ch!='\n'){
ch=getchar();
}
}
switch(option)
{
case 1:
{
ch=getchar();
while(ch!=EOF && ch!='\n')
{
ch=getchar();
}
printf("Please enter the name of the element.\n ");
fgets(name,30,stdin);
Enqueue(q, name);
PrintAll(q->first);
break;
}
case 2:
{
PrintAll(q->last);
break;
}
default:
return 0;
}
}while(option != 0);
return 0;
}
Can anybody please shed light on the problem ? I would appreciate it.
here's the rest of the code:
Time.c:
#include "Time.h"
struct Queue* CreateQueue()
{
struct Queue* q = malloc(sizeof(struct Queue));
q->first = NULL;
q->last = NULL;
q->size = 0;
return q;
}
void Enqueue(struct Queue* queue, char* string)
{
struct Node* newNode = malloc(sizeof(struct Node));
newNode->next = NULL;
newNode->student = string;
newNode->start_time = time(0);
if(queue->size == 0)
{
queue->first = newNode;
}
else
{
queue->last->next = newNode;
}
queue->last = newNode;
queue->size = queue->size + 1;
}
char* Dequeue(struct Queue* queue)
{
if (queue->size < 0)
{
exit(0);
}
char* toBeRemoved = queue->first->student;
struct Node* oldNode = queue->first;
queue->first = oldNode->next;
queue->size = queue->size - 1;
if(queue->size == 0)
{
queue->last = NULL;
}
free(oldNode);
return toBeRemoved;
}
int IsEmpty(struct Queue *q)
{
return q->size == 0;
}
char* Peek(struct Queue *q)
{
return q->first->student;
}
void PrintOne(struct Node *node)
{
if(node !=NULL)
{
int elapsed = ElapsedTime(node);
printTime(elapsed, node->student);
//printf("%s\n", node->student);
}
}
void PrintAll(struct Node* node)
{
if (node !=NULL)
{
PrintAll(node->next);
PrintOne(node);
}
}
// returns the waiting time for a student node.
int ElapsedTime(struct Node* node)
{
int elapsed;
time_t stop_time;
stop_time = time(NULL);
elapsed = difftime( stop_time , node->start_time );
return elapsed;
}
void printTime(int elapsed, char* student_name)
{
printf("%s : waiting for ", student_name);
int minutes_or_hours = 0; //Stores a zero to indicate that it is not neccesary to print minutes or hours.
//Stores a one to indicate that hours and/or minutes have been printed.
if( (elapsed / 3600) >= 1)
{
int hours = elapsed/3600;
if(hours == 1)
{
printf("1 hour, ");
}
else
{
printf("%d hours, ", hours);
}
elapsed = elapsed - (hours*3600);
minutes_or_hours = 1;
}
if( (elapsed / 60) >= 1)
{
int minutes = elapsed/60;
if(minutes == 1)
{
printf("1 minute, ");
}
else
{
printf("%d minutes, ", minutes);
}
minutes_or_hours = 1;
elapsed = elapsed - (minutes*60);
}
if(minutes_or_hours == 1)
{
printf("and ");
}
printf("%d seconds\n", elapsed);
}
Time.h:
#ifndef TIME_H_
#define TIME_H_
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Node
{
time_t start_time;
struct Node* next;
char* student;
};
struct Queue
{
int size;
struct Node* first;
struct Node* last;
};
struct Queue* CreateQueue();
void Enqueue(struct Queue* , char* );
char* Dequeue(struct Queue* );
int IsEmpty(struct Queue *);
char* Peek(struct Queue *);
void PrintOne(struct Node *);
void PrintAll(struct Node *);
int ElapsedTime(struct Node* );
void printTime(int , char* );
#endif /* TIME_H_ */
In the function Enqueue() you have only copied the string pointer to your structure. In your first case that works, because all the four strings have different pointers to string literals. But in your second example, you are storing the pointer of your data entry name, and the contents of this string change with each entry. Each structure store the same pointer, so all point to the most recent string you typed in. If your struct stored the actual string, it would work (but you need to be careful with string lengths).
struct Node
{
time_t start_time;
struct Node* next;
char student[31];
};
void Enqueue(struct Queue* queue, char* string)
{
...
strncpy (newNode->student, 30, string);
...
}

Linked List problems with process sync

This program is a work in progress. It is going to simulate a multiprocessor and I am programming it with producer-consumer sync.
Few problems here:
- My pending_request counter starts 1 lower than it should and goes down to -1. It should stop at 0.
- My remove_queue function also keeps removing one over. It will remove until the list is blank, but it doesn't recognize the list is empty. Then if I run remove_queue one more time, then it recognizes the list empty. SAMPLE OUTPUT AT THE BOTTOM at http://tinyurl.com/3ftytol
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
typedef struct pr_struct{
int owner;
int burst_time;
struct pr_struct *next_prcmd;
} prcmd_t;
static prcmd_t *pr_head = NULL;
static prcmd_t *pr_tail = NULL;
static int pending_request = 0;
static pthread_mutex_t prmutex = PTHREAD_MUTEX_INITIALIZER;
int add_queue(prcmd_t *node)
{ pthread_mutex_lock(&prmutex);
//code
prcmd_t *curNode = pr_head;
if(pr_head == NULL) { pr_head = node; return;}
while(curNode->next_prcmd)
{
curNode = curNode->next_prcmd;
}
curNode->next_prcmd = node;
//
pending_request++;
pthread_mutex_unlock(&prmutex);
return(0);
}
int remove_queue(prcmd_t **node)
{
pthread_mutex_lock(&prmutex);
if(pr_head == NULL)
{
//your code
printf("Queue is empty\n");
//
pthread_mutex_unlock(&prmutex);
return(-1);
}
else
{
//your code
prcmd_t *tempNode; tempNode = (prcmd_t*)malloc(sizeof(prcmd_t));
tempNode = *node;
*node = tempNode->next_prcmd;
free(tempNode);
//
pending_request--;
pthread_mutex_unlock(&prmutex);
return(0);
}
}
int get_number_request(void)
{ return pending_request; }
void display_list(prcmd_t *node)
{
if (pr_head == NULL)
{
printf("List is empty!\n\n");
}
printf("-----------\n");
while(node)
{
printf("%i %i\n", node->owner,node->burst_time);
node = node->next_prcmd;
}
int r = get_number_request();
printf("Pending requests: %i\n", r);
}
int main()
{
int i=0;
int length = 4;
prcmd_t *pr[length];
for(i =0;i<length;i++)
{
pr[i] = (prcmd_t*)malloc(sizeof(prcmd_t));
pr[i]->owner = i+1;
pr[i]->burst_time = i + 2;
add_queue(pr[i]);
}
display_list(pr_head);
remove_queue(&pr_head);
display_list(pr_head);
remove_queue(&pr_head);
display_list(pr_head);
remove_queue(&pr_head);
display_list(pr_head);
remove_queue(&pr_head);
display_list(pr_head);
remove_queue(&pr_head);
display_list(pr_head);
}
some things (although maybe not all):
There is no need for a tail pointer if the list is not doubly linked, because there is no way to go from tail to head (no previous pointer)
Why do you malloc in your remove queue?
*node = prHead;
prHead = prHead->next_prcmd;
--pending_request;
in add_queue you have to node->next_prcmd = NULL; otherwwise you will never know the end.
again, some things, but maybe not all...
Mario

Resources