【问题标题】:Sorting 2d array (matrix) in C在C中对二维数组(矩阵)进行排序
【发布时间】:2018-01-16 23:41:09
【问题描述】:

我的任务是对二维数组进行排序,但这对我来说真的很难。我不知道我在哪里犯了错误。

用while循环代替for循环会更好

这是任务:

  1. 输入一个维度为 n 的方阵。
  2. 主对角线以下的元素按升序排序。
  3. 主对角线上方的元素按降序排列。
  4. 主对角线排序的元素:
    • 第一个偶数按升序排列。
    • 然后按降序排列奇数。

排序前的矩阵:

1  5  4  7  2

4  8  5  9  0

2  7  6  5  3

3  1  7  4  9

2  5  1  7  3

排序后的矩阵:

4  9  9  7  5

1  6  5  5  4 

1  2  8  3  2 

2  3  4  3  0

5  7  7  7  1

代码如下:

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

int main () {

    int n, i, j, a, k, l, o;
    int m[50][50];

    printf ("Enter n of square matrix : \n");
    scanf ("%d", &n);

    printf ("Enter rows and columns numbers n :\n");

    i = 0;
    while (i < n) {
        j = 0;
        while (j < n) {
            scanf ("%d", &m[i][j]);
            j++;
        }
        i++;
    }
    printf ("Matrix before sorting \n");
    i = 0;
    while (i < n) {
        j = 0;
        while (j < n) {
            printf ("%d  ", m[i][j]);
            j++;
        }
        printf ("\n");
        i++;
    }
    printf ("Matrix after sorting \n");

    i = 0;
    while (i < n) {
        j = 0;
        while (j < n) {
            if (i < j) {
                k = j + 1;
                while (k < (n - 1)) {
                    if (m[i][k] < m[i][k + 1]) {
                        a = m[i][k];
                        m[i][k] = m[i][k + 1];
                        m[i][k + 1] = a;
                    }
                    k++;
                }
            } 
            else if (i > j) {
                l = i + 1;
                while (l < (n - 1)) {
                    if (m[l][j] > m[l + 1][j]) {
                        a = m[l][j];
                        m[l][j] = m[l + 1][j];
                        m[l + 1][j] = a;
                    }
                    l++;
                }
            } 
            else {
                if (m[i][j] % 2 == 0 && m[i + 1][j + 1] % 2 == 0) {
                    if (m[i][j] > m[i + 1][j + 1]) {
                        a = m[i][j];
                        m[i][j] = m[i + 1][j + 1];
                        m[i + 1][j + 1] = a;
                    }
                }
                if (m[i][j] % 2 != 0 && m[i + 1][j + 1] % 2 != 0) {
                    if (m[i][j] < m[i + 1][j + 1]) {
                        a = m[i][j];
                        m[i][j] = m[i + 1][j + 1];
                        m[i + 1][j + 1] = a;
                    }
                }
            }
            j++;
        }
        i++;
    }

    i = 0;
    while (i < n) {
        j = 0;
        while (j < n) {
            printf ("%d  ", m[i][j]);
            j++;
        }
        printf ("\n");
        i++;
    }

    return 0;
}

2018 年 2 月 2 日所做的更改

我需要编写简单的代码,没有 size_t、缓冲区和指针等...

我编写了一些代码,但是当我使用奇数 n 个矩阵时,它无法正常工作(例如 5x5)我不知道我在哪里犯了错误。

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

 int main()
 {
static int a[500][500];
int i,j,l,k,m,b,n,t,d,c;

printf("Unesite n kvadratne matrice : \n");
scanf("%d" , &n);
printf("Matrica pre sortiranja \n \n");

for ( i = 0; i < n; i++)
{
    for ( j = 0; j < n ; j++)
    {
        scanf("%d",&a[ i ][ j ]);
    }
}


for ( i = 0; i < n; i++)
{
    for ( j = 0; j < n; j++)
    {
        if ( i > j )  // ispod dijagonale
        {
                for ( l = i ; l < n ; l++)
            {
                for ( k = j ; k < l  ; k++ )
                {
                    if ( a[ i ][ j ] > a[ l ][ k ] && k  < l )
                    {
                    t = a[ i ][ j ];
                    a[ i ][ j ] = a[ l ][ k ];
                    a[ l ][ k ] = t ;
                    }
                }
            }
        }
        if ( i < j ) // iznad dijagonale
        {
            for ( m = i ; m < n  ; m++)
            {
                for ( b = j ; b < n ; b++)
                {
                    if ( a[ i ][ j ] < a[ m ][ b ] && m < b )
                    {
                    t = a[ i ][ j ];
                    a[ i ][ j ] = a[ m ][ b ];
                    a[ m ][ b ] = t ;
                    }
                }
            }
        }
        if ( i == j ) // dijagonala
        {
            for (d = i ; d < n ; d++)
                {
                for ( c = d + 1 ; c < n ; c++)
                    {
                    if ( a[ d ] [ d ] % 2 != 0 && a[ c ] [ c]%2 == 0 )
                        {
                        t = a[ d ] [ d ] ;
                         a[ d ] [ d ] = a[ c ] [ c] ;
                         a[ c ] [ c] = t ;
                        }
                    }
                }
                for (d = i ; d < n ; d++)
                    {
                    for ( c = d + 1 ; c < n ; c++)
                        {
                             if ( a[ d ][ d ] %2 == 0 && a[ c ][ c ] %2 ==0 
       && a[ d ][ d ] > a [ c ][ c ])
                            {
                            t = a[ d ] [ d ] ;
                            a[ d ] [ d ] = a[ c ] [ c] ;
                            a[ c ] [ c] = t ;
                            }
                            else if ( a[ d ][ d ] %2 != 0 && a[ c ][ c ] %2 
   !=0 && a[ d ][ d ] < a [ c ][ c ])
                            {
                            t = a[ d ] [ d ] ;
                            a[ d ] [ d ] = a[ c ] [ c] ;
                            a[ c ] [ c] = t ;
                            }
                        }
                    }
        }
    }
  }

    printf("Posle sortiranja : \n");
    for ( i = 0; i < n; i++)
    {
        for ( j = 0; j < n;j++)
        {
        printf("    %d  ",a[i][j]);
        }
    printf("\n \n");
    }
  return 0;
 }

【问题讨论】:

  • 如果不能直接放代码,至少用pastebin之类的粘贴服务,放在这里
  • 欢迎来到 Stack Overflow,请拨打tour 并阅读How to ask a good question。 Stack Overflow 不是编码服务,您不能只发布您的家庭作业并期望我们为您做作业。自己做吧,如果你有什么问题,那么你可以问这个。另见How to create a Minimal, Complete, and Verifiable example
  • 这个问题也可以有很多答案......它不会有一个单一的解决方案......你可能需要以更好的方式来构建问题
  • 在排序代码之后打印“排序后的矩阵”的消息可能会更好。
  • 如果是我的代码,会有三个单独的排序函数,对角线、上三角和下三角各一个。我可能还会有两个或三个比较函数,一个用于对角线,一个用于上下三角形。比较可能是static inline 以获得最大收益。我还没有坐下来完成三角形的索引排序;不过,对角线很容易。

标签: c arrays sorting matrix


【解决方案1】:

这是一个有趣的问题。正如我在comment 中概述的那样,我认为解决方案必须通过三个单独的排序操作来解决:

  • 对角线排序
  • 对上三角进行排序
  • 对下三角排序

这些操作发生的顺序无关紧要。事实上,如果你想用线程并行运行这三种排序,你可以这样做。

对对角线排序的诀窍是编写一个比较函数,确保所有偶数都在所有奇数之前(因此每个偶数都被认为小于任何奇数),但是当比较两个偶数时,它们'重新按升序排序,而当比较两个奇数时,它们按降序排序。 cmp_aeod() 函数(ascending even odd descending)函数实现了这一点。

可以只使用cmp_asc()cmp_dsc() 函数之一,但同时使用这两个函数更直接。 (x &gt; y) - (x &lt; y) 成语总是进行两次比较,但如果x 大于y,则第一项为1,第二项为0,结果为1。如果x小于y,则第一项为0,第二项为1,结果为-1。如果x等于y,当然两个词都是0,结果也是0

对三角形进行排序的关键是要注意排序算法对连续数组起作用,但三角形中的数据不是连续的。所示的解决方案是将三角形中的元素从0 编号到m,其中m = (n * (n - 1)) / 2,假设方阵是n 乘以n 1。然后,代码需要能够识别应访问matrix 中的哪些索引以获得相应的元素编号,并且此映射由三角形排序函数中的utlt 矩阵完成。我无法制定一个非迭代公式将三角形中的序列号转换为行/列对,因此我创建了映射矩阵。这给出了 O(N2) 大小的辅助存储需求。

使用的排序算法是简单的二次排序;您可以根据需要将其更改为更复杂的算法(快速排序或其他)。

/*
**  + Enter a square matrix of dimensions n .
**  + Elements below main diagonal sort in ascending order.
**  + Elements above main diagonal sort in descending order.
**  + Elements on main diagonal sort :
**    - first even numbers in ascending order.
**    - then odd numbers in descending order.
*/

static inline int cmp_asc(int x, int y) { return (x > y) - (x < y); }
static inline int cmp_dsc(int x, int y) { return (x < y) - (x > y); }
static inline int cmp_eaod(int x, int y)
{
    int px = x & 1;
    int py = y & 1;
    if (px != py)
        return px - py;
    if (px == 1)
        return cmp_dsc(x, y);
    return cmp_asc(x, y);
}

#include <stdio.h>

static void print_matrix(const char *tag, size_t r, size_t c, int matrix[r][c])
{
    printf("%s:\n", tag);
    for (size_t i = 0; i < r; i++)
    {
        for (size_t j = 0; j < c; j++)
            printf("%3d", matrix[i][j]);
        putchar('\n');
    }
}

static void sort_diagonal(size_t n, int matrix[n][n])
{
    for (size_t i = 0; i < n; i++)
    {
        for (size_t j = i + 1; j < n; j++)
        {
            if (cmp_eaod(matrix[i][i], matrix[j][j]) > 0)
            {
                int t = matrix[i][i];
                matrix[i][i] = matrix[j][j];
                matrix[j][j] = t;
            }
        }
    }
}

/*
**   D0  U0  U1  U2  U3
**   L0  D1  U4  U5  U6
**   L1  L2  D3  U7  U8
**   L3  L4  L5  D4  U9
**   L6  L7  L8  L9  D5
**
** D0 = (0, 0); U0 = (0, 1); U1 = (0, 2); U2 = (0, 3); U3 = (0, 4);
** L0 = (1, 0); D1 = (1, 1); U4 = (1, 2); U5 = (1, 3); U6 = (1, 4);
** L1 = (2, 0); L2 = (2, 1); D2 = (2, 2); U7 = (2, 3); U8 = (2, 4);
** L3 = (3, 0); L4 = (3, 1); L5 = (3, 2); D3 = (3, 3); U9 = (3, 4);
** L6 = (4, 0); L7 = (4, 1); L8 = (4, 2); L9 = (4, 3); D4 = (4, 4); 
*/

/*
** It is probably best to create an array that does the mapping from an
** index to the row/column, with one such mapping for the lower
** triangle; one for the upper triangle.
*/

static void sort_lt(size_t n, int matrix[n][n])
{
    size_t m = (n * (n - 1)) / 2;
    int lt[m][2];
    size_t r = 1;
    size_t c = 0;
    for (size_t i = 0; i < m; i++)
    {
        lt[i][0] = r;
        lt[i][1] = c++;
        if (c == r)
        {
            r++;
            c = 0;
        }
    }
    //print_matrix("LT map", m, 2, lt);

    for (size_t i = 0; i < m; i++)
    {
        size_t xi = lt[i][0];
        size_t yi = lt[i][1];
        for (size_t j = i + 1; j < m; j++)
        {
            size_t xj = lt[j][0];
            size_t yj = lt[j][1];
            if (cmp_asc(matrix[xi][yi], matrix[xj][yj]) > 0)
            {
                int t = matrix[xi][yi];
                matrix[xi][yi] = matrix[xj][yj];
                matrix[xj][yj] = t;
            }
        }
    }
}

static void sort_ut(size_t n, int matrix[n][n])
{
    size_t m = (n * (n - 1)) / 2;
    int ut[m][2];
    size_t r = 0;
    size_t c = 0;
    for (size_t i = 0; i < m; i++)
    {
        ut[i][0] = r;
        ut[i][1] = ++c;
        if (c == n - 1)
        {
            r++;
            c = r;
        }
    }
    //print_matrix("UT map", m, 2, ut);

    for (size_t i = 0; i < m; i++)
    {
        size_t xi = ut[i][0];
        size_t yi = ut[i][1];
        for (size_t j = i + 1; j < m; j++)
        {
            size_t xj = ut[j][0];
            size_t yj = ut[j][1];
            if (cmp_dsc(matrix[xi][yi], matrix[xj][yj]) > 0)
            {
                int t = matrix[xi][yi];
                matrix[xi][yi] = matrix[xj][yj];
                matrix[xj][yj] = t;
            }
        }
    }
}

static void test_matrix(const char *tag, size_t n, int matrix[n][n])
{
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "Matrix %s (%zux%zu) - before", tag, n, n);
    print_matrix(buffer, n, n, matrix);
    //print_matrix("Before sorting diagonal", n, n, matrix);
    sort_diagonal(n, matrix);
    //print_matrix("After sorting diagonal", n, n, matrix);
    sort_lt(n, matrix);
    //print_matrix("After sorting lower triangle", n, n, matrix);
    sort_ut(n, matrix);
    //print_matrix("After sorting upper triangle", n, n, matrix);
    snprintf(buffer, sizeof(buffer), "Matrix %s (%zux%zu) - after", tag, n, n);
    print_matrix(buffer, n, n, matrix);
}

int main(void)
{
    int matrix1[5][5] =
    {
        { 1, 5, 4, 7, 2 },
        { 4, 8, 5, 9, 0 },
        { 2, 7, 6, 5, 3 },
        { 3, 1, 7, 4, 9 },
        { 2, 5, 1, 7, 3 },
    };
    test_matrix("SAMPLE1", 5, matrix1);

    // gen_matrix -i -n matrix2 -r 10 -c 10 -L 10 -H 99
    int matrix2[10][10] =
    {
        { 87, 32, 98, 58, 60, 71, 46, 81, 70, 14, },
        { 22, 92, 15, 98, 51, 26, 94, 67, 46, 56, },
        { 71, 89, 86, 16, 20, 89, 97, 89, 45, 92, },
        { 63, 13, 76, 19, 75, 19, 66, 89, 58, 41, },
        { 82, 68, 75, 26, 58, 20, 89, 87, 65, 66, },
        { 74, 83, 68, 92, 10, 98, 90, 21, 39, 63, },
        { 24, 65, 23, 68, 62, 44, 48, 22, 27, 59, },
        { 26, 27, 71, 71, 51, 31, 43, 69, 92, 10, },
        { 54, 19, 41, 50, 10, 89, 42, 52, 94, 54, },
        { 42, 50, 79, 48, 77, 18, 29, 40, 61, 63, },
    };
    test_matrix("SAMPLE 2", 10, matrix2);

    return 0;
}

运行时,输出为:

Matrix SAMPLE1 (5x5) - before:
  1  5  4  7  2
  4  8  5  9  0
  2  7  6  5  3
  3  1  7  4  9
  2  5  1  7  3
Matrix SAMPLE1 (5x5) - after:
  4  9  9  7  5
  1  6  5  5  4
  1  2  8  3  2
  2  3  4  3  0
  5  7  7  7  1
Matrix SAMPLE 2 (10x10) - before:
 87 32 98 58 60 71 46 81 70 14
 22 92 15 98 51 26 94 67 46 56
 71 89 86 16 20 89 97 89 45 92
 63 13 76 19 75 19 66 89 58 41
 82 68 75 26 58 20 89 87 65 66
 74 83 68 92 10 98 90 21 39 63
 24 65 23 68 62 44 48 22 27 59
 26 27 71 71 51 31 43 69 92 10
 54 19 41 50 10 89 42 52 94 54
 42 50 79 48 77 18 29 40 61 63
Matrix SAMPLE 2 (10x10) - after:
 48 98 98 97 94 92 92 90 89 89
 10 58 89 89 87 81 75 71 70 67
 10 13 86 66 66 65 63 60 59 58
 18 19 22 92 58 56 54 51 46 46
 23 24 26 26 94 45 41 39 32 27
 27 29 31 40 41 98 26 22 21 20
 42 42 43 44 48 50 87 20 19 16
 50 51 52 54 61 62 63 69 15 14
 65 68 68 68 71 71 71 74 63 10
 75 76 77 79 82 83 89 89 92 19

“SAMPLE1 - before”数据对应于问题中的输入,“SAMPLE 1 - after”输出对应于所需的输出。更大的矩阵结果似乎也符合要求。

我首先开发了对角线排序,因为它是迄今为止最简单的;偶数升序,奇数降序是我之前解决的问题。然后我开发了一种三角形,并对其进行了调试。对第二个三角形进行排序非常简单。确保我有一个良好的灵活矩阵打印功能也有帮助。注释掉的调用都在开发过程中的某个时候使用过。


计时测试

随着矩阵的增长,显示的“就地排序”代码变得非常慢。还有一种替代方法——将矩阵中的数据复制到一维向量中;对向量进行排序;将数据复制回矩阵。我做了一些时间测试。对于 10x10 的矩阵大小,时间相当(上面显示的基本排序代码为 15µs;使用提取、快速排序、插入的代码为 12µs)。当矩阵大小为 20x20 时,性能坚定地支持提取、快速排序、插入:172µs 与 32µs 支持快速排序,到 900x900 时,基本排序为 285s 与 0.054s 快速排序。差异的增长速度超过了二次排序所能解释的范围。问题是访问被排序元素的访问路径非常复杂。创建ltut 矩阵的代码仍然有用。 ltut 矩阵告诉您从哪些单元格收集数据以对三角形进行排序(在提取数据时顺序并不重要,因为无论如何它都将被排序),而且(至关重要)告诉您在排序数据中放置每个元素的位置。

您可以在 GitHub 上的 SOQ 中找到我的代码(堆栈 溢出问题)存储库中的 src/so-4829-1562 子目录。 (请注意,目前,该代码将 VLA 用于中间矩阵;它在 Mac 上以 1000x1000 左右崩溃。我需要将其更改为在排序代码和数据生成代码中使用动态内存分配。它可能会得到迟早会修复。此外,我不相信在硬件刷新之间有足够的时间在 10000x10000 大小的矩阵上使用基本排序,尽管我认为快速排序代码仍然可用。)

另一个有趣的测试是在对三角形进行排序时调整“基本排序”以使用提取、二次排序和插入。我很确定它会大大超过“基本排序”代码,尽管随着数组变大,它仍然会输给 O(NlogN) 快速排序代码。与排序时间相比,复制时间可以忽略不计。

使用qsort()

/* SO 4829-1562 */

#include "time.sort2d-31.h"
#include "emalloc.h"

/*
**  + Enter a square matrix of dimensions n .
**  + Elements below main diagonal sort in ascending order.
**  + Elements above main diagonal sort in descending order.
**  + Elements on main diagonal sort :
**    - first even numbers in ascending order.
**    - then odd numbers in descending order.
*/

/* Variation 4: Use system qsort() and common code to coordinate sorting of triangles */
/* Avoids two matrices lt and ut, thereby reducing the extra data space needed. */

static inline int cmp_asc(int x, int y) { return (x > y) - (x < y); }
static inline int cmp_dsc(int x, int y) { return (x < y) - (x > y); }
static inline int cmp_eaod(int x, int y)
{
    int px = x & 1;
    int py = y & 1;
    if (px != py)
        return px - py;
    if (px == 1)
        return cmp_dsc(x, y);
    return cmp_asc(x, y);
}

static int qs_cmp_int_asc(const void *v1, const void *v2)
{
    int i1 = *(const int *)v1;
    int i2 = *(const int *)v2;
    return cmp_asc(i1, i2);
}

static int qs_cmp_int_dsc(const void *v1, const void *v2)
{
    int i1 = *(const int *)v1;
    int i2 = *(const int *)v2;
    return cmp_dsc(i1, i2);
}

static int qs_cmp_int_eaod(const void *v1, const void *v2)
{
    int i1 = *(const int *)v1;
    int i2 = *(const int *)v2;
    return cmp_eaod(i1, i2);
}

static void sort_diagonal(size_t n, int matrix[n][n])
{
    int data[n];
    for (size_t i = 0; i < n; i++)
        data[i] = matrix[i][i];
    qsort(data, n, sizeof(data[0]), qs_cmp_int_eaod);
    for (size_t i = 0; i < n; i++)
        matrix[i][i] = data[i];
}

/*
**   D0  U0  U1  U2  U3
**   L0  D1  U4  U5  U6
**   L1  L2  D3  U7  U8
**   L3  L4  L5  D4  U9
**   L6  L7  L8  L9  D5
**
** D0 = (0, 0); U0 = (0, 1); U1 = (0, 2); U2 = (0, 3); U3 = (0, 4);
** L0 = (1, 0); D1 = (1, 1); U4 = (1, 2); U5 = (1, 3); U6 = (1, 4);
** L1 = (2, 0); L2 = (2, 1); D2 = (2, 2); U7 = (2, 3); U8 = (2, 4);
** L3 = (3, 0); L4 = (3, 1); L5 = (3, 2); D3 = (3, 3); U9 = (3, 4);
** L6 = (4, 0); L7 = (4, 1); L8 = (4, 2); L9 = (4, 3); D4 = (4, 4); 
*/

typedef void (*Copier)(int *val1, int *val2);

static void copy_a_to_b(int *val1, int *val2) { *val2 = *val1; }
static void copy_b_to_a(int *val1, int *val2) { *val1 = *val2; }

static void copy_lt_data(size_t n, int matrix[n][n], int vector[], Copier copy)
{
    size_t m = (n * (n - 1)) / 2;
    size_t r = 1;
    size_t c = 0;
    for (size_t i = 0; i < m; i++)
    {
        (*copy)(&matrix[r][c++], &vector[i]);
        if (c == r)
        {
            r++;
            c = 0;
        }
    }
}

static void copy_ut_data(size_t n, int matrix[n][n], int vector[], Copier copy)
{
    size_t m = (n * (n - 1)) / 2;
    size_t r = 0;
    size_t c = 0;
    for (size_t i = 0; i < m; i++)
    {
        (*copy)(&matrix[r][++c], &vector[i]);
        if (c == n - 1)
        {
            r++;
            c = r;
        }
    }
}

typedef void (*Mapper)(size_t n, int matrix[n][n], int vector[], Copier copy);
typedef int (*Comparator)(const void *v1, const void *v2);

static void sort_triangle(size_t n, int matrix[n][n], Mapper mapper, Comparator cmp)
{
    size_t m = (n * (n - 1)) / 2;
    int *data = MALLOC(m * sizeof(*data));

    (*mapper)(n, matrix, data, copy_a_to_b);
    qsort(data, m, sizeof(data[0]), cmp);
    (*mapper)(n, matrix, data, copy_b_to_a);

    FREE(data);
}

void quick_sort(size_t n, int matrix[n][n])
{
    sort_diagonal(n, matrix);
    sort_triangle(n, matrix, copy_lt_data, qs_cmp_int_asc);
    sort_triangle(n, matrix, copy_ut_data, qs_cmp_int_dsc);
}

我还进行了计时测试——请参阅 GitHub 获取源代码。结果是:

Basic sort (10x10) - elapsed:    0.000010
Clean sort (10x10) - elapsed:    0.000008
Quick sort (10x10) - elapsed:    0.000015
Basic sort (20x20) - elapsed:    0.000153
Clean sort (20x20) - elapsed:    0.000112
Quick sort (20x20) - elapsed:    0.000026
Basic sort (30x30) - elapsed:    0.000800
Clean sort (30x30) - elapsed:    0.000645
Quick sort (30x30) - elapsed:    0.000060
Basic sort (40x40) - elapsed:    0.002661
Clean sort (40x40) - elapsed:    0.002057
Quick sort (40x40) - elapsed:    0.000106
Basic sort (50x50) - elapsed:    0.006347
Clean sort (50x50) - elapsed:    0.005038
Quick sort (50x50) - elapsed:    0.000175
Basic sort (60x60) - elapsed:    0.014120
Clean sort (60x60) - elapsed:    0.009732
Quick sort (60x60) - elapsed:    0.000258
Basic sort (70x70) - elapsed:    0.023101
Clean sort (70x70) - elapsed:    0.016593
Quick sort (70x70) - elapsed:    0.000360
Basic sort (80x80) - elapsed:    0.035169
Clean sort (80x80) - elapsed:    0.027466
Quick sort (80x80) - elapsed:    0.000445
Basic sort (90x90) - elapsed:    0.053590
Clean sort (90x90) - elapsed:    0.039012
Quick sort (90x90) - elapsed:    0.000665
Basic sort (100x100) - elapsed:    0.074192
Clean sort (100x100) - elapsed:    0.053694
Quick sort (100x100) - elapsed:    0.000797
Basic sort (200x200) - elapsed:    0.656721
Clean sort (200x200) - elapsed:    0.478688
Quick sort (200x200) - elapsed:    0.002313
Basic sort (300x300) - elapsed:    2.826153
Clean sort (300x300) - elapsed:    2.126663
Quick sort (300x300) - elapsed:    0.004871
Basic sort (400x400) - elapsed:    8.384908
Clean sort (400x400) - elapsed:    6.374244
Quick sort (400x400) - elapsed:    0.008324
Basic sort (500x500) - elapsed:   22.083337
Clean sort (500x500) - elapsed:   16.124325
Quick sort (500x500) - elapsed:    0.014953
Basic sort (600x600) - elapsed:   43.233985
Clean sort (600x600) - elapsed:   31.362548
Quick sort (600x600) - elapsed:    0.019563
Basic sort (700x700) - elapsed:   85.463261
Clean sort (700x700) - elapsed:   60.488744
Quick sort (700x700) - elapsed:    0.027003
Basic sort (800x800) - elapsed:  148.358024
Clean sort (800x800) - elapsed:  102.991679
Quick sort (800x800) - elapsed:    0.038143
Basic sort (900x900) - elapsed:  253.434539
Clean sort (900x900) - elapsed:  150.658682
Quick sort (900x900) - elapsed:    0.045815

Quick sort (10x10) - elapsed:    0.000007
Quick sort (20x20) - elapsed:    0.000025
Quick sort (30x30) - elapsed:    0.000057
Quick sort (40x40) - elapsed:    0.000104
Quick sort (50x50) - elapsed:    0.000196
Quick sort (60x60) - elapsed:    0.000245
Quick sort (70x70) - elapsed:    0.000397
Quick sort (80x80) - elapsed:    0.000435
Quick sort (90x90) - elapsed:    0.000538
Quick sort (100x100) - elapsed:    0.000676
Quick sort (200x200) - elapsed:    0.002780
Quick sort (300x300) - elapsed:    0.005868
Quick sort (400x400) - elapsed:    0.009393
Quick sort (500x500) - elapsed:    0.016258
Quick sort (600x600) - elapsed:    0.024982
Quick sort (700x700) - elapsed:    0.031137
Quick sort (800x800) - elapsed:    0.042561
Quick sort (900x900) - elapsed:    0.052450
Quick sort (1000x1000) - elapsed:    0.061720
Quick sort (2000x2000) - elapsed:    0.229984
Quick sort (3000x3000) - elapsed:    0.480724
Quick sort (4000x4000) - elapsed:    0.826916
Quick sort (5000x5000) - elapsed:    1.308370
Quick sort (6000x6000) - elapsed:    1.890218
Quick sort (7000x7000) - elapsed:    2.559171
Quick sort (8000x8000) - elapsed:    3.346258
Quick sort (9000x9000) - elapsed:    4.359553
Quick sort (10000x10000) - elapsed:    5.345243
Quick sort (20000x20000) - elapsed:   22.189061
Quick sort (30000x30000) - elapsed:   51.385711
Quick sort (40000x40000) - elapsed:   97.543689
Quick sort (50000x50000) - elapsed:  177.373366
Quick sort (60000x60000) - elapsed:  315.083561
Quick sort (70000x70000) - elapsed:  476.135379
Quick sort (80000x80000) - elapsed:  756.888114
Quick sort (90000x90000) - elapsed: 1002.540185

在非常小的尺寸(10x10 或更小)下,qsort() 代码可能比其他代码慢 - 差异很小(几微秒)但相当一致。当您达到 20x20 时,qsort() 代码持续更快,并且差异越来越大。请注意,用于 O(NlogN) 或 O(N2) 的大小 N 对应于矩阵大小的平方 - 因此要在 20x20 矩阵中排序的数据量是要在 10x10 矩阵中排序的数据量的四倍。基本排序或“干净排序”的性能非常糟糕,以至于无法考虑 90k x 90k 矩阵,但 qsort() 代码对其进行排序的时间与其他人排序 900 所用的时间相当x 900 矩阵(大小的 1/10,000th)。

修复 2018-02-02 添加的代码

2018-02-02 添加到问题中的代码是以不同方式解决问题的一次很好的尝试。 正如 OP 所指出的,它有时无法正确排序数据。

问题在于下三角的代码

这是固定的代码,因此它可以在之前使用的两个样本矩阵上产生正确的输出。

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

int main(void)
{
    static int a[500][500];
    int i, j, l, k, m, b, n, t, d, c;

    printf("Unesite n kvadratne matrice:\n");
    scanf("%d", &n);
    printf("Matrica pre sortiranja\n\n");

    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            scanf("%d", &a[i][j]);
        }
    }

    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
            printf("%3d", a[i][j]);
        printf("\n");
    }

    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            if (i > j) // ispod dijagonale (LT)
            {
                int s = j + 1;                                          // JL
                for (l = i; l < n; l++)
                {
                    //for (k = j; k < l; k++)                           // OP
                    for (k = s; k < l; k++)                             // JL
                    {
                        //printf("a[%d][%d] = %d <=> a[%d][%d] %d\n",   // JL
                        //    i, j, a[i][j], l, k, a[l][k]);            // JL
                        //if (a[i][j] > a[l][k] && k < l)               // OP
                        if (a[i][j] > a[l][k])                          // JL
                        {
                            t = a[i][j];
                            a[i][j] = a[l][k];
                            a[l][k] = t;
                        }
                    }
                    s = 0;                                              // JL
                }
            }
            if (i < j) // iznad dijagonale (UT)
            {
                int s = j + 1;                                          // JL
                for (m = i; m < n; m++)
                {
                    //for (b = j; b < n; b++)                           // OP
                    for (b = s; b < n; b++)                             // JL
                    {
                        //printf("a[%d][%d] = %d <=> a[%d][%d] %d\n",   // JL
                        //    i, j, a[i][j], m, b, a[m][b]);            // JL
                        //if (a[i][j] < a[m][b] && m < b)               // OP
                        if (a[i][j] < a[m][b])                          // JL
                        {
                            t = a[i][j];
                            a[i][j] = a[m][b];
                            a[m][b] = t;
                        }
                    }
                    s = m + 2;                                          // JL
                }
            }
            if (i == j) // dijagonala
            {
                for (d = i; d < n; d++)
                {
                    for (c = d + 1; c < n; c++)
                    {
                        if (a[d][d] % 2 != 0 && a[c][c] % 2 == 0)
                        {
                            t = a[d][d];
                            a[d][d] = a[c][c];
                            a[c][c] = t;
                        }
                    }
                }
                for (d = i; d < n; d++)
                {
                    for (c = d + 1; c < n; c++)
                    {
                        if (a[d][d] % 2 == 0 && a[c][c] % 2 == 0
                            && a[d][d] > a[c][c])
                        {
                            t = a[d][d];
                            a[d][d] = a[c][c];
                            a[c][c] = t;
                        }
                        else if (a[d][d] % 2 != 0 && a[c][c] % 2
                                 != 0 && a[d][d] < a[c][c])
                        {
                            t = a[d][d];
                            a[d][d] = a[c][c];
                            a[c][c] = t;
                        }
                    }
                }
            }
        }
    }

    printf("Posle sortiranja:\n");
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
            printf("%3d", a[i][j]);
        printf("\n");
    }

    return 0;
}

注释掉的打印操作对于找出问题所在至关重要。

样本输出

这个程序是sort2d-mk2-73

$ sort2d-mk2-73 < example-2.in
Unesite n kvadratne matrice:
Matrica pre sortiranja

 87 32 98 58 60 71 46 81 70 14
 22 92 15 98 51 26 94 67 46 56
 71 89 86 16 20 89 97 89 45 92
 63 13 76 19 75 19 66 89 58 41
 82 68 75 26 58 20 89 87 65 66
 74 83 68 92 10 98 90 21 39 63
 24 65 23 68 62 44 48 22 27 59
 26 27 71 71 51 31 43 69 92 10
 54 19 41 50 10 89 42 52 94 54
 42 50 79 48 77 18 29 40 61 63
Posle sortiranja:
 48 98 98 97 94 92 92 90 89 89
 10 58 89 89 87 81 75 71 70 67
 10 13 86 66 66 65 63 60 59 58
 18 19 22 92 58 56 54 51 46 46
 23 24 26 26 94 45 41 39 32 27
 27 29 31 40 41 98 26 22 21 20
 42 42 43 44 48 50 87 20 19 16
 50 51 52 54 61 62 63 69 15 14
 65 68 68 68 71 71 71 74 63 10
 75 76 77 79 82 83 89 89 92 19
$ sort2d-mk2-73 < example-1.in
Unesite n kvadratne matrice:
Matrica pre sortiranja

  1  5  4  7  2
  4  8  5  9  0
  2  7  6  5  3
  3  1  7  4  9
  2  5  1  7  3
Posle sortiranja:
  4  9  9  7  5
  1  6  5  5  4
  1  2  8  3  2
  2  3  4  3  0
  5  7  7  7  1
$

为了比较,问题中发布的代码(sort2d-mk2-67)生成:

$ sort2d-mk2-67 < example-2.in
Unesite n kvadratne matrice : 
Matrica pre sortiranja 

Posle sortiranja : 
    48      98      98      97      94      92      92      90      89      66  

    10      58      89      89      89      87      81      75      70      63  

    10      13      86      71      67      66      65      60      59      56  

    18      19      22      92      58      58      54      51      46      46  

    23      24      26      29      94      45      41      39      32      27  

    26      27      31      40      41      98      26      22      21      20  

    42      42      43      44      48      50      87      20      19      16  

    50      51      52      54      61      62      63      69      15      14  

    65      68      68      68      71      71      71      76      63      10  

    74      75      77      79      82      83      89      89      92      19  

$ sort2d-mk2-67 < example-1.in
Unesite n kvadratne matrice : 
Matrica pre sortiranja 

Posle sortiranja : 
    4      9      9      7      5  

    1      6      5      5      3  

    1      2      8      4      2  

    2      3      5      3      0  

    4      7      7      7      1  

$

sort2d-mk2-67.csort2d-mk2-73.c 之间的变化之一是压缩打印;另一个变化是在排序操作之前和之后打印矩阵。

在较小的矩阵中,您可以看到第 1 行第 4 列(从 0 开始计数)中的 3 应该是第 2 行第 3 列中的 4。 同样,第 3 行第 2 列中的 5 应该是第 4 行第 1 列中的 4。 固定代码就OK了。

我还没有对此代码进行基准测试。

【讨论】:

  • 有没有更简单的方法来完成这项任务,我的初学者可以完全理解?在你写给我的这些例子中,很多东西我都不懂。我不需要程序才能生效,暂时(也许我以后想通了可以做),我想写一个初学者理解的程序。 :) 无论如何,谢谢你的努力
  • 需要多个问题才能弄清楚如何使它更简单。首先,您是否了解需要将操作拆分为三个不同的类别?接下来,你以前用过qsort()吗?这可以解释您是否可以理解比较器功能。对角线排序的诀窍是要认识到每个偶数必须比任何奇数都小。只有当两个数字都是奇数或都是偶数时,您才会真正比较它们的大小。
  • 嗯;我突然想到代码不能处理退化的情况。大小 0 和 1 始终是完全排序的。大小 2 只需要对对角线进行排序。 3 号及以上需要全面处理。
  • 我知道我需要 3 个单独的排序,我使用了 qsort() 。但我以前从未使用过指针。 ://
  • 我不确定你如何在不使用指针的情况下使用qsort()。也许有人为您提供了比较器功能?然而,这并不重要。如果你被要求按升序对一个包含 M 个整数的数组进行排序,你会怎么做?降序呢?您会创建或使用可以以任何一种方式排序的单个函数,还是需要创建两个函数?或者你会在main() 中编写两个代码块来完成这两项工作吗?在我看来,解决这个问题的关键是将矩阵的每个三角形部分复制到一个简单的 (1D) 向量中,对其进行排序,然后将向量复制回来。
猜你喜欢
  • 2015-01-31
  • 2015-09-17
  • 1970-01-01
  • 1970-01-01
  • 2013-07-03
  • 2010-09-18
  • 2020-08-15
  • 2019-05-17
相关资源
最近更新 更多