Search code examples
clinked-listbucket-sort

Sorting an array using Bucket Sort in C. Question about how the code to insert new elements in the linked list works


I am coding a program in C that sorts an array by using bucketSort. My code works. I can print the data structure and every element of the original array is in the right "bucket". I understand what a linked list is and how it works. But I couldn't understand very well how this part of the code works.

/*If the bucket has already another element, */
            else

            {
             
             
                p -> next = buckets[index];

                buckets[index] = p;
            }

And it is not very clear to me how the last node of the linked list is going to points to NULL to indicate the end of the linked list?

bucketSort Function:

void bucketSort(float arr[], int arr_length)
    {
        /*Sort an array within elements from [0, 1). We are going to use insertion sort
        as a subroutine.
        Assume arr contains elements from [0, 1)*/
        
        //Initialize empty buckets. 
         for (int i = 0; i < NBUCKETS; i++)
         {
            buckets[i] = NULL;
         }
        
        //Fill the buckets with respective elements
        
        for (int i = 0; i < arr_length; i++)
        {
            node *p = malloc(sizeof(node));
            //Check if malloc has succeeded in getting memory
            if (p == NULL)
             {
                  printf("Something went wrong!\n");
                  exit(1);
             }
            //Get index of element arr[i]
            int index = getBucketIndex(arr[i]);
            //Assign the element arr[i] to the data structure
            p -> data = arr[i];
            //If data is the first element of bucket do the following...
            if (buckets[index] == NULL)
            {
                buckets[index] = p;
            }
            /*If the bucket has already another element, */
            else
            
            {
                p -> next = buckets[index];
             
                buckets[index] = p;
            }
            
        }
   

Solution

  • When the bucket array is initially created, all buckets are usually marked empty, as follows:

    buckets[0] -> NULL
    buckets[1] -> NULL
    

    Then let's say you want to insert a new element 42 in the first bucket. You have it pointed to via p and pointing to some random location as its next element:

    p -> (42) -> ?
    

    This is what happens when you run your code to insert the first item (which doesn't actually need a special case provided you already have the bucket pointing to NULL:

                                     // buckets[0] -> NULL
                                     // p -> (42) -> ?
    p -> next = buckets[index];      // p -> (42, NULL)
    buckets[index] = p;              // buckets[0] -> (42, NULL) -> NULL
    

    And this is what happens when you run your code to insert the second item 99:

                                     // buckets[0] -> (42) -> NULL
                                     // p -> (99) -> ?
    p -> next = buckets[index];      // p -> (99) -> (42) -> NULL
    buckets[index] = p;              // buckets[0] -> (99) -> (42) -> NULL
    

    In other words, it just inserts the new item at the start of the list (empty or otherwise).


    You are absolutely correct that the code you posted is not safe. In the event that the bucket is currently empty, there is no statement that sets the next pointer of the new item to NULL, almost certainly leading to corrupted structures.

    The good news is, as mentioned above, that you can simply throw away the if block and do the else block unconditionally, assuming the buckets are correctly initialised to NULL (and this seems to be likely based on the fact the original code if explicitly checking that to decide if a bucket is empty).