Qsort - переменный порядок сортировки - PullRequest
3 голосов
/ 27 декабря 2010

У меня есть программа, которая использует (и должна продолжать использовать) старую функцию сортировки, реализующую qsort.Я также должен предоставить функции сортировки надлежащие данные для сортировки данных как по возрастанию (если строка содержит четные числа), так и по убыванию (если строка содержит нечетные числа).

Данные должны быть изменены для достижения этой цели, функция сортировкине может быть изменено.

Код написан на C , но у меня нет соответствующего фрагмента кода для этой конкретной проблемы.

Реальный вопрос:

Как мне преобразовать данные так, чтобы выходные данные соответствовали желаемым выходным данным ниже?

У меня есть следующие данные (или аналогичные)

String 1
String 2
String 3
String 4
String 5
String 6

РЕДАКТИРОВАТЬ: данные представляют собой число строк типа char **, число в каждой строке представляет собой целое число.

Требуемое значение:

String 5
String 3
String 1
String 2
String 4
String 6

Сортировка обычно выполняется в порядке убывания, соответствующем вводу 1: 1.Мне удалось произвести преобразование, отображающее следующий вывод, добавив 1 или 0 к числам, следующим за строкой.

Таким образом, внутренние сортируемые данные выглядят так:

String 01
String 12
String 03
String 14
String 05
String 16

Создает следующий вывод (преобразование используется только при сортировке и является временным).

String 1
String 3
String 5
String 2
String 4
String 6

Ответы [ 4 ]

3 голосов
/ 27 декабря 2010

У вас должна быть структура, которая содержит данные и значение:

Struct DataValue
{
   string data;
   int value;
} 

подобно {"01", 1} Затем сортируйте по значению и выводите данные, сортировка не сложная, если вы хотите выполнить обычную сортировку: первая сортировкапо значению, чтобы сделать список, как то, что вы показали.(для значений) теперь создайте пустой массив значений данных (с базовым размером массива), начните с последнего элемента и заполните его следующим образом:

    int j = 0;
    for (int i = a.Count - 1; i >= 0; i -= 2) // fill bottom of list
    {
        b[a.Count - 1 - j] = a[i];
        j++;
    }

    j = 0;
    for (int i = a.Count - 2; i >= 0; i -= 2)  // fill root of list
    {
        b[j] = a[i];
        j++;
    }

При последнем выводе значений.

Я написал это в c #, это не очень отличается в c.вы получите:

  List<int> a = new List<int>{1,2,3,4,5,6,7};

   b==> 6,4,2,1,3,5,7

and for:
  List<int> a = new List<int>{1,2,3,4,5,6};
  b==> 5,3,1,2,4,6
2 голосов
/ 27 декабря 2010

Это можно сделать на месте (то есть с одним массивом значений и не требуя отдельного списка), используя пользовательскую процедуру сравнения.Функция ниже предполагает, что вы сортируете строки напрямую.Вероятно, лучше предварительно обработать данные, чтобы вы извлекли число из строки и поместили оба в структуру.Но это даст вам идею.

Вы бы передали указатель на эту функцию сравнения на qsort.

int Comparer(void * v1, void * v2)
{
    char *s1 = (char *)v1;
    char *s2 = (char *)v2;

    // Here, extract the numbers from the ends of the strings.
    int n1 = // extract number
    int n2 = // extract number

    // First comparison sorts odd numbers above even numbers
    if ((n1 % 2) == 1)
    {
        // first number is odd
        if ((n2 % 2) == 1)
        {
            // second number is odd, so sort the numbers ascending
            return (n1 - n2);
        }
        else
        {
            // second number is even, which is "greater than" any odd number
            return -1;
        }
    }
    else
    {
        // first number is even
        if ((n2 % 2) == 0)
        {
            // second number is even, so sort the numbers descending
            return (n2 - n1);
        }
        else
        {
            // second number is odd, which is "less than" any even number
            return 1;
        }
    }
}
1 голос
/ 27 декабря 2010
  1. Предварительная обработка: поместите четные строки в список (назовем этот список _evens_) и поместите нечетные строки в отдельный список (называемый _odds _)
  2. Сортировка обоих списков
  3. Создать список адресатов
  4. Рассматривайте список _odds_ как стек: вставьте верхнюю часть _odds_ и поместите извлеченный элемент в * front * списка назначения.
  5. Рассматривайте _evens_ как очередь: выдвиньте верхнюю часть _evens_ и поместите вытолкнутый элемент в * end * списка адресатов.
1 голос
/ 27 декабря 2010

Prepend 9-i, если i нечетно. В противном случае добавьте 9.

...