4

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!

4

2 回答 2

4

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;
    }
};
于 2012-11-15T04:52:45.547 回答
2

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;
}
于 2012-11-15T07:02:59.267 回答