c bubblesort a link list - c

trying to get a function to run that will bubble sort a link list from smallest to largest number. I don't want the data to be moved around in the link list instead have the pointers be pointing elsewhere in case each link needs to hold a lot of data.
In each link I have a INT arrivalTime field that will house a integer value. THis number determines where the link should be in the list.
My program seems to hang at the moment, I'd appreciate if anyone could fix it up, Thanks
bubble sort function
void bubbleSort(struct order *start)
{
int swapped, i;
processData *current = start;
processData *temp;
struct order *lptr = NULL;
/* Checking for empty list */
if (current == NULL)
printf("null \n");
do
{
swapped = 0;
current = start;
while (current->next != lptr)
{
if (current->arrivalTime > current->next->arrivalTime)
{
temp = current;
current = current->next;
current->next = temp;
swapped = 1;
}
current = current->next;
}
lptr = current;
}
while (swapped);
}
structure of link list
struct order
{
int name;
int arrivalTime;
int quanta;
struct order * next;
};
typedef struct order processData;

Swapping two adjacent items in a singly-linked-list requires that you change three next pointers.
If the order is A --> B --> C --> D and you swap B with C to get A --> C --> B --> D then
A->next needs to point to C instead of B
B->next needs to point to D instead of C
C->next needs to point to B instead of D

This is a very slow thing you're trying to do - see this paper on comparing ways to sort a linked list.
Currently, your algorithm will never terminate because in your while loop, you set lptr = current, but then test whether current->next == lptr. This will never return true unless one of your list members points to itself.
If you do have a definite use case to bubble sort the linked list, consider this: The purpose of a linked list is that you access it by working sequentially from the list head to the item you want. If your initial list head is not the smallest or the largest and you're only changing pointers, you need to keep track of where the head of the list is.
I did think of a way to do it loosely based on yours, see below. Sorry it's a bit messy - I'm not a C expert (hope the memory allocation is OK...) and I'm sure there are optimisations. In particular I'm sure there are better ways to pass the headOfList pointer back to the main algorithm. I've tested it for a number of 100 member lists of structs with some negative numbers. I've left the code to generate them with random arrival times in main() so you can just paste this in where your old code was and run it.
processData *bubbleSort(processData *start)
{
int swapped;
processData *current = start;
processData *lheadptr = start;
processData *previous = NULL;
processData *oldPrevButBigger;
processData *oldAfterThisPair;
/* Checking for empty list */
if (current == NULL)
{
printf("null \n");
return NULL;
}
do
{
swapped = 0;
current = lheadptr;
previous = NULL;
while (current->next) //Stop when current->next is null (i.e. end of list)
{
if (current->arrivalTime > current->next->arrivalTime)
{
oldPrevButBigger = current;
oldAfterThisPair = current->next->next;
current = current->next;
current->next = oldPrevButBigger;
current->next->next = oldAfterThisPair;
if (!previous)
{
//If no previous, this was the head of the list, so need to update
lheadptr = current;
}
else
{
// If there is a "previous", then we're not at head of list, so need
// to update that pointer too
previous->next = current;
}
swapped = 1;
}
previous = current;
current = current->next;
}
}
while (swapped);
return lheadptr;
}
int main()
{
srand(time(NULL));
int NUM = 100;
processData* pointToLast = NULL;
int i;
processData orders[NUM];
//Generate a list with random arrival times (last member of the list generated first
for (i = 0; i < NUM; i++ )
{
orders[i].name = i;
orders[i].arrivalTime = rand()-1000000000;
orders[i].quanta = 500;
orders[i].next = pointToLast;
pointToLast = &orders[i];
}
printf("List before\n");
printf("===========\n");
for (i=0; i < NUM; i++)
{
printf("%i;%i;%i\n", pointToLast->name, pointToLast->arrivalTime, pointToLast->quanta);
pointToLast = pointToLast->next;
}
processData* newListHead = bubbleSort(&orders[NUM-1]);
printf("List after\n");
printf("===========\n");
for (i=0; i < NUM; i++)
{
printf("%i;%i;%i\n", newListHead->name, newListHead->arrivalTime, newListHead->quanta);
newListHead = newListHead->next;
}
return 0;
}

Related

Why is my linked list while loop not working? (C)

I am unsure why the code below does not execute up to the while loop. It only gives this output:enter image description here
The desired output of this program is that the largest node of the linked list is taken, multiplied by 0.8, and then printed as an output.
Code:
struct Process{
int burst_time;
struct Process* next;
};
int main()
{
int i;
struct Process* head = NULL, *temp = NULL;
struct Process* current = head; // Reset the pointer
int proc_count, time_quantum, total_time;
// BTmax
int max = 0;
printf("How many processes?: ");
scanf("%d",&proc_count);
for(i = 0; i < proc_count; i++)
{
temp = malloc(sizeof(struct Process));
printf("\nEnter burst time of process %d: ", i + 1);
scanf("%d", &temp -> burst_time);
temp->next=NULL;
if(head==NULL)
{
head=temp;
current=head;
}
else
{
current->next=temp;
current=temp;
}
}
current = head;
// BTmax * 0.8
while(current != NULL)
{
if (head -> burst_time > max)
{
max = head->burst_time;
}
head = head->next;
}
time_quantum = max * 0.8;
printf("\nTime Quantum is: %d", time_quantum);
Also, inside while loop you are iterating head variable but in condition you are checking current != NULL
From the way you wrote your while loop (iterating via head=head->next) you are apparently trying to do these two things at the same time:
Scan the list for its largest element
Remove/deallocate each element after it has been considered
Although head=head->next does remove each element from the list, it neglects to deallocate (causing memory to leak).
This loop correctly does both the scanning and the removal/deallocation:
while (head != NULL)
{
if (head->burst_time > max)
{
max = head->burst_time;
}
temp = head;
head = head->next;
free(temp);
}
(Notice that the while condition should be testing head, not testing current. Thus, there is no need to initialize current=head prior to the loop.)
You'll want to change the final while loop. You're checking to make sure current isnt NULL but you're iterating with head. If you still need access to the data, changing the final while loop to this should work :
while(current != NULL) {
if (current->burst_time > max) max = current->burst_time;
current = current->next;
}
Finally, maybe you already have in your actual program, but you need to free() any memory allocated with malloc()
So if you're done with the list at that point you can change the final while loop to :
while(head != NULL) {
if (head->burst_time > max) max = head->burst_time;
temp = head;
head = head->next;
free(temp);
}

Updating linked-list by pointer inside a function

I'm missing with linked-list and trying to make a function which gonna take of all the odd numbers out of the link and make a new linked-list with them.
The point is that I dont understand how to update the original list by pointer to the function, actually what I made so far is making a new list with the odd numbers but I dont really understand how to "delete" them from the original list and link all the rest togther, then send it back to the main.
Node *build_odd_list(Node *oldlst, Node *newlst) {
Node *temp, *curheadNew;
temp = (Node*)malloc(sizeof(Node));
if (oldlst->value % 2 != 0) {
temp->next = NULL;
temp->value = oldlst->value;
newlst = temp;
curheadNew = newlst;
oldlst = oldlst->next;
printf("Passed %d\n", curheadNew->value);
}
else {
oldlst = oldlst->next;
}
while (oldlst) {
if (oldlst->value % 2 != 0) {
temp = (Node*)malloc(sizeof(Node));
temp->value = oldlst->value;
temp->next = NULL;
curheadNew->next = temp;
curheadNew = curheadNew->next;
oldlst = oldlst->next;
printf("Passed %d\n", curheadNew->value);
}
else {
oldlst = oldlst->next;
}
}
return newlst;
}
Thanks a lot!
Since you need to return a new list containing the odd numbers, and modify the original list due to removal of the odd numbers, you need to pass two values back to the caller: a pointer to the first element of the updated original list, and a pointer to the first element of the "odd numbers" list.
Since you need to pass the original list to the function anyway, the simplest option for the function is to:
pass a pointer to a pointer to the first element of the original list;
modify the original list via the pointer;
return a pointer to the first element of the "odd numbers" list extracted from the original list.
There is no need to allocate any new elements for the "odd numbers" list as the odd number elements can be moved from one list to the other.
It is worth learning the "pointer to a pointer" trick as it is a common way of manipulating list pointers.
Here is an example program to illustrate the above method. Pay particular attention to the extract_odd_list() function and the call to that function from main().
#include <stdio.h>
#include <stdlib.h>
typedef struct _Node {
int value;
struct _Node *next;
} Node;
/* Move odd numbers in *list to returned list. */
Node *extract_odd_list(Node **list) {
Node *oddstart = NULL; /* start of returned list */
Node **oddend = &oddstart; /* pointer to final link of returned list */
while (*list) {
if ((*list)->value % 2 != 0) {
/* Current element of original *list is odd. */
/* Move original *list element to end of returned list. */
*oddend = *list;
/* Bypass moved element in original list. */
*list = (*list)->next;
/* Update pointer to final link of returned list. */
oddend = &(*oddend)->next;
}
else {
/* Current element of original *list is even. */
/* Skip to next element of original *list. */
list = &(*list)->next;
}
}
/* Terminate the returned list. */
*oddend = NULL;
/* And return it. */
return oddstart;
}
void *printlist(Node *list) {
while (list) {
printf(" %d", list->value);
list = list->next;
}
}
int main(void) {
int i;
Node *list = NULL;
Node *end = NULL;
Node *oddlist;
Node *temp;
/* Construct a list containing odd and even numbers. */
for (i = 1; i <= 10; i++) {
temp = malloc(sizeof(*temp));
temp->value = i;
if (end == NULL) {
list = temp;
}
else {
end->next = temp;
}
end = temp;
}
end->next = NULL;
printf("Original list:");
printlist(list);
printf("\n");
/* Move the "odd number" elements from the original list to a new list. */
oddlist = extract_odd_list(&list);
printf("Updated list:");
printlist(list);
printf("\n");
printf("Odd list:");
printlist(oddlist);
printf("\n");
return 0;
}

C Program - Removing duplicates from LinkedList

I am trying out on removing duplicates from a linkedlist. The user will insert one value and then, the program will check if the user's input and value in the linkedlist are the same. If it's similar, it will remove and leave only one in the linkedlist. For e.g. linkedlist=10 100. user=10. outcome=10 100 and not 10 10 100.
int insertSorted(LinkedList *ll, int item)
{
ListNode *cur = ll->head;
int size = ll->size;
int i;
for (i = 0; i <= size; i++)
{
if ((size - i) == 0 || item < cur->item)
{
insertNode(ll, i, item); // function to insert the value into Linkedlist
return i;
}
cur = cur->next;
}
ListNode *current = ll->head;
while (current->next != NULL)
{
if (current->item == current->next->item)
{
ListNode *nextNext = current->next->next;
free(current->next);
current->next = nextNext;
}
else
{
current = current->next; // only advance if no deletion
}
}
return -1;
}
When you insert the new node (the value 10 in your example), you then return i;, making the rest of the code, which I suppose checks for duplicates not to execute.
If you always return after you insert, you don't reach the code that deletes the duplicate. I think you need to break instead.
Also, where do you modify the size of the linked-list when you delete an element?
Should be reduced by 1 if I understand correctly.
In addition, since you clean duplicates after every insertion, you don't need the conditional advancement in the deleting loop

Returning head of linked list from a function

The function that I have created takes the heads of two linked lists of structs and uses them to update a member of the struct in the first linked list. Once my while loop has finished I wish to return the head of the struct 'a' however currently when I return it it has a value of NULL because of the while loop. How would I return the head of 'a' once it has been updated? I know that I have to use a temporary struct but how would I implement it?
struct artist *update_counts(struct artist *a, struct play *p)
{
struct artist *tmp = a;
int count = 0;
while (a != NULL)
{
while (a->artist_id == p->artist_id)
{
count += p->playcount;
p = p->next;
}
a->playcount = count;
a = a->next;
count = 0;
}
return a;
}
Generally, to visit the linked list, we can use a head pointer to keep its original linked list head like head_p = ...inputed head node..., and then use a visitor pointer to visit linked list like visitor_p = visitor_p->next. Here in your code, tmp is that head pointer.
struct artist *update_counts(struct artist *a, struct play *p)
{
struct artist *tmp_head = a;//tmp is the head of inputed linked list a
int count = 0;
while (a != NULL)
{
while (a->artist_id == p->artist_id)
{
count += p->playcount;
p = p->next;
}
a->playcount = count;
a = a->next;
count = 0;
}
return tmp_head;//just return the head of a
}

Sorting by line

If someone could help me find where i am going wrong, i have been working on this code for a long time but cannot get it right.
It takes a linked list to be sorted by passing *head as head pointer. The output of that function should be the same linked list sorted in ascending order such that the header node will be the smallest value in the
list.
void sortByCount (struct lnode** head) {
struct lnode* temp= (*head);
struct lnode* temp2 = (*head);
int i;
int j;
int counter = 0;
while(temp != NULL)
{
temp = nodeGetNext(temp);
counter++;
}
for( i = 1; i<counter; i++)
{
temp2=(*head);
bool flag = false;
for(j = 1; j<counter-i+1;j++)
{
if(countCmp(temp2,nodeGetNext(temp2))>0)
{
swap(head,temp2,nodeGetNext(temp2));
}
if(countCmp(temp2,nodeGetNext(temp2))== 0 && (wordCmp(temp2,nodeGetNext(temp2))>0))
{
swap(head,temp2,nodeGetNext(temp2));
flag = true;
//continue;
}
}
temp2 = nodeGetNext(temp2);
}
}
The problem is in this part of your loop:
if(countCmp(temp2,nodeGetNext(temp2))>0)
{
swap(head,temp2,nodeGetNext(temp2));
}
if(countCmp(temp2,nodeGetNext(temp2))== 0
&& (wordCmp(temp2,nodeGetNext(temp2))>0))
{
swap(head,temp2,nodeGetNext(temp2));
flag = true;
//continue;
}
If you decide to bubble up, and swap, then the second if check might choose to bubble up again (since the swap has happened, the next of temp2 will have changed). This is probably not what you intended. Instead, you probably meant to do the second if check only if the first if check failed. This is normally accomplished by adding an else to the if statement.

Resources