Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing bucket sort in c++

A book I have says this:

a) Place each value of the one-dimensional array into a row of the bucket array based on the value's ones digit. For example, 97 is placed in row 7, 3 is placed in row 3, and 100 is placed in row 0. This is called a "distribution pass."

b) Loop through the bucket array row by row, and copy the values back to the original array. This is called a "gathering pass." The new order of the preceding values in the one-dimensional array is 100, 3, and 97.

c) Repeat this process for each subsequent digit position.

I am having a lot of trouble trying to understand and implement this. So far I have:

void b_sort(int sarray[], int array_size) {
    const int max = array_size;
    for(int i = 0; i < max; ++i)
        int array[i] = sarray[i];

    int bucket[10][max - 1];
}

I'm thinking that in order to sort them by ones, tens, hundreds, etc, I can use this:

for(int i = 0; i < max; ++i)
    insert = (array[i] / x) % 10;
    bucket[insert];

where x = 1, 10, 100, 1000, etc. I am totally lost on how to write this now.

like image 220
Jonathan Dewein Avatar asked Feb 16 '12 18:02

Jonathan Dewein


People also ask

What is bucket sort with example?

Bucket Sort is a sorting algorithm that divides the unsorted array elements into several groups called buckets. Each bucket is then sorted by using any of the suitable sorting algorithms or recursively applying the same bucket algorithm. Finally, the sorted buckets are combined to form a final sorted array.

How do you solve a bucket sort?

Following is bucket algorithm. bucketSort(arr[], n) 1) Create n empty buckets (Or lists). 2) Do following for every array element arr[i]. .......a) Insert arr[i] into bucket[n*array[i]] 3) Sort individual buckets using insertion sort. 4) Concatenate all sorted buckets.


3 Answers

Here's a bucket sort based on the info in the OP question.

void b_sort(int sarray[], int array_size) {
    const int max = array_size;
    // use bucket[x][max] to hold the current count
    int bucket[10][max+1];
    // init bucket counters
    for(var x=0;x<10;x++) bucket[x][max] = 0;
    // main loop for each digit position
    for(int digit = 1; digit <= 1000000000; digit *= 10) {
        // array to bucket
        for(int i = 0; i < max; i++) {
            // get the digit 0-9
            int dig = (sarray[i] / digit) % 10;
            // add to bucket and increment count
            bucket[dig][bucket[dig][max]++] = sarray[i];
        }
        // bucket to array
        int idx = 0;
        for(var x = 0; x < 10; x++) {
            for(var y = 0; y < bucket[x][max]; y++) {
                sarray[idx++] = bucket[x][y];
            }
            // reset the internal bucket counters
            bucket[x][max] = 0;
        }
    }
}

Notes Using a 2d array for the bucket wastes a lot of space... an array of queues/lists usually makes more sense.

I don't normally program in C++ and the above code was written inside the web browser, so syntax errors may exist.

like image 195
Louis Ricci Avatar answered Sep 22 '22 17:09

Louis Ricci


The following code uses hex digits for a bucket sort (for BITS_PER_BUCKET=4). Ofcourse it is meant to be instructive, not productive.

#include <assert.h>
#include <stdio.h>

#define TEST_COUNT 100
#define BITS_PER_BUCKET 4
#define BUCKET_COUNT (1 << BITS_PER_BUCKET)
#define BUCKET_MASK (BUCKET_COUNT-1)
#define PASS_COUNT (8*sizeof(int)/BITS_PER_BUCKET)

int main(int argc, char** argv) {

  printf("Starting up ...");
  assert((PASS_COUNT*BITS_PER_BUCKET) == (8*sizeof(int)));
  printf("... OK\n");

  printf("Creating repeatable very-pseudo random test data ...");
  int data[TEST_COUNT];
  int x=13;
  int i;
  for (i=0;i<TEST_COUNT;i++) {
    x=(x*x+i*i) % (2*x+i);
    data[i]=x;
  }
  printf("... OK\nData is ");
  for (i=0;i<TEST_COUNT;i++) printf("%02x, ",data[i]);
  printf("\n");

  printf("Creating bucket arrays ...");
  int buckets[BUCKET_COUNT][TEST_COUNT];
  int bucketlevel[BUCKET_COUNT];
  for (i=0;i<BUCKET_COUNT;i++) bucketlevel[i]=0;
  printf("... OK\n");

  for (i=0;i<PASS_COUNT;i++) {

    int j,k,l;

    printf("Running distribution pass #%d/%d ...",i,PASS_COUNT);
    l=0;
    for (j=0;j<TEST_COUNT;j++) {
      k=(data[j]>>(BITS_PER_BUCKET*i)) & BUCKET_MASK;
      buckets[k][bucketlevel[k]++]=data[j];
      l|=k;
    }
    printf("... OK\n");

    if (!l) {
      printf("Only zero digits found, sort completed early\n");
      break;
    }

    printf("Running gathering pass #%d/%d ...",i,PASS_COUNT);
    l=0;
    for (j=0;j<BUCKET_COUNT;j++) {
      for (k=0;k<bucketlevel[j];k++) {
        data[l++]=buckets[j][k];
      }
      bucketlevel[j]=0;
    }
    printf("... OK\nData is ");
    for (l=0;l<TEST_COUNT;l++) printf("%02x, ",data[l]);
    printf("\n");

  }
}
like image 27
Eugen Rieck Avatar answered Sep 18 '22 17:09

Eugen Rieck


a rewrite of Louis's code in C++11 with STL queues.

void bucket_sort(vector<int>& arr){
    queue<int> buckets[10];
    for(int digit = 1; digit <= 1e9; digit *= 10){
        for(int elem : arr){
            buckets[(elem/digit)%10].push(elem);
        }
        int idx = 0;
        for(queue<int>& bucket : buckets){
            while(!bucket.empty()){
                arr[idx++] = bucket.front();
                bucket.pop();
            }
        }
    } 
}
like image 30
hesham safi Avatar answered Sep 22 '22 17:09

hesham safi