0

我被困在这个任务的第二部分。我认为我的算法有问题。如果我的代码朝着好的方向发展,请告诉我。这是我的任务 给定集合二维整数。该数组由 5 行和 10 列组成。系统中的每个值都是 0 到 20 之间的随机数。必须编写一个程序来执行数组值的排序,如下所示:首先将每列中的值排列,以便它们按升序排序(从上到下) ),然后 - 因此可以通过比较同一行中不同列中的值对(“比较词典”)对“正确”的列进行排序:比较第一行中两列中的两个值,如果它们与第二行中的值相比是相同的,依此类推,并相应地更改列的顺序(参见下面数组第三次打印中的示例)。在紧急情况的两个阶段中的每个阶段之前和之后显示数组。例如 : 输出

 #include "stdio.h"
#include "conio.h"
#include "malloc.h"
#include "stdlib.h"

#define N 5
#define M 10
#define LOW 0
#define HIGH 20

void initRandomArray(int arr[N][M]);
void printArray(int arr[N][M]);
void SortInColumn(int arr[N][M],int m);
void SortColumns(int arr[][M]);
int compareColumns(int arr[][M], int col1, int col2);
void swapColumns( int col1, int col2);

int main()
{
    int arr[N][M];
    int m;
    m=M;

    srand((unsigned)time(NULL)); //To clear the stack of Random Number
    initRandomArray(arr);
    printf("Before sorting:\n");
    printArray(arr);
    printf("Sorting elements in each column:\n");
    SortInColumn(arr,M);
    printf("Sorting columns:\n");
    SortColumns(arr);

    system("pause");
    return 0;
}
void initRandomArray(int arr[N][M])
{

    int i,j;
    for (i=0 ; i<N ; i++)
        for (j=0 ; j<M ; j++)
        {
         arr[i][j]=LOW+rand()%(HIGH-LOW+1);
        }

}
void printArray(int arr[N][M])
{ 
    int i,j;
    for (i=0 ; i<N ; i++)
    {
        for (j=0 ; j<M ; j++)
            printf("%d ", arr[i][j]);
         printf("\n");
    }
}
void SortInColumn(int arr[][M],int m)
{

    int i,j,k;
    int temp;

    for( k=0 ; k<m ; ++k) // loops around each columns
    {
        for(j=0; j<N-1; j++)// Loop for making sure we compare each column N-1 times since for each run we get one item in the right place
        {
                for(i=0; i < N-1 - j; i++) //loop do the adjacent comparison
                {
                        if (arr[i][k]>arr[i+1][k]) // compare adjacent item
                        {
                                temp=arr[i][k];
                                arr[i][k]=arr[i+1][k];
                                arr[i+1][k]=temp;
                        }
                }
        }
    }

    printArray(arr);
}
void SortColumns(int arr[][M])
{   int row=0,cols=0,i=0,n=N;
    int col1=arr[row][cols];
    int col2=arr[row][cols];
    compareColumns(arr,col1,col2);

}
int compareColumns(int arr[][M], int col1, int col2)
{
    int row=0,cols=0,j;
    for ( row=0 ; row < N ; row ++ );
        {
            for( cols=0 ; cols < M-1 ; cols++)
            {
                if(arr[row][cols]>arr[row][cols+1])
                {
                  for (j=0 ; j < M-1 ; j++)
                  {
                    col1=arr[row][cols];
                    col2=arr[row][cols+1];
                    swapColumns(col1 , col2 );
                  }

                }
            }
        }
    printArray(arr);
}
void swapColumns(int col1, int col2)
{
    int temp;
    temp=col1;
    col1=col2;
    col2=temp;

}

顺便说一下 compareColumns 函数的复杂度是 (n^3) 吗?

4

1 回答 1

0

那个算法太慢了,你可以做得更好。

您可以利用每个数字都介于 0 和 20 之间的事实来以线性时间对列进行排序。为此,请使用辅助 20x10 数组,其中 array[i][j] 保存值 i 在原始矩阵的 j 列中出现的次数。对于您的示例,第一列包含值 12、18、13、17、13,因此我们将拥有:

数组[12][0] = 1

数组[13][0] = 2

数组[18][0] = 1

数组[17][0] = 1

对于具有 n 个元素的矩阵,构建此数组需要 O(n) 时间(实际上,问题大小始终相同 - 5*10 = 50)

在构建该数组之后,您现在有两种可能性:

a) 用排好序的列值覆盖原始矩阵。为此,您将进入辅助数组中的每一列 j,并扫描这些值。例如,对于第一列,第一个非零值在array[12][0]中,即1,所以你在原始数组的第一列写“12”,并增加行数,这样您将在正确的位置写入下一个值。然后,您会看到 array[13][0] 为 2,因此您将在原始矩阵中写入两次“13”。您继续为每一列执行此操作。现在您有了一个带有已排序列的矩阵,您可以将您的方法应用于列之间的字典排序。

b)由于您想要列之间的字典顺序,您可以看到这相当于按列的累积总和值对列进行排序。因此,您可以存储另一个包含 10 个元素的数组,其中每个元素都是一个结构,其中包含数组 [0..20][j] 和位置 j 的累积和(请注意,对于位置 i,数组 [i][ j]*i 是总和的实际值)。对这个 10 元素数组进行排序非常快,现在您所要做的就是遍历这个排序后的数组。对于该数组中的每个位置,您使用原始索引 j(之前存储在结构中)来索引 array[0][j],然后使用 a) 中描述的方法覆盖原始矩阵。这样做的好处是您根本不需要编写任何排序程序,您可以使用您的系统 qsort。

此解决方案适用于可接受的值。对于具有 N 个元素的矩阵,构建辅助数组和累积和数组需要 O(N)。对累积和数组进行排序所花费的时间与列数成正比,而覆盖原始数组需要 O(N) 时间。

请注意,此算法足够快,但对于非常大的值,它可能会消耗大量内存。您可能想考虑是否可以通过增加运行时间来减少内存使用量。

至于您发布的代码,它非常不完整,请尝试为我们提供一些更完善的东西。

于 2013-09-19T10:24:38.993 回答