currently I'm writing a code which requires me to "copy" a series of integers(user input) from a linkedlist and place them into a queue.
I understand that I require a function called enqueue to proceed, however, I was taught that by simply using the insertNode() function, I can create a basic enqueue function. e.g
void enqueue(Queue *q, int item)
{
insertNode(&(q->ll),q->ll.size, item);
removeNode(ll,0);
}
Given insertNode() :
int insertNode(LinkedList *ll, int index, int value)
{
ListNode *pre, *cur;
if (ll == NULL || index < 0 || index > ll->size + 1)
return -1;
if (ll->head == NULL || index == 0) {
cur = ll->head;
ll->head = malloc(sizeof(ListNode));
ll->head->item = value;
ll->head->next = cur;
ll->size++;
return 0;
}
if ((pre = findNode(ll, index - 1)) != NULL) {
cur = pre->next;
pre->next = malloc(sizeof(ListNode));
pre->next->item = value;
pre->next->next = cur;
ll->size++;
return 0;
}
return -1;
}
and then finally by using another function to make use of the enqueue()
void createQueueFromLinkedList(LinkedList *ll, Queue * q)
{
if (isEmptyQueue) {
removeAllItemsFromQueue(q);
}// empty the queue if it is not empty
while (ll->size)
{
enqueue(q, ll->head->item);
//code to remove ll->size by 1 each time
}
}
int isEmptyQueue(Queue *q)
{
if ((q->ll).size == 0){
return 0;
}
return 1;
}
The problem which I'm facing is that I am not sure whether is my enqueue() working correctly or if there is a better way of going about doing it?
Thanks in advance.
definition of Queue, Linkedlist and ListNode; Suppose I'm not allow to change them :
typedef struct _listnode
{
int item;
struct _listnode *next;
} ListNode;
typedef struct _linkedlist
{
int size;
ListNode *head;
} LinkedList;
typedef struct _queue
{
LinkedList ll;
} Queue;
Related
I need to write a new function called enqueue_priority using my previous enqueue and dequeue functions I cant use sort premade sort I dont know how to implement the priority queue. This is for a simple linux operating system. I am just dragging this out because stack says that My question is mostly code and needs more words but I dont have anything else to say about it
this struct is in a different file
struct pcb {
uint32_t esp;
uint32_t pid;
struct pcb *next;
uint32_t priority;
};
typedef struct pcb pcb_t;
#endif
starts new file
struct pcbq {
pcb_t *head;
pcb_t *tail;
};
typedef struct pcbq pcbq_t;
pcbq_t RR_q;
pcb_t *Running;
void initq(pcbq_t *q) {
q->head = q->tail = 0;
}
bool comparePTR(pcb_t *a1, pcb_t *a2) {
return a1->priority < a2->priority;
}
void enqueue_priority (pcbq_t *q, pcb_t *item){
// item->next = 0;
// if (q->tail == 0) {
// q->tail = q->head = item;
// } else {
// q->tail->next = item;
// q->tail = item;
// }
}
void enqueue(pcbq_t *q, pcb_t *item) {
item->next = 0;
if (q->tail == 0) {
q->tail = q->head = item;
} else {
q->tail->next = item;
q->tail = item;
}
}
void default_handler();
pcb_t *dequeue(pcbq_t *q) {
if (q->head == 0) {
default_handler();
}
pcb_t *item = q->head;
q->head = q->head->next;
return item;
}
void init_rrq() {
Running = 0;
initq(&RR_q);
}
// returns 1 if no process is on the ready Q
int rr_schedule() {
if (Running == 0) {
default_handler();
}
if (RR_q.head == 0)
return 1; // running process is the only one in the system
enqueue(&RR_q, Running);
Running = dequeue(&RR_q);
return 0;
}
void rr_schedule_first() {
if (RR_q.head == 0)
default_handler();
Running = dequeue(&RR_q);
}
void rr_enqueue(pcb_t *pcb) {
enqueue(&RR_q, pcb);
}
Note: As others have mentioned, there are better ways to implement a priority queue. But ...
To implement a priority queue with a linked list, one way is to insert the new item in the correct sorted place when we add a new item.
We have to scan the list looking for the proper place.
Your code had elements of both a doubly linked list and singly linked list. But, it was mostly a singly linked list (e.g. your pcb didn't have a prev pointer).
The only time the tail was used, was to append to the back of the list (in enqueue).
But, to maintain the sort, we'd probably never want to use that, but, only enqueue_priority.
So, I've simplified the code. Also, the RR* stuff wasn't relevant to the queue insertion, so I've elided that as well.
I've coded this, but not tested it:
#include <stdio.h>
#include <stdint.h>
struct pcb {
uint32_t esp;
uint32_t pid;
uint32_t priority;
struct pcb *next;
};
typedef struct pcb pcb_t;
struct pcbq {
pcb_t *head;
};
typedef struct pcbq pcbq_t;
void
initq(pcbq_t *q)
{
q->head = NULL;
}
// enqueue_priority -- enqueue item in proper sorted order
void
enqueue_priority(pcbq_t *q, pcb_t *item)
{
pcb_t *bef = NULL;
pcb_t *cur = q->head;
item->next = NULL;
// find the lower priority (use rightmost of same/equal priority)
for (; cur != NULL; cur = cur->next) {
if (cur->priority > item->priority)
break;
bef = cur;
}
do {
// empty queue
if (q->head == NULL) {
q->head = item;
break;
}
// insert after lower
if (bef != NULL) {
item->next = bef->next;
bef->next = item;
}
// insert before head of non-empty queue
else {
item->next = q->head;
q->head = item;
}
} while (0);
}
// enqueue -- enqueue at back of queue
void
enqueue(pcbq_t *q, pcb_t *item)
{
pcb_t *cur = q->head;
pcb_t *bef = NULL;
item->next = NULL;
for (; cur != NULL; cur = cur->next)
bef = cur;
// append to end of queue
if (bef != NULL)
bef->next = item;
// empty list
else
q->head = item;
}
// dequeue -- dequeue from front of queue
pcb_t *
dequeue(pcbq_t *q)
{
pcb_t *item = q->head;
do {
if (item == NULL)
break;
q->head = item->next;
item->next = NULL;
} while (0);
return item;
}
UPDATE:
The above requires a list scan. However, if we used separate queues for each priority level, we could use a modified version of the above to enqueue and dequeue faster (we add back the tail pointer).
This is [AFAIK] how OSes actually do it. It requires that we look at each queue and check for a non-null head, but with few(er) priority levels (e.g. 10), this will be faster when we have (e.g.) thousands of processes.
So, here's the modified version:
#include <stdio.h>
#include <stdint.h>
struct pcb {
uint32_t esp;
uint32_t pid;
uint32_t priority;
struct pcb *next;
};
typedef struct pcb pcb_t;
struct pcbq {
pcb_t *head;
pcb_t *tail;
};
typedef struct pcbq pcbq_t;
#define MAXPRIORITY 10
pcbq_t allqueues[MAXPRIORITY];
void
initq(pcbq_t *q)
{
q->head = NULL;
}
// enqueue -- enqueue at back of queue
void
enqueue(pcbq_t *q, pcb_t *item)
{
item->next = NULL;
// empty list
if (q->tail == NULL) {
q->tail = item;
q->head = item;
}
// append to end of queue
else {
q->tail->next = item;
q->tail = item;
}
}
// enqueue_priority -- enqueue item in proper sorted order
void
enqueue_priority(pcbq_t *q, pcb_t *item)
{
q += item->priority;
enqueue(q,item);
}
// dequeue -- dequeue from front of queue
pcb_t *
dequeue(pcbq_t *q)
{
pcb_t *item = q->head;
do {
if (item == NULL)
break;
q->head = item->next;
if (item == q->tail)
q->tail = NULL;
} while (0);
return item;
}
// dequeue_priority -- dequeue from front of highest priority queue
pcb_t *
dequeue_priority(pcbq_t *q)
{
pcb_t *item = NULL;
for (int qidx = 0; qidx < MAXPRIORITY; ++qidx, ++q) {
if (q->head != NULL) {
item = dequeue(q);
break;
}
}
return item;
}
lengthOfLinkedList() below counts the number of nodes in a linked list, but the runtime is linear which I do not want. How can I reduce it to a constant runtime function? Are there any library functions I can use?
typedef struct node {
int val;
struct node *next;
} NODE;
struct list_struct {
NODE *front;
NODE *back;
};
int lengthOfLinkedList(LIST *l) {
NODE *n = l->front;
int count = 0;
while (n != NULL) {
count++;
n = n->next;
}
return count;
}
You cannot achieve constant time size calculation with your current struct definition. Now, if you add a size_t member to the struct and use it to store the length, modifying it on any additions or deletions, you can access the length in constant time.
typedef struct node {
int val;
struct node *next;
size_t length;
} NODE;
Define the head-node struct accordingly.
For int value type the list-node remains same:
typedef struct _node {
int val;
struct _node* next;
} listNode_t;
We alter the head-node to suit our needs:
typedef struct {
// add members as scenario demands
int size; // updated after every insert/delete
int min; // updated/checked after every insert/delete/update
int max; // updated/checked after every insert/delete/update
long sum; // updated after every insert/delete/update
listNode_t* first; // to insert/delete from beginning (LIFO-Stack)
listNode_t* last; // to insert at the end (can't delete though)
} listHead_t;
Then you can get those values in O(1), provided they're updated consistently.
listHead_t* head;
...
int listLength = list_getSize (head);
int listMin = list_getMin (head);
int listMax = list_getMax (head);
long listSum = list_getSum (head);
float listAvg = list_getAverage (head); // (float)sum/size
/* List Methods */
list_prefix (head, value); // add value as the first node
list_suffix (head, value); // add value as the last node
That makes list_prefix() like:
...
#include <limits.h>
...
listHead_t* head = list_init_head ();
...
...
listHead_t* list_init_head () {
listHead_t* head = malloc (sizeof(listHead_t));
if (!head) {
perror("list_init_head-malloc");
exit (1);
}
head->size = head->sum = 0;
head->first = head->last = NULL;
head->min = INT_MAX;
head->max = INT_MIN;
return head;
}
int list_prefix (listHead_t* head, int val) {
if (!head) return -1; // invalid call
listNode_t* node = malloc (sizeof(listNode_t));
if (!node) {
perror("list_prefix-malloc");
exit (1);
}
node->val = val;
// update list-head stats
++head->size;
head->sum += val;
if (val < head->min) head->min = val;
if (val > head->max) head->max = val;
if (!head->first) {
node->next = NULL;
head->first = head->last = node;
} else {
node->next = head->first;
head->first = node;
}
return 0;
}
I'm trying to figure out how to limit the number of items in a linked list to 5 from an array of 20, any ideas would be great.
You need a container storing the size of the list, something like:
struct node
{
the data;
struct node *next;
};
typedef struct
{
struct node *head;
struct node *tail;
size_t size;
} queue;
queue *queue_create(void)
{
return calloc(1, sizeof(queue));
}
Now your insert function can return NULL or false when the list is full:
bool insert(queue *list, the *data)
{
if (list->size == 5)
{
return false;
}
struct node *node = malloc(sizeof *node);
if (node == NULL)
{
return false;
}
node->data = data;
node->next = NULL;
if (list->head == NULL)
{
list->head = node;
}
else
{
list->tail->next = node;
}
list->tail = node;
list->size++;
return true;
}
It can be done in so many different ways. The best solution depends on your program, i.e. how the list is used in your program.
One way is like:
// This struct is used for the individual nodes in the list
typedef struct node {
int data;
struct node * next;
} node;
// This struct is used for managing the list - includes a size counter
typedef struct node_list {
struct node * head;
struct node * tail; // optional
size_t size;
} node_list;
#define MAX_SIZE 10
int insert(node_list * l, int data)
{
if (l->size == MAX_SIZE)
{
// List is full
return -1;
}
// Add code to insert the new node
l->size = l->size + 1; // Increase size
return 0;
}
int main()
{
node_list list = {NULL, NULL, 0}; // Create empty list
if (insert(&list, 42) != 0)
{
// Insert failed - list is full
}
return 0;
}
Like the insert function increases size, you need a delete function where you decrease size when a node is deleted.
I have the following linked list implementation:
struct _node {
char *string;
struct _node *next;
}
struct _list {
struct _node *head;
struct _node *tail;
}
I want to make the following function:
void deleteList(struct _list *list, int from, int to) {
int i;
assert(list != NULL);
// I skipped error checking for out of range parameters for brevity of code
for (i = from; i <= to; i++) {
deleteNode(list->head, i);
}
}
// I ran this function with this linked list: [First]->[Second]->NULL
like this deleteNodes(list, 1, 1) to delete the second line and got
[First]->[Second]->NULL but when I run it like this deleteList(list, 0, 1) with this input [First]->[Second]->[Third]->NULL I get a seg fault.
Here is my deleteNode function
void deleteNode(struct _node *head, int index) {
if (head == NULL) {
return;
}
int i;
struct _node *temp = head;
if (index == 0) {
if (head->next == NULL) {
return;
}
else {
head = head->next;
free(head);
return;
}
}
for (i = 0; temp!=NULL && i<index-1; i++) {
temp = temp->next;
}
if (temp == NULL || temp->next == NULL) {
return;
}
Link next = temp->next->next;
free(temp->next);
temp->next = next;
}
I wrote a separate function to delete the head of the linked list if from or to = 0:
void pop(struct _node *head) {
if (head == NULL) {
return;
}
struct _node *temp = head;
head = head->next;
free(temp);
}
but it gives me seg fault or memory error Abort trapL 6.
It's all good to use just one struct, a node for your purpose.
struct node {
char *string;
struct node *next;
};
Then your loop for removing elements between two indices will not delete the right elements if you don't adjust the index according to the changing length of the list. And you must also return the new head of the list.
struct node *deleteList(struct node *head, unsigned from, unsigned to) {
unsigned i;
unsigned count = 0;
for (i = from; i <= to; i++) {
head = delete_at_index(head, i - count);
count++;
}
return head;
}
The help function delete_at_index looks as follows.
struct node *delete_at_index(struct node *head, unsigned i) {
struct node *next;
if (head == NULL)
return head;
next = head->next;
return i == 0
? (free(head), next) /* If i == 0, the first element needs to die. Do it. */
: (head->next = delete_at_index(next, i -
1), head); /* If it isn't the first element, we recursively check the rest. */
}
Complete program below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *string;
struct node *next;
};
void freeList(struct node *head) {
struct node *tmp;
while (head != NULL) {
tmp = head;
head = head->next;
free(tmp->string);
free(tmp);
}
}
struct node *delete_at_index(struct node *head, unsigned i) {
struct node *next;
if (head == NULL)
return head;
next = head->next;
return i == 0
? (free(head), next) /* If i == 0, the first element needs to die. Do it. */
: (head->next = delete_at_index(next, i -
1), head); /* If it isn't the first element, we recursively check the rest. */
}
struct node *deleteList(struct node *head, unsigned from, unsigned to) {
unsigned i;
unsigned count = 0;
for (i = from; i <= to; i++) {
head = delete_at_index(head, i - count);
count++;
}
return head;
}
void pushvar1(struct node **head_ref, char *new_data) {
struct node *new_node = malloc(sizeof(struct node));
new_node->string = strdup(new_data);
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void printListvar1(struct node *node) {
while (node != NULL) {
printf(" %s ", node->string);
node = node->next;
}
printf("\n");
}
int main(int argc, char **argv) {
struct node *head = NULL;
for (int i = 0; i < 5; i++) {
char str[2];
sprintf(str, "node%d", i);
pushvar1(&head, str);
}
puts("Created Linked List: ");
printListvar1(head);
head = deleteList(head, 0, 2);
puts("Linked list after deleted nodes from index 0 to index 2: ");
printListvar1(head);
freeList(head);
return 0;
}
Test
Created Linked List:
node4 node3 node2 node1 node0
Linked list after deleted nodes from index 0 to index 2:
node1 node0
every programming problem can be solved by adding an extra level of indirection: use a pointer to pointer ...
unsigned deletefromto(struct node **head, unsigned from, unsigned to)
{
unsigned pos,ret;
struct node *this;
for (pos=ret=0; this = *head;pos++) {
if (pos < from) { head = &(*head)->next; continue; }
if (pos > to) break;
*head = this->next;
free(this);
ret++;
}
return ret; /* nuber of deleted nodes */
}
I was having some confusion between ListNode and LinkedList. Basically my question was divided into 2 parts. For first part, I was supposed to do with ListNode. The function prototype as such:
int removeNode(ListNode **ptrHead, int index);
All function were working fine for the ListNode part. Then as for the second part, I was supposed to change the function above to this:
int removeNode(LinkedList *11, int index);
My code for part 1 which is working fine look like this:
int removeNode(ListNode **ptrHead, int index) {
ListNode *pre, *cur;
if (index == -1)
return 1;
else if (findNode(*ptrHead, index) != NULL) {
pre = findNode(*ptrHead, index - 1);
cur = pre->next;
pre->next = cur->next;
return 0;
}
else
return 1;
}
ListNode *findNode(ListNode *head, int index) {
ListNode *cur = head;
if (head == NULL || index < 0)
return NULL;
while (index > 0) {
cur = cur->next;
if (cur == NULL) return NULL;
index--;
}
return cur;
}
And here is my entire code for the part 2 which is not working:
#include "stdafx.h"
#include <stdlib.h>
typedef struct _listnode {
int num;
struct _listnode *next;
}ListNode;
typedef struct _linkedlist {
ListNode *head;
int size;
}LinkedList;
void printNode2(ListNode *head);
int removeNode2(LinkedList *ll, int index);
int main()
{
int value, index;
ListNode *head = NULL, *newNode = NULL;
LinkedList *ptr_ll = NULL;
printf("Enter value, -1 to quit: ");
scanf("%d", &value);
while (value != -1) {
if (head == NULL) {
head = malloc(sizeof(ListNode));
newNode = head;
}
else {
newNode->next = malloc(sizeof(ListNode));
newNode = newNode->next;
}
newNode->num = value;
newNode->next = NULL;
scanf("%d", &value);
}
printNode2(head);
printf("\nEnter index to remove: ");
scanf("%d", &index);
removeNode2(ptr_ll, index);
printNode2(head);
return 0;
}
void printNode2(ListNode *head) {
printf("Current list: ");
while (head != NULL) {
printf("%d ", head->num);
head = head->next;
}
}
int removeNode2(LinkedList *ll, int index) {
ListNode *head = ll->head;
if (head == index)
{
if (head->next == NULL)
{
printf("There is only one node. The list can't be made empty ");
return 1;
}
/* Copy the data of next node to head */
head->num = head->next->num;
// store address of next node
index = head->next;
// Remove the link of next node
head->next = head->next->next;
return 0;
}
// When not first node, follow the normal deletion process
// find the previous node
ListNode *prev = head;
while (prev->next != NULL && prev->next != index)
prev = prev->next;
// Check if node really exists in Linked List
if (prev->next == NULL)
{
printf("\n Given node is not present in Linked List");
return 1;
}
// Remove node from Linked List
prev->next = prev->next->next;
return 0;
}
When I try to run the part 2, the cmd just not responding and after a while, it just closed by itself and I have no idea which part went wrong. I was thinking am I in the correct track or the entire LinkedList part just wrong?
When I tried to run in debug mode, this error message popped up:
Exception thrown at 0x01201FD1 in tut.exe: 0xC0000005: Access violation reading location 0x00000000.
If there is a handler for this exception, the program may be safely continued.
Thanks in advance.
You say that you got the linked list to work wihen the list is defined via the head pointer only. In this set-up, you have to pass a pointer to the head pointer when the list may be updated, and just the head pointer when you only inspect the list without modifying, for example:
int removeNode(ListNode **ptrHead, int index);
ListNode *findNode(ListNode *head, int index);
Here, the head pointer is the handle for the list that is visible to the client code.
The approach with the list struct defines a new interface for the linked list. While the head node is enough, it might be desirable to keep track of the tail as well for easy appending or of the number of nodes. This data can be bundles in the linked list struct.
What that means is that the handling of the nodes is left to the list and the client code uses only the linked list struct, for example:
typedef struct ListNode ListNode;
typedef struct LinkedList LinkedList;
struct ListNode {
int num;
ListNode *next;
};
struct LinkedList {
ListNode *head;
ListNode *tail;
int size;
};
void ll_print(const LinkedList *ll);
void ll_prepend(LinkedList *ll, int num);
void ll_append(LinkedList *ll, int num);
void ll_remove_head(LinkedList *ll);
int main()
{
LinkedList ll = {NULL};
ll_append(&ll, 2);
ll_append(&ll, 5);
ll_append(&ll, 8);
ll_print(&ll);
ll_prepend(&ll, 1);
ll_prepend(&ll, 0);
ll_print(&ll);
ll_remove_head(&ll);
ll_print(&ll);
while (ll.head) ll_remove_head(&ll);
return 0;
}
There's also one difference: In the head-node set-up, the head node might be null. Here, the list cannot be null, it must exist. (Its head and tail members can be null, though.) Here the list is allocated on the stack, its address &ll must be passed to the functions.
In the linked list set-up, the distinction between modifying and read-only access is done via the const keyword:
void ll_print(const LinkedList *ll);
void ll_prepend(LinkedList *ll, int num);
In your example, you take a mixed approach with two independent structures, a head node and a list. That can't work, one single list is described by one struct, pick one.
The advantage to the linked list structure approach is that all required data like head, tail and size are always passed together to a function. You can also hide the implementation from the user by not disclosing the struct members, so that theb user can only work on pointers to that struct.
Finally, here's an example implementation of the above interface for you to play with:
void ll_print(const LinkedList *ll)
{
ListNode *node = ll->head;
while (node != NULL) {
printf("%d ", node->num);
node = node->next;
}
putchar('\n');
}
void ll_prepend(LinkedList *ll, int num)
{
ListNode *nnew = malloc(sizeof *nnew);
nnew->next = ll->head;
nnew->num = num;
ll->head = nnew;
if (ll->tail == NULL) ll->tail = ll->head;
ll->size++;
}
void ll_append(LinkedList *ll, int num)
{
ListNode *nnew = malloc(sizeof *nnew);
nnew->next = NULL;
nnew->num = num;
if (ll->tail == NULL) {
ll->tail = ll->head = nnew;
} else {
ll->tail->next = nnew;
ll->tail = nnew;
}
ll->size++;
}
void ll_remove_head(LinkedList *ll)
{
if (ll->head) {
ListNode *ndel = ll->head;
ll->head = ll->head->next;
ll->size--;
free(ndel);
}
}