arrayssortingfortranfortran90

Sorting an array from lowest to greatest FORTRAN


So I'm in my first year of the carrer and I've gotten stuck in an assignment, we need to read an array and then give it sorted from lowest to highest, so my approach was to create another array and star giving it the first array's minimum value and go on. Little me I did it, I made a code so that I could read the array's values and assign the lowest to a separate value called minimo. However I'm stuck right there, I can assign that lowest value to the first value of my new sorted array, but when checking again for the lowest value it would of course tell me the same number, so I thought that maybe after giving me the lowest value I could remove it from the original array and check again for the lowest value, but I literally don't know where to start, or even if this is the optimal way to do it, or even a possible one. Here's the code.

PROGRAM hello
IMPLICIT NONE
integer, dimension(1000) :: vector, v_ascendente, v_descendente
integer :: v_size, i, j, minimo = 1000000

print*, "Cuantos numeros introducira"
read*, v_size
print*, "Introduzca los", v_size, "numeros del vector separandolos por ENTER"

do i=1, v_size
    read*, vector(i)
end do

do j=1, v_size
    do i=1, v_size
        minimo = min(minimo, vector(i))
    end do
    print*, "minimo = ", minimo
    v_ascendente(j) = minimo
end do
END PROGRAM

You guys got any idea on another way to do this? Thanks in advance.


Solution

  • Leaving aside for a moment whether or not this is a good way to sort an array let's answer OP's immediate question concerning how to make the chosen approach work. This answer uses the intrinsic routines minval and minloc. In both cases it uses the optional argument mask which governs which elements of an array argument are considered. For a proper explanation of the functions, and of their arguments, see your favourite Fortran documentation.

    First, declare the mask, a logical array of the same size and shape as vector

      LOGICAL, DIMENSION(v_size) :: mk = .TRUE.
    

    Next, repeat the following logic v_size times:

    • find the smallest element in vector which has not been masked off;
    • copy that element to the i-th location in v_ascendente;
    • mask off the location of that smallest element so that it is not considered next time around.

    Which leads to

    DO ix = 1, v_size
       v_ascendente(ix) = MINVAL(vector,mk)
       mk(MINLOC(vector,mk)) = .FALSE.
    END DO
    

    Note that this approach avoids entirely the conceptually problematic, and in practice slow, operation of removing elements from arrays. Yes, I could have demonstrated a code doing that, but it would have made an already slow approach even slower.

    Is this a good sorting method ? Not particularly, but I've seen worse in production code and for short arrays its poor performance won't be noticed. And it is that performance as the size of the array to sort grows which makes this a poor choice for a general-purpose sort routine.

    Which takes us to the issues of computational complexity and of sorting in general, which is just about the most studied problem in computer science and software engineering. And here I agree with the comments made that tackling a wider question such as What is a good sorting method ? takes us way beyond what is acceptable here.