选择排序模式

时间:2015-03-23 01:23:45

标签: loops sorting design-patterns for-loop selection

我收到了以下代码:

#include <stdio.h>
#include <stdlib.h> 
int ordsel[4][4]={ {3,10,12,7},
                   {33,22,13,21},
                   {15,6,3,30},
                   {16,20,27,2}};
void imprimir()
{
    for (int k=0;k<4;k++)
    {
        for (int m=0;m<4;m++)
          printf("%d\t",ordsel[k][m]);
      printf("\n");
    }    
}

void ordenar()
{
    int cmenor, aux, ia, fmenor;

    for (int k = 0 ; k < 4 ; k++)
    {
        for (int m = 0 ; m < 4 ; m++)
        {
            fmenor=k;
            cmenor=m;
            ia=m;

            for (int i=k;i<4;i++)
            {
                for (int j=ia;j<4;j++)
                {
                   if (ordsel[i][j]<ordsel[fmenor][cmenor])
                   {
                        cmenor=j;
                        fmenor=i;
                   }
                } 

                ia = 0;
            }
         } 

         aux = ordsel[k][m];
         ordsel[k][m] = ordsel[fmenor][cmenor];
         ordsel[fmenor][cmenor] = aux;
      }
}

// Pregunta 3 Parcial III 1415-1
main()
{
printf("Programa que Ordenada una Matriz 4 x 4 por el Metodo Selectivo\n");
printf("\n");
printf("\n       MATRIZ INICIAL\n");
imprimir();
printf("\n");
ordenar(); 
printf("      MATRIZ ORDENADA\n");
imprimir();
printf("\n");
system("pause");
}

SelectionSort

我很难找到任何关于这种排序方法如何工作的模式。如果有人能解释,我会很感激。另外,有没有办法只使用2个“for”循环?我认为主要的问题是我无法绕过3“for”循环来导航Matrix。谢谢。

1 个答案:

答案 0 :(得分:1)

典型的选择排序适用于1维(即1D)阵列。您发布的代码只使用相同的排序原则对2D数组(即矩阵)进行排序。

我将首先解释Selection Sort如何在1D数组上工作,然后扩展它以解释代码如何在2D数组上工作。

选择排序

选择排序通过循环N元素阵列A中的每个元素来工作。在迭代i,其中0 <= i <1。 N,它找到最小的元素 在A [i]和A [N-1]之间(即,从索引i开始),​​并将该元素交换为A [i]。

当i = 0时,算法将最小元素交换为A [0],当i = 1时,它将第二个最小元素交换为A [1](因为最小元素已经在A [0]中,它是从A [1]搜索到A [N-1])。对i = 0到N-1执行此操作将对A进行排序。

void selection_sort(int A[], int N)
{
    // Loop over each element.
    for (int i = 0; i < N; i++)
    {
        // At each iteration, put the next smallest element
        // into the correct position.

        // Find the smallest element from A[i] onwards
        int min_element_index = i;
        for (int j = i + 1; j < N; j++)
        {
            if (A[j] < A[min_element_index])
                min_element_index = j;
        }

        // Swap the smallest element between A[i] and A[N-1] into A[i]
        int tmp = A[i];
        A[i] = A[min_element_index];
        A[min_element_index] = tmp;
    }
}

您可以看到此算法如何工作的可视化here

选择排序(2D情况)

您的代码基本上执行以下操作:

1)循环遍历矩阵中的每个元素ordsel [k] [m]:

  for (int k=0;k<4;k++)
        for (int m=0;m<4;m++)
        {

这对应于1D情况下的最外层循环(上图)。

2)在上面的嵌套循环中,考虑元素ordsel [k] [m],它从ordsel [k] [m]开始找到最小的元素:

    fmenor=k;  // Row index of the smallest element
    cmenor=m;  // Col index of the smallest element
    ia=m;      // Starting position of the col index
    for (int i=k;i<4;i++)
    {
        for (int j=ia;j<4;j++) // Start at col ia := m.
        {
            if (ordsel[i][j]<ordsel[fmenor][cmenor])
            {
                cmenor=j;
                fmenor=i;
            }
        }

        ia=0;  // Reset col index to first col when we move to next row

这对应于1D情况下的内环(上图)。

选择排序(2D)使用2 for for循环

这里的技巧是将4 x 4 2D阵列视为16个元素的1D阵列。这减少了上述1D分拣案例的问题。但是为了使事情有效,我们必须能够使用循环遍历&#34; 1D&#34;来计算此2D数组中的行和col索引。视图的数组。

2D数组ordsel可以被视为:

int A[] = {3, 10, 12, 7, 33, 22, 13, 21, 15, 6, 3, 30, 16, 20, 27, 2}

现在A[0] == ordsel[0][0]A[1] == ordsel[0][1],...

特别是A[5] == ordsel[1][0]A[6] == ordsel[1][2]A[7] == ordsel[1][3],...,A[15] == ordsel[3][3]

请注意,您可以从ordsel[k][m]的索引计算A[j]的行和列索引,如下所示:

int k = j / NUM_COLS;  // Row index
int m = j % NUM_COLS;  // Col index

我们使用整数截断来舍入j和模数运算符%来计算列索引。

int NUM_ROWS = 4;
int NUM_COLS = 4;
void selection_sort_2D()
{
    // Loop over 2D array as a 1D array
    for (int i = 0; i < NUM_ROWS * NUM_COLS; i++)
    {
        // The trick is to compute the row and col indices
        // from the index i.
        int cur_row = i / NUM_COLS;  // Index of current row
        int cur_col = i % NUM_COLS;  // and col

        int min_row_idx = cur_row;
        int min_col_idx = cur_col;
        for (int j = i; j < NUM_ROWS * NUM_COLS; j++)
        {
            // Similar to how we compute cur_row, cur_col
            int k = j / NUM_COLS;  // Row index
            int m = j % NUM_COLS;  // Col index
            if (ordsel[k][m] < ordsel[min_row_idx][min_col_idx])
            {
                min_row_idx = k;
                min_col_idx = m;
            }
        }

        // Swap
        int tmp = ordsel[cur_row][cur_col];
        ordsel[cur_row][cur_col] = ordsel[min_row_idx][min_col_idx];
        ordsel[min_row_idx][min_col_idx] = tmp;
    }
}