2016-09-04 4 views
1

Я пытаюсь сделать эту программу сортировкой 2d массива строк по индексу столбца.Строка массива Сортировка C

Я инициализируется этот 2d массив так:

char *str[ROWS][COLS] = {{"Russia", "Boxing", "Mens", "Gold"}, 
         {"America", "Cycling", "Mens", "Gold"}, 
         {"New Zealand", "Swimming", "Womens", "Silver"}, 
         {"India", "Badminton", "Mens", "Bronze"}}; 

И если бы я хотел, чтобы отсортировать этот массив по первой колонке, названия стран, то это будет выглядеть примерно так:

char *str[ROWS][COLS] = {{"America", "Cycling", "Mens", "Gold"}, 
         {"India", "Badminton", "Mens", "Bronze"}}; 
         {"New Zealand", "Swimming", "Womens", "Silver"}, 
         {"Russia", "Boxing", "Mens", "Gold"}}; 

Это то, что я сделал до сих пор, и это почти правильно, за исключением метода сортировки. У меня проблемы с этим.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define ROWS 4 
#define COLS 4 

void print_array(char *str[][COLS]); 
void sort_array(char *str[][COLS], int nrows, int col); 

int 
main(void) { 
    char *str[ROWS][COLS] = {{"Russia", "Boxing", "Mens", "Gold"}, 
          {"America", "Cycling", "Mens", "Gold"}, 
          {"New Zealand", "Swimming", "Womens", "Silver"}, 
          {"India", "Badminton", "Mens", "Bronze"}}; 
    int col; 

    /* array before sorting */ 
    printf("Before: \n"); 
    print_array(str); 

    /*choosing column index to sort by*/ 
    printf("\nChoose which column index you wish to sort by: "); 
    if (scanf("%d", &col) != 1) { 
     printf("Invalid input\n"); 
     exit(EXIT_FAILURE); 
    } 

    sort_array(str, ROWS, col); 

    /* array after sorting */ 
    printf("\nAfter: \n"); 
    print_array(str); 

return 0; 
} 

void 
print_array(char *str[][COLS]) { 
    int i, j; 

    for (i = 0; i < ROWS; i++) { 
     for (j = 0; j < COLS; j++) { 
      printf("%s ", str[i][j]); 
     } 
     printf("\n"); 
    } 
} 

/*function used for sorting the array */ 
void 
sort_array(char *str[][COLS], int nrows, int col) { 
    int i, j; 
    char *temp; 

    for (i = 0; i < nrows; i++) { 
     for (j = i; j < nrows; j++) { 
      if(strcmp(str[i][col], str[j][col]) > 0) { 
       temp = str[i][col]; 
       str[i][col] = str[j][col]; 
       str[j][col] = temp; 
      } 
     } 
    } 
} 

Проблема у меня в том, что мой алгоритм сортировки не поменять местами строки, но только строки в этом столбце. Я также пытался использовать алгоритм insertion sort, но я не был уверен, как реализовать это с помощью 2d массива строк.

Любая помощь будет оценена :)

+3

«не меняя строки, но только строки в этой колонке» - так ?? напишите петлю. –

+0

Да, так будет 'insertion sort' быть хорошим выбором для этого? – RoadRunner

+2

Использовать 'qsort' (стандартная библиотека) – BLUEPIXY

ответ

1

Итерация по рядам. Сравните столбец для двух строк, i и i + 1. По мере необходимости итерации по столбцам и замены двух строк. Повторяйте, пока не будет свопов.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define ROWS 4 
#define COLS 4 

void print_array(char *str[][COLS]); 
void sort_array(char *str[][COLS], int nrows, int ncols, int col); 

int 
main(void) { 
    char *str[ROWS][COLS] = {{"Russia", "Boxing", "Mens", "Gold"}, 
          {"America", "Cycling", "Mens", "Gold"}, 
          {"New Zealand", "Swimming", "Womens", "Silver"}, 
          {"India", "Badminton", "Mens", "Bronze"}}; 
    int col; 
    int result = 0; 
    int clean = 0; 
    /* array before sorting */ 
    printf("Before: \n"); 
    print_array(str); 

    /*choosing column index to sort by*/ 
    do { 
     printf("\nChoose which column index you wish to sort by 0 to %d: ", COLS - 1); 
     if ((result = scanf("%d", &col)) != 1) { 
      printf("Invalid input\n"); 
      if (result == EOF) { 
       fprintf (stderr, "problem getting input\n"); 
       exit(EXIT_FAILURE); 
      } 
      //clean input stream 
      while ((clean = getchar()) != '\n' && clean != EOF) {} 
     } 
    } while (result != 1 || col < 0 || col >= COLS); 

    sort_array(str, ROWS, COLS, col); 

    /* array after sorting */ 
    printf("\nAfter: \n"); 
    print_array(str); 
    return 0; 
} 

void 
print_array(char *str[][COLS]) { 
    int i, j; 

    for (i = 0; i < ROWS; i++) { 
     for (j = 0; j < COLS; j++) { 
      printf("%s ", str[i][j]); 
     } 
     printf("\n"); 
    } 
} 

/*function used for sorting the array */ 
void 
sort_array(char *str[][COLS], int nrows, int ncols, int col) { 
    int i = 0, j = 0, swap = 0; 
    char *temp; 

    do { 
     swap = 0; 
     for (i = 0; i < nrows - 1; i++) {//iterate through rows 
      if (strcmp(str[i][col], str[i + 1][col]) > 0) {//compare col for row i and i+1 
       for (j = 0; j < ncols; j++) {//iterate through cols and swap rows 
        temp = str[i][j]; 
        str[i][j] = str[i + 1][j]; 
        str[i + 1][j] = temp; 
       } 
       swap = 1; 
      } 
     } 
    } while (swap);//loop until no swaps 
} 
+0

Большое спасибо @ user3121023, это напоминает мне алгоритм сортировки пузырьков, который является приятным и простым в использовании. Есть ли способ сделать сортировку столбцов на основе аргументов командной строки? Например, если я иду './myprogram 2 0 RoadRunner

+1

Нет ничего приятного в сортировке пузыря (за исключением, может быть, если вы считаете «приятным и медленным», хорошо, приятно). Кроме того, выбор сортировки является более эффективным и, на мой взгляд, концептуально более простым (т. Е. «Найти наименьший элемент из несортированных и добавить его к отсортированным, повторить, пока у вас не будет никаких несортированных элементов»). – Arkku

+0

Спасибо @ user3121023, Теперь я просто думаю о способе разрешить любые аргументы командной строки, например './myprogram 2 0 3 RoadRunner

1

С C11 вы можете сделать это следующим образом:

int compare_col(const void *a, const void *b, void *ctx) { 
    int col = *(int*)ctx; 
    return strcmp(((char**)a)[col], ((char**)b)[col]); 
} 

/*function used for sorting the array */ 
void sort_array(char *str[][COLS], int nrows, int col) { 
    qsort_s(str, nrows, sizeof(char*)*COLS, compare_col, &col); 
} 
+0

Я считаю, что 'qsort_s' находится только в приложении K, поэтому он не обязательно поддерживается даже всеми совместимыми с C11 реализациями ... Какой из них жалко, поскольку третий аргумент компаратора является полезным дополнением, как вы показали. – Arkku

+1

Между тем, я бы предложил использовать 'sizeof (* str)' вместо 'sizeof (char *) * COLS', чтобы избежать избыточности и возможных ошибок, если тип изменяется. – Arkku

2

Использование qsort, вам нужна функция компаратора принимает в качестве аргументов указателей на двух элементов, подлежащих сортировке. В этом случае элемент, который нужно отсортировать, представляет собой целую строку в 2D-массиве. Если вам нужно изменить столбец сортировки, вам также необходимо заставить переменную удерживать ее глобально (или вам нужно создать разные компараторы для каждого столбца).

static int sort_column = 0; 

static int compare_rows(const void *a, const void *b) { 
    return strcmp(((const char **)a)[sort_column], ((const char **)b)[sort_column]); 
} 

Тогда вы просто вызываете qsort с вашего массива и функции сравнения в качестве аргументов:

qsort(str, ROWS, sizeof(*str), (compare_rows)); 
Смежные вопросы