user200081
user200081

Reputation: 563

Sorting an array by increasing frequency of element

I would like to sort an array by increasing order of frequency. For example, if I had an array

int arr[] = { 3, 3, 10, 2, 5, 10, 10, 2, 2, 2 };

or another array would have the following sequence in it:

int arr[] = {5, 3, 3, 10, 10, 10, 2, 2, 2, 2};

However, I cannot use hashing or maps – I can only use arrays. What I have thought of is sorting the array using a quick sort algorithm, scanning the sorted array and performing the count in a 2d array so that for each element, there is a count associated with it, and then sorting by count. If two counts are same then I would merely print out the one with the lower value first. I'm having trouble implementing the last two steps. I'm not sure how to "map" a count to an index in the 2d array, nor am I sure on how to sort the 2d array by a count. Could anyone help me out? Thanks!

Upvotes: 4

Views: 3163

Answers (2)

Mikhail
Mikhail

Reputation: 21749

That's how I'd code it without STL (requires additional O(n) memory):

// Represents a bunch of equal numbers in an array
struct Bunch
{
  int x;  // value of numbers
  int n;  // count of numbers
};

int cmp_int(const void *x, const void *y)
{
  return *static_cast<const int*>(x) - *static_cast<const int*>(y);
}

int cmp_bunch(const void *x, const void *y)
{
  const Bunch* bx = static_cast<const Bunch*>(x);
  const Bunch* by = static_cast<const Bunch*>(y);
  return (bx->n != by->n) ? bx->n - by->n : bx->x - by->x;
}

void sort_by_freq(int arr[], int arr_size)
{
  // Buffer array to store counted bunches of numbers
  Bunch* buf = new Bunch [arr_size];
  int buf_size = 0;

  // Sort input array
  qsort(arr, arr_size, sizeof(int), cmp_int);

  // Compute bunches
  Bunch bunch;
  bunch.x = arr[0];
  bunch.n = 1;
  for (int i = 1; i < arr_size; ++i)
  {
    if (arr[i] > bunch.x)
    {
      buf[buf_size++] = bunch;
      bunch.x = arr[i];
      bunch.n = 1;
    }
    else
    {
      ++bunch.n;
    }
  }
  buf[buf_size++] = bunch;  // Don't forget the last one!

  // Sort bunches
  qsort(buf, buf_size, sizeof(Bunch), cmp_bunch);

  // Populate bunches to the input array
  int i = 0;
  for (int k = 0; k < buf_size; ++k)
    for (int j = 0; j < buf[k].n; ++j) arr[i++] = buf[k].x;

  // Don't forget to deallocate buffer, since we cannot rely on std::vector...
  delete [] buf;
}

Upvotes: 2

Karthik T
Karthik T

Reputation: 31952

Scan your array (sort first to optimize, but not needed), and generate an array of the struct below. Now sort the array of these structs, then regenerate your original array.

struct ElemCount {
    int Elem;
    int count;
    bool operator<(const ElemCount& other) {
        if (count!=other.count)
            return count<other.count;

        return Elem<other.Elem;
    }
};

Upvotes: 4

Related Questions