【问题标题】:How to sort a 2D Matrix如何对二维矩阵进行排序
【发布时间】:2013-07-03 06:44:29
【问题描述】:

我在一次采访中被问到这个问题。我得到了一个随机数的二维数组(数字可以重复),我需要对它们进行行和列的排序,即所有的行和列都应该排序。谁能解释一下如何有效地做到这一点(最小时间和空间复杂度)。如果您可以提供 C 或 C++ 代码,那将非常有帮助

【问题讨论】:

  • 请阅读about section,这样的问题不适合SO。您应该在解决问题方面取得了不错的进展,如果您仍然感到困惑,请在这里提问,但请提供SSCCE
  • 请给我们至少一个排序矩阵的例子。
  • 之前:3 6 7 5 3 5 6 2 9 1 2 7 0 9 3 6 之后:0 1 2 2 3 3 3 5 5 6 6 6 7 7 9 9
  • 嗯,谢谢你从我的回答中复制粘贴我自己的例子,我想这意味着我至少理解了这个问题:)。请考虑编辑您的问题,而不仅仅是评论。
  • 抱歉,Maxime,我没有看到您发布的代码。我的错,但是您可以在不使用标准 qsort 函数的情况下发布代码吗?

标签: c sorting matrix multidimensional-array


【解决方案1】:

我的想法是二维数组(在某些情况下)可以被视为一维数组,因为它的内存存储。如果没有,您可以将其复制到一维数组中,编写一个自定义排序函数,该函数使用将索引从一维转换为二维的函数。

这里是使用函数 qsort 的示例:

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

int matrix[4][4];

void print_matrix() {
    int i, j;
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}

int compar(const void *a, const void *b) {
    int ia = *((int*)a);
    int ib = *((int*)b);
    return ia - ib;
}

int main() {
    int i, j;
    // Init of a 2D array with random numbers:
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            matrix[i][j] = random() % 10;
        }
    }

    // Before:
    printf("Before:\n");
    print_matrix();

    // This array can be considered as a big 1D array.
    qsort(matrix, 16, sizeof(int), compar);

    // After:
    printf("After:\n");
    print_matrix();

    return 0;
}

输出:

Before:
3 6 7 5 
3 5 6 2 
9 1 2 7 
0 9 3 6 
After:
0 1 2 2 
3 3 3 5 
5 6 6 6 
7 7 9 9 

编辑: OP 要求我避免使用 qsort...所以这里有一个能够对 2D 数组进行排序的快速排序:

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

void print_matrix(int **matrix, int rows, int cols) {
    int i, j;
    for (i = 0; i < rows; i++) {
        for (j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}

void swap(int *a, int *b) {
    int buf = *a;
    *a = *b;
    *b = buf;
}

int partition(int **a, int l, int r, int c) {
    int i;
    // Left pivot
    int pivot_val = a[l/c][l%c];
    // Move pivot to end
    swap(&a[l/c][l%c], &a[r/c][r%c]);

    // If <= to the pivot value, swap
    int j = l;
    for (i = l; i < r; i++) {
        if (a[i/c][i%c] <= pivot_val) {
            swap(&a[i/c][i%c], &a[j/c][j%c]);
            j++;
        }
    }

    // Move pivot to its place.
    swap(&a[j/c][j%c], &a[r/c][r%c]);

    return j;
}

void quicksort_r(int **a, int l, int r, int c) {
    if (l < r) {
        int pivot = partition(a, l, r, c);
        quicksort_r(a, l, pivot-1, c);
        quicksort_r(a, pivot+1, r, c);
    }
}

void quicksort(int **a, int rows, int cols) {
    quicksort_r(a, 0, rows * cols - 1, cols);
}

int main() {
    int i, j;
    int rows = 5;
    int cols = 4;
    int **matrix = malloc(sizeof(int*) * rows);

    // Init of a 2D array with random numbers:
    for (i = 0; i < rows; i++) {
        matrix[i] = malloc(sizeof(int) * cols);
        for (j = 0; j < cols; j++) {
            matrix[i][j] = random() % 10;
        }
    }

    // Before:
    printf("Before:\n");
    print_matrix(matrix, rows, cols);

    quicksort(matrix, rows, cols);

    // After:
    printf("After:\n");
    print_matrix(matrix, rows, cols);

    return 0;
}

这给出了:

Before:
3 6 7 5 
3 5 6 2 
9 1 2 7 
0 9 3 6 
0 6 2 6 
After:
0 0 1 2 
2 2 3 3 
3 5 5 6 
6 6 6 6 
7 7 9 9 

Edit2:后来我意识到方阵还有另一个明显的解决方案:

我们来看第一个例子:

0 1 2 2 
3 3 3 5 
5 6 6 6 
7 7 9 9

还有:

0 3 5 7
1 3 6 7
2 3 6 9
2 5 6 9

但对于第二个例子也是如此:

0 0 1 2 
2 2 3 3 
3 5 5 6 
6 6 6 6 
7 7 9 9 

还有:

0 2 3 6
0 2 5 6
1 3 5 6
2 3 6 6
7 7 9 9

这意味着也许我们可以做一个能够给出所有解决方案的专门算法,或者一个试图最小化移动次数的算法,我不知道。其实这是一个很有趣的问题。

【讨论】:

    【解决方案2】:

    尝试使用和调整它...

    void sort(int MyArray[8][8])
    {
         for(int ir=0;ir<8;ir++)
         {
            for(int ic=0;ic<8;ic++)
            {
                for(int jr=0;jr<8;jr++)  
                {
                        for(int jc=0;jc<8;jc++)
                        {        
                          if(MyArray[ir][jr]>MyArray[ic][jc])
                           {
                             int temp=MyArray[ir][jr];
                             MyArray[ir][jr]=MyArray[ic][jc];
                             MyArray[ic][jc]=temp;
                           }
                        }
                 }
            }
         }
    }
    

    这是一个简单的冒泡排序。它有效地运行在 O(n^4) 上,您可以通过编写诸如快速排序之类的算法来提高效率。我从未见过甚至想过尝试对二维数组进行快速排序。这并不容易。您可以尝试将所有内容添加到单个数组中,对其进行快速排序并将所有内容复制回二维数组中。但是数组必须非常大才能更有效......如果有人在这里为二维数组提供快速排序或合并排序算法。他应该得到一枚勋章!那是铁杆

    【讨论】:

    • 注意我不确定你想如何对它们进行排序......这有点定义不正确。但我希望这对你有帮助。这是一个棘手的面试问题
    • 接受挑战 :)。请参阅我的答案以获取二维数组的快速排序;)。
    • 马克西姆干得好。非常令人印象深刻。在递归函数中使用 for 循环。做得好 ! :)
    • 这其实只是一个快速排序,唯一的修改是a[j/c][j%c]而不是a[j]
    • 啊啊我现在看到了...对不起。数据结构对我来说是前段时间......做得很好。 :) 像你这样的答案提醒我那里确实有聪明的人。我对在“现实世界”中编程很陌生,刚开始时很难。但我喜欢它
    猜你喜欢
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 2015-01-31
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多