I am trying to implement binary radix sort in C which sorts a linked list of integers stably. Although my algorithm has a time complexity of O(log2(k).n)
(where k is the biggest integer in the linked list), other standard implementations of algorithms like merge sort/quick sort seem to have better execution time even when input size is large (n
>10^6) and k
is small (k
<1000). Am I doing something wrong which is causing these longer execution times? Could you review this code?
Here is the code for my implementation:
#include<stdio.h> #include<math.h> #include<stdlib.h> #include<time.h> struct ListNode { int val; struct ListNode *next; }; void print_list(struct ListNode *node) // printing integer values of linked list { while(node!=NULL) { printf("%d, ", node->val); node=node->next; } } int getMax(struct ListNode *node) // finding biggest integer in linked list { int max=node->val; while(node!=NULL) { if(node->val > max) { max=node->val; } node=node->next; } return max; } void addMin(struct ListNode *node, int min) // Adding smallest integer in linked list so that no integer in linked list is negative { while(node!=NULL) { node->val+=min; node=node->next; } } void subMin(struct ListNode *node, int min) // returning linked list to original values after sorting { while(node!=NULL) { node->val-=min; node=node->next; } } int getMin(struct ListNode *node) // finding smallest integer in linked list { int min=node->val; while(node!=NULL) { if(node->val < min) { min=node->val; } node=node->next; } return min; } void binarySort(struct ListNode **head, int bit) // sorts linked list based on a particular bit { struct ListNode *temp = *head; struct ListNode *insertNode = *head; struct ListNode *prevNode = NULL; int flag=0; int flag2=0; if((((*head)->val) & (1 << (bit - 1)))) { flag=1; } while(temp!=NULL) { if(flag==0 && !((temp->val) & (1 << (bit - 1)))) { if((temp->next)!=NULL && (((temp->next)->val) & (1 << (bit - 1)))) { insertNode=temp; flag=1; flag2=1; } } else if(flag2==0 && !((temp->val) & (1 << (bit - 1)))) { prevNode->next=temp->next; temp->next=*head; insertNode=temp; *head=temp; temp=prevNode; flag=1; flag2=1; } else if(!((temp->val) & (1 << (bit - 1)))) { prevNode->next=temp->next; temp->next=insertNode->next; insertNode->next=temp; insertNode=temp; temp=prevNode; } prevNode=temp; temp=temp->next; } } struct ListNode* sortList(struct ListNode* head) // binary radix sort { if(head==NULL) { return NULL; } int min=getMin(head); if(min<0) { subMin(head, min); } int biggest_int_len = log2(getMax(head))+1; int i; for(i=1 ; i<=biggest_int_len ; i++) { binarySort(&head, i); } if(min<0) { addMin(head, min); } return head; } int main() // code to test the function { srand(time(0)); int num; struct ListNode *head = (struct ListNode*) malloc(sizeof(struct ListNode)); head->next=NULL; printf("Enter input size: "); scanf("%d", &num); head->val=rand()%1000; struct ListNode *prevNode = head; while(num-1>0) { struct ListNode *temp = (struct ListNode*) malloc(sizeof(struct ListNode)); temp->val=rand()%1000; temp->next=NULL; prevNode->next=temp; prevNode=temp; num--; } printf("\n\n"); print_list(head); clock_t t; t = clock(); struct ListNode *sortedList=sortList(head); t = clock() - t; double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds printf("\n\n"); print_list(sortedList); printf("\n\nfun() took %f seconds to execute \n", time_taken); }
Also is there a good way to test how much memory the sort uses?