Rutinas para clasificar un array en memoria

Primera: 7/Ago/97


Incluyo CUATRO rutinas para clasificar un array.
Iba a poner sólo una, la que yo he estado usando durante años, pero me decidí a incluir la que venía con uno de los ejemplos del QuickBasic, creo que esta era la que llaman QuickSort, no he encontrado otro archivo que incluía varias rutinas de clasificación, si algún día las localizo, estarán en los discos de instalación, las pondré para que decidas cual quieres usar.

La rutina que yo he estado usando, realmente no clasifica el Array que contiene los datos, en su lugar lo que hace es clasificar un array de punteros... Estos punteros indican la posición clasificada. De esta forma no se cambia el orden original del array, ya que puede ser que nos interese mantenerlo en la forma original. Este era mi caso y por eso la "adapté".
En la rutina original, tenía una opción para clasificar un archivo... Lo he quitado de este ejemplo, porque no es la parte que interesa. Yo lo utilizaba para el caso de un número grande de datos, ya que la memoria disponible en MS-DOS no era precisamente mucha, sobre todo si el programa tenía unos Trescientos y pico KB

Bueno, vamos al tema.
En el form de ejemplo he incluido 4 botones para las cuatro formas de clasificar.
Realmente son dos, pero con la variante de poder clasificar directamente el array o usar los punteros al array clasificado.

También incluyo un procedimiento para intercambiar valores entre dos variables: SWAP

Sólo voy a incluir el listado de MI rutina, el SWAP y la forma de usarla.
Para ver el ejemplo completo, pulsa en este link (clasif.zip 2.84 KB)

Private Sub Classif(n$(), CL() As Integer, FI As Integer)
    '------------------------------------------------------------
    'Esta rutina está adaptada de una que "copié" de un libro
    'para el Amstrad CPC de Data-Becker
    '
    'Los parámetros:
    'n$() es el array a clasificar
    'CL() aquí se guardan "punteros" a los elementos clasificados
    'FI   es el número de elementos
    '
    'La variable n$() permanece sin clasificar, para acceder a los
    'elementos clasificados habría que hacer esto:
    'For i = 0 to FI
    '   Print i, n$(CL(i))
    'Next
    '
    'Puede que sea muy rebuscado, pero lo hice porque mis arrays
    'deberían permanecer en el mismo orden que estaban originalmente
    '------------------------------------------------------------
    Dim i%, S%, L%, J%, R%, t$

    For i = 1 To FI: CL(i) = i: Next
    If FI < 2 Then Exit Sub             'Nada que clasificar

    ReDim O(30) As Integer, U(30) As Integer
    S = 1
    O(1) = 1
    U(1) = FI

    Do
        L = O(S): R = U(S): S = S - 1
        Do
            i = L: J = R:
            t$ = n$(CL((L + R) / 2))
            If LTrim$(t$) = "" Then t$ = Chr$(255)
            Do
                While (n$(CL(i)) < t$ And i < R): i = i + 1: Wend
                While (n$(CL(J)) > t$ And J > L): J = J - 1: Wend
                If i <= J Then
                    Swap CL(i), CL(J)
                    i = i + 1
                    J = J - 1
                End If
            Loop While i <= J
            If R - i <= J - L Then
                If i < R Then
                    S = S + 1
                    O(S) = i
                    U(S) = R
                End If
                R = J
            Else
                If L < J Then
                    S = S + 1
                    O(S) = L
                    U(S) = J
                End If
                L = i
            End If
        Loop While R > L
    Loop While S > 0
    Erase O, U
End Sub


Private Sub Swap(uno As Variant, dos As Variant)
    'Intercambia dos valores
    Dim tres As Variant

    tres = uno
    uno = dos
    dos = tres
End Sub


Private Sub cmdClassif_Click()
    Dim i As Integer
    Dim t1#, t2#

    MousePointer = vbHourglass

    Label1 = "Un momento..."
    DoEvents

    nItem = List1.ListCount
    ReDim Preserve Nombre(nItem)
    ReDim Orden(0 To nItem) As Integer

    For i = 1 To nItem
        Nombre(i) = List1.List(i - 1)
    Next

    List2.Clear
    t1 = Timer
    Classif Nombre(), Orden(), nItem
    t2 = Timer
    Label1 = "Para " & CStr(nItem) & " elementos= " & Format$(t2 - t1, "###,##0.00") & " seg"
    DoEvents
    For i = 1 To nItem
        List2.AddItem Nombre(Orden(i))
    Next
    MousePointer = vbDefault
End Sub


ir al índice