I need to make three threads with shared access to linkedlist: searching,adding,removing thread. Seaching thread only browsing through list. Adding threads add item at the end of list and they are mutual exclusive (protected by mutex) but you can searching and adding at the same time. Removing threads remove item from any point at the list and they are mutal exclusive with adding and searching.
My linked list:
struct node
{
int data;
struct node *next;
}
void search(int num)
{
int flag = 0;
struct node *temp;
temp = start;
while(temp!=NULL)
{
if(temp->data == num)
return(temp); //Found
temp = temp->next;
}
if(flag == 0)
return(start); // Not found
}
void insert(int num)
{
int c=0;
struct node *temp;
temp=head;
if(temp==NULL)
{
add(num);
}
else
{
while(temp!=NULL)
{
if(temp->data<num)
c++;
temp=temp->next;
}
if(c==0)
add(num);
else if(c<count())
addafter(num,++c);
else
append(num);
}
}
int delete(int num)
{
struct node *temp, *prev;
temp=head;
while(temp!=NULL)
{
if(temp->data==num)
{
if(temp==head)
{
head=temp->next;
free(temp);
return 1;
}
else
{
prev->next=temp->next;
free(temp);
return 1;
}
}
else
{
prev=temp;
temp= temp->next;
}
}
return 0;
}
If anyone could show me way how to do with threads and mutex I will be so thankful
Assuming you are using pthread.h.
First you should add a struct for you linked list:
typedef struct
{
struct node *first;
pthread_mutex_t list_mutex;
} *List;
And then add pthread_mutex_lock(&list_mutex); to the start of each function and pthread_mutex_unlock(&list_mutex); to the end.
Also your functions should receive a List as an argument, so you need to change the function definitions.
You should read about Pthread mutex locks.
Related
I am trying to return the head of a linked list in the function Insert of the following program. However, it is failing with compilation error.
Can anyone please tell me what wrong I have done:
#include<stdio.h>
#include<stdlib.h>
struct ListNode
{
int data;
struct ListNode *next;
};
int ListLength(struct ListNode *head)
{
int count = 0;
struct ListNode *temp=head;
while(temp!=NULL)
{
count++;
temp=temp->next;
}
return count;
}
struct ListNode *Insert(struct ListNode *head, int value, int pos)
{
struct ListNode *temp,*curr;
curr=head;
int k=1;
temp=(struct ListNode *)malloc(sizeof(struct ListNode));
if(pos==1)
{
temp->data=value;
if(head==NULL)
{
temp->next=NULL;
head=temp;
}
else
{
temp->next=head;
head=temp;
}
}
else
{
while((curr!=NULL) && (k<pos))
{
k++;
curr=curr->next;
}
temp->data=value;
temp->next=curr->next;
curr->next=temp;
}
return head;
}
void printList(struct ListNode *head)
{
struct ListNode *temp;
temp=head;
while(temp!=NULL)
{
printf("%d",temp->data);
printf(" ");
temp=temp->next;
}
}
int main
{
struct ListNode *head=NULL;
//head = NULL;
head=Insert(head,10,1);
//Insert(head,11,2);
printList(head);
return 0;
}
I am trying to return the head of the new linked list after the insertion. I don't know where I am going wrong. Thanks in advance for the help.
(i) Firstly, include int main(void) as mentioned in the comments.
(ii) Next, with your current code, when you try printing the list, you are going to be in an infinite loop and get a stack overflow.
To avoid this, increment the temp to point to the next node after each print.
So your print function should look like:
void printList(struct ListNode *head)
{
struct ListNode *temp;
temp=head;
while(temp!=NULL)
{
printf("%d",temp->data);
printf(" ");
temp=temp->next; // this line is required
}
}
(iii) And in your main function, call the printList with an argument, that is the head of the node like this:
printList(head);
(iv) And don't forget to return the count in your finding the length of the list function. Add the return statement at the end of your ListLength function:
return count;
(v) Your current code does not handle a case when head is NULL, and user wants to insert at a position greater than 1. Or more generally, when a user wants to insert at a position that is greater than the current list's length.
While you trust such an input would not be given, always handle such exceptions (you would probably get a SEGMENTATION FAULT here when trying to access memory of null nodes).
To handle this, you can add a check at the start of the Insert function like,
int lenList = ListLength(head);
if (lenList < pos)
{
printf("Please provide a position less than %d to insert", lenList);
return 0; // don't proceed with inserting node with NULL pointers
}
If head is declared global you don't have to return it. (Sorry, my answer is short)
I'm working on a C code. I have a singly linked list, and i want to delete a node,which i don't know the position of it. My struct is this:
struct list_node{
int num;
char name[25];
int year;
float money;
struct list_node *next;
};
typedef struct list_node node;
node *head=NULL;
I have a value which i have to compare with the node->name so it deletes the node. How can i do this? I had tried with this code to do this:
value=argv[2];
temp=head;
if(temp==NULL){
return 0;
}
if(strcmp(current->name,value)==0){
temp=head;
head=head->next;
free(temp);
return 0;
}
p=head;
while(p->next!=NULL){
if(strcmp(p->next->name,value)==0){
temp=p->next;
p->next=temp->next;
free(temp);
return 0;
}
p=p->next;
}
return 0;
}
but the node was not deleted. (I have a function to print the list)
Try this code.. I think you probably have made mistake in taking pointers to structures!
{
node* temp;
node * ptr=head;
if(ptr=NULL)
{
return 0;
}
else if(strcmp(ptr->name, name2)==0)
{
head=head->next;
free(ptr);
return 0;
}
while(ptr->next!=NULL)
{
if(strcmp(ptr->next->name, name2)==0)
{
temp=ptr->next;
ptr->next=ptr->next->next;
free(temp);
return 0;
}
ptr=ptr->next;
}
printf("Node not found!");
return 0;
}
I have a value which i have to compare with the node->name so it
deletes the node. How can i do this?
… not too complicated:
node *curr, **prev;
for (prev = &head; curr = *prev; prev = &curr->next)
if (strcmp(curr->name, value) == 0)
{
*prev = curr->next,
free(curr);
break;
}
I have written this code in c to implement linked list. while the semantic and syntax are fine, it does not work as it should. For example, when I insert 1 into the list and then print the linked list, it shows that the list is empty.
#include<stdio.h>
#include<stdlib.h>
struct node {
int info;
struct node *next;
}; typedef struct node Node;
void addNode(Node *head, int x)
{
Node *temp;
temp=malloc(sizeof(temp));
temp->info=x;
if (head==NULL)//if this is the first node in the list
{
head=temp;
temp->next=NULL;
}
else //if not, add it as the head
{
temp->next=head;
head=temp;
}
}
void appendNode(Node *head, int x)
{
Node *rear =head;
Node *temp= malloc(sizeof(temp));
temp->info=x;
temp->next=NULL;
while (rear->next!=NULL)
rear=rear->next;
rear->next=temp;
rear=temp;
}
void insertNodeafter(Node *head, int location, int x)
{
int i;
Node *before, *after = head;
Node *temp= malloc(sizeof(temp));
temp->info=x;
for (i=0;i<location;i++)
before=before->next;
after=before->next;
temp->next=after;
before->next=temp;
}
void insert(Node *head, int x)
{
int c=0;
Node *temp;
temp=head;
if(temp==NULL)
{
addNode(temp,x);
}
else
{
while(temp!=NULL)
{
if(temp->info<x)
c++;
temp=temp->next;
}
if(c==0)
addNode(temp,x);
else if(c<listSize())
insertNodeafter(temp,x,++c);
else
appendNode(temp,x);
}
}
int listSize()
{
Node *head, *n;
int c=0;
n=head;
while(n!=NULL)
{
n=n->next;
c++;
}
return c;
}
void DisplayLinkedList(Node* head)
{
Node *rear=NULL;
if (head==NULL)
printf("list is empty!\n");
else
{
rear=head;
while (rear!=NULL)
printf("%d |---> ", rear->info);
rear=rear->next;
}
}
int getNextNode(Node *head)
{
if (head == NULL)
return -1;
else
return head->next->info;
}
Node* deleteNode(Node *head, int x)
{
Node *temp;
if (head == NULL)
return NULL;
else
{
if (head->info==x)
{
temp = head->next;
free(head);
head=temp;
return head;
}
else
{
deleteNode(head->next,x);
return head;
}
}
}
void main()
{
int i=0;
Node *myNode;
insert(myNode,1);
DisplayLinkedList(myNode);
}
Because you are using Node* variable instead of using Node** variable in function parameter. Since you are using Node* so changes done in variable head is local to that function. If you want to reflect these changes even after function call(which you obviously wants to) then use Node** and use it accordingly in your code.
As the previous poster has mentioned, it is best to use Node** variable to reflect changes after a function call. If you wanted to use Node*, you'd have to return Node* back to main to print from it.
I pared your code down to add the 1, using AddNode, insert and DisplayLinkedList and it is now displaying correctly with the code below.
You should also set Node* to NULL in main to initialize the empty linked list. Check your DisplayLinkedList function - you're missing curly brackets in the while loop. It was only reading the printf line and not traversing the list, leading to an infinite loop.
Best practice is to debug and test as you are creating this program.
#include<stdio.h>
#include<stdlib.h>
#include "stack.h"
void main()
{
int i=0;
Node *myNode;
myNode = NULL;
insert(&myNode,1);
DisplayLinkedList(myNode);
}
void addNode(Node **head, int x)
{
Node *temp;
temp=malloc(sizeof(temp));
temp->info=x;
if (*head==NULL)//if this is the first node in the list
{
*head=temp;
temp->next = NULL;
}
else //if not, add it as the head
{
temp->next=*head;
*head=temp;
}
}
void insert(Node **head, int x)
{
int c=0;
Node *temp;
temp=*head;
if(temp==NULL)
{
addNode(head ,x);
}
}
void DisplayLinkedList(Node* head)
{
Node *rear=NULL;
if (head==NULL)
printf("list is empty!\n");
else
{
rear=head;
while (rear!=NULL)
{
printf("%d |---> ", rear->info);
rear=rear->next;
}
}
}
void sortlist()
{
struct node *a;
struct node *temp=head;
struct node *temp1=head->next;
while(temp!=NULL)
{
while(temp1->next!=NULL)
{
if(temp->data > temp1->data)
{
a->data=temp->data;
temp->data=temp1->data;
temp1->data=a->data;
}
else
{
temp1=temp1->next;
}
}
temp=temp->next;
}
}
//I am new to data structures.i am encountering some problem here while trying to sort elements of linked list.list does not get sorted.any help is greatly appreciated.
a is an uninitialised pointer so the line
a->data=temp->data;
invokes undefined behaviour. Crashing is the most likely result here as you'll try to write to memory at an undefined address that may not be writeable by your code or may be in use by another part of your program.
You could fix this by giving a the same type as temp->data instead.
void sortlist()
{
int a; // change type to match node->data if required
...
if(temp->data > temp1->data)
{
a=temp->data;
temp->data=temp1->data;
temp1->data=a
}
...
}
EDIT: There is also a potential NULL dereference crash in the line while(temp1->next!=NULL). The code below shows a potential implementation of sortlist which avoids this.
void sortlist()
{
struct node *ptr=head;
while(ptr!=NULL) {
struct node *next;
if (ptr == NULL)
return;
next = ptr->next;
while(next!=NULL) {
if(ptr->data > next->data) {
int a=ptr->data;
ptr->data=next->data;
next->data=a;
}
next = next->next;
}
ptr=ptr->next;
}
}
I made changes in the code and add the comments for the changes
void sortlist()
{
// struct node *a; /* this is not required. */
/* NULL checks are required,if head is NULL,head->next will crash.*/
if(head == NULL || head->next == NULL) return;
struct node *temp=head;
struct node *temp1=head->next;
while(temp!=NULL)
{
while(temp1->next!=NULL)
{
if(temp->data > temp1->data)
{
/* assuming you data is integer*/
int d=temp->data;
temp->data=temp1->data;
temp1->data=d;
}
//else /* else is not required, better to remove it.*/
//{
temp1=temp1->next;
//}
}
temp=temp->next;
}
}
//at last i found answer to my own problem and this is the solution,thanks for your help buddies
void sortlist()
{
struct node *temp=head;
int s;
struct node *temp1=temp->next;
while(temp!=NULL)
{
temp1=temp->next;
while(temp1!=NULL)
{
if(temp->data > temp1->data)
{
s=temp->data;
temp->data=temp1->data;
temp1->data=s;
}
temp1=temp1->next;
}
temp=temp->next;
}
}
I've implemented the following code for queues as a linked list. Now I'm trying to get an hashtable as an array of queues as a linked list. It works fine until I do insertion after deletion.
What is being done is a queue is implemented as linked list. So when I want to remove, I delete the head element and for insert I use tail.
To do an hashtable I maintain another linked list of keys in the order in which they were inserted. Deletion starts with first removing this key and going to that individual linked list and removing the head and updating the head.
#include<stdio.h>
#include<stdlib.h>
struct Node{
int value;
struct Node *next;
struct Node* head;
struct Node* tail;
};
struct Node* lruhashtable[10];
struct Node* trackHead;
struct Node* trackTail;
void insert(int page)
{
if(trackHead==NULL)
{
trackHead=malloc(sizeof(struct Node));
trackHead->value=(page-1)%10;
trackHead->next=NULL;
trackTail=trackHead;
}
else
{
struct Node* temp=malloc(sizeof(struct Node));
temp->value=(page-1)%10;
temp->next=NULL;
trackTail->next=temp;
trackTail=temp;
}
}
void hashEntry(int page)
{
struct Node** iter;
iter=&lruhashtable[(page-1)%10];
for(;*iter;iter=&(*iter)->next);
*iter = malloc(sizeof **iter );
(*iter)->value = page;
(*iter)->next = NULL;
if((*iter)->head==NULL)
{
(*iter)->head=*iter;
(*iter)->tail= (*iter)->head;
}
else
{
(*iter)->tail->next=*iter;
(*iter)->tail=*iter;
}
insert(page);
}
void deleteInHashEntry()
{
int pageToDelete=delete();
struct Node** iter;
iter=&lruhashtable[pageToDelete];
if((*iter)->head!=NULL)
{
struct Node* curr=(*iter)->head;
(*iter)=curr->next;
if((*iter)!=NULL)
(*iter)->head=*iter;
free(curr);
}
else
{
(*iter)->tail=NULL;
}
}
void print()
{
int i;
struct Node **iter;
for(i=0;i<10;i++)
{
iter=&lruhashtable[i];
for(;*iter;iter=&(*iter)->next)
{
printf("%d%s%d\n",(*iter)->value,"--",i);
}
}
}
int delete()
{
int page=-1;
if(trackHead!=NULL)
{
struct Node*current=trackHead;
page=current->value;
trackHead=current->next;
free(current);
}
else
{
trackTail=NULL;
}
return page;
}
void printTrack()
{
struct Node* temp=trackHead;
while(temp!=NULL)
{
printf("%d",temp->value);
printf("\n");
temp=temp->next;
}
}
int main()
{
hashEntry(1);
hashEntry(11);
hashEntry(2);
hashEntry(3);
hashEntry(22);
hashEntry(4);
hashEntry(33);
print();
printTrack();
deleteInHashEntry();
print();
printTrack();
deleteInHashEntry();
print();
printTrack();
deleteInHashEntry();
print();
printTrack();
hashEntry(1);
hashEntry(11);
hashEntry(22);
deleteInHashEntry();
deleteInHashEntry();
deleteInHashEntry();
deleteInHashEntry();
deleteInHashEntry();
deleteInHashEntry();
deleteInHashEntry();
return 0;
}
GDB to the rescue, thought I think I should have caught it much before,in the function hashEntry if((*iter)->head==NULL) this statement is wrong as everytime this will execute after malloc. Added a STATUS variable to do this check before malloc statement and change if condition to if status. Hopefully this is the only bug.