Autor Tema: Ordenar un UDT Array  (Leído 3347 veces)

0 Usuarios y 1 Visitante están viendo este tema.

LeandroA

  • Administrador
  • Petabyte
  • *****
  • Mensajes: 1128
  • Reputación: +151/-8
    • Ver Perfil
Ordenar un UDT Array
« en: Abril 08, 2010, 03:54:11 am »
Hola, al fin pude hacer un ordenamiento de un array que sea rápido. voy a tratar de explicar un poco como funciona anteriormente utilizaba un método como este para ordenar un array y era muy lento, luego BlackZeroX▓▓▒▒░░ me sugirio este otro método en donde ya se puede ordenar numericamente, pero sigue siendo lento. asi que decidi intentar de otra forma.

Este método utiliza un array paralelo que almacena los id del array original ordenados correctamente usando esta forma para poder insertar las ubicaciones. para hacer la comparación no recorre todo el array sino que lo va dividiendo en dos hasta encontrar su ubicación mas cercana.

para probar el ejemplo insertar un ListBox , un CommandButton, un CheckBox, y Tres OptionButton con index del 0 al 2
Código: (VB) [Seleccionar]
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Private Declare Function GetTickCount Lib "kernel32.dll" () As Long


Private Type myType
    Name As String
    Birthday As Date
    Age As Long
End Type

Dim m_OrderBy As Integer

Private MT() As myType

Private Sub Command1_Click()
    Dim SortedArray() As Long
    Dim TempMT() As myType
    Dim DescendingOrder As Boolean
    Dim LenMyArray As Long
    Dim i As Long

    Dim t As Long
   
    t = GetTickCount
   
    LenMyArray = UBound(MT)
       
    SortedArray = OrderedArray(LenMyArray)
       
       
    ReDim TempMT(UBound(MT))
   
    DescendingOrder = Check1.Value
   
    If DescendingOrder Then
        For i = 0 To LenMyArray
            TempMT(LenMyArray - i) = MT(SortedArray(i))
        Next
    Else
        For i = 0 To LenMyArray
            TempMT(i) = MT(SortedArray(i))
        Next
    End If
   
    MT = TempMT
   
    MsgBox "Tiempo de ordenado: " & GetTickCount - t
   
    List1.Clear
   

    For i = 0 To LenMyArray
        List1.AddItem MT(i).Name & Space(10) & MT(i).Birthday & Space(10) & MT(i).Age
    Next


End Sub

Private Function OrderedArray(ByVal UBoundArray As Long) As Long()
    Dim Index As Long, i As Long
    Dim Arr() As Long, LenArray As Long, TempArr() As Long
    Dim nInf As Long, nSup As Long, nMid As Long
   
    ReDim Arr(0)

    For Index = 1 To UBoundArray
       
        If GetVar(Arr(UBound(Arr))) <= GetVar(Index) Then
            ReDim Preserve Arr(UBound(Arr) + 1)
            Arr(UBound(Arr)) = Index
        Else
       
            nInf = 0
            nSup = UBound(Arr)
       
            Do
                nMid = (nSup - nInf) \ 2
           
                Do
                    If GetVar(Arr(nMid)) <= GetVar(Index) Then
                        nInf = nMid - 1
                        nMid = nMid + ((nSup - nInf) \ 2)
                    Else
                        nSup = nMid
                        Exit Do
                    End If
                Loop
               
                If nInf < 0 Then nInf = 0: Exit Do
               
               
                If nSup - nInf < 4 Then Exit Do
            Loop
               
       
            For i = nInf To nSup
                If GetVar(Arr(i)) >= GetVar(Index) Then
               
                    LenArray = UBound(Arr) + 1
                   
                    ReDim TempArr(LenArray)
                    If i > 0 Then CopyMemory TempArr(0), Arr(0), 4 * i
                    TempArr(i) = Index
                    CopyMemory TempArr(i + 1), Arr(i), 4 * (LenArray - i)
                    ReDim Arr(LenArray)
                    CopyMemory Arr(0), TempArr(0), 4 * (LenArray + 1)

                    Exit For
                End If
            Next
           
        End If
    Next
   
    OrderedArray = Arr
   
End Function


'Private Function GetVar(ByVal Index As Long) As Variant
'    Dim Value As String
   
'    Value = MT(Index).Caption

'    If IsNumeric(Value) Then
'        GetVar = Val(Value)
'    Else
'        If IsDate(Value) Then
'            GetVar = CDate(Value)
'        Else
'            GetVar = CStr(Value)
'        End If
'    End If
'End Function

Private Function GetVar(ByVal Index As Long) As Variant
    Select Case m_OrderBy
        Case 0
            GetVar = MT(Index).Name
        Case 1
            GetVar = MT(Index).Birthday
        Case 2
            GetVar = MT(Index).Age
    End Select
End Function



Private Sub Form_Load()
    Dim i As Long
   
    ReDim MT(10000)
   
    List1.FontName = "MS Mincho"
   
    Randomize
   
    For i = 0 To 10000
        MT(i).Name = GetRndName
        MT(i).Birthday = GetRandom(CDate("01/01/1930"), CDate("01/01/1995"))
        MT(i).Age = (Date - MT(i).Birthday) / 365
        List1.AddItem MT(i).Name & Space(10) & MT(i).Birthday & Space(10) & MT(i).Age
    Next
   
    Option1(0).Caption = "Nombre": Option1(0).Value = True
    Option1(1).Caption = "Fehca de Nacimiento"
    Option1(2).Caption = "Edad"
    Check1.Caption = "Desendente"
    Command1.Caption = "Ordenar"
End Sub

Private Function GetRndName() As String
    Dim i As Long
    For i = 1 To 6
        GetRndName = GetRndName & Chr(GetRandom(91, 64))
    Next
End Function

Private Function GetRandom(ByVal Lower As Variant, ByVal Upper As Variant) As Variant
    GetRandom = Int((Upper - Lower + 1) * Rnd() + Lower)
End Function

Private Sub Option1_Click(Index As Integer)
    m_OrderBy = Index
End Sub

si quieren usar esta funcion para algun proyecto lo que tienen que modificar es la funcion GetVar esta es la que se encarga de obtener la variable de nuestro UDT o Array.

La función OrderedArray es la que devuelve el array con los index ordenados y bien dentro del evento command1 pueden ver como se utiliza.

Saludos.
« última modificación: Abril 08, 2010, 03:56:41 am por LeandroA »

raul338

  • Terabyte
  • *****
  • Mensajes: 894
  • Reputación: +62/-8
  • xD fan!!!!! xD
    • Ver Perfil
    • Raul's Weblog
Re:Ordenar un UDT Array
« Respuesta #1 en: Abril 08, 2010, 10:13:41 am »
:O Funciona (?), lo que si mas o menos no entendi el codigo, pero segun la tecnica que utiilizas, creo que es usando arboles binarios no? (o algo asi recuerdo que lei en algoritmos :P)


Buen codigo igual, la primera vez hize el list tan corto que no veia la edad y tenia que estar calculando mas o menos la edad que tenian JAAJA

k_arlytos

  • Megabyte
  • ***
  • Mensajes: 210
  • Reputación: +2/-4
    • Ver Perfil
Re:Ordenar un UDT Array
« Respuesta #2 en: Abril 20, 2010, 04:23:50 am »
no se la verdad si es lento o rapido pero yo uso este metod en java para ordenar
es el algoritmo de la Burbuja
la variable "a" es un arrelo de tipo int
public void ordernaarreglo(){
int temp;
          for(int i=0;i<super.a.length;i++){
           for(int j=i+1;j<super.a.length;j++){
               if(super.a[j]<super.a){
                   temp = super.a;
                   super.a = super.a[j];
                   super.a[j] = temp;
               }
           }
          }   
   }
si es de menor a mayor solo cambio el
if(super.a[j]<super.a)
por
if(super.a[j]>super.a)


"Comentar el código es como limpiar el cuarto de baño; nadie quiere hacerlo, pero el resultado es siempre una experiencia más agradable para uno mismo y sus invitados"

raul338

  • Terabyte
  • *****
  • Mensajes: 894
  • Reputación: +62/-8
  • xD fan!!!!! xD
    • Ver Perfil
    • Raul's Weblog
Re:Ordenar un UDT Array
« Respuesta #3 en: Abril 20, 2010, 09:49:20 am »
k_arlytos definitivamente es mas rapido, esto es porque el metodo de la burbuja usa muuuchos bucles, y ordena poco a poco (ya saben, ordena de a dos, de a dos, cuando llega al final vuelve a comprobar ordenando de a 2)

En cambio el metodo de leandro no se como se llama exactamente (era usando arboles binarios, o algo asi xD) pero es mas rapido porque en pocas palabras funciona asi

se fija si al principio esta ordenado (si estan ordenados ni los toca)
a partir de los restantes desordenados (pueden ser todo, porque no) los ordena poniendo los mayores en un extremo y los menores en otro, luego los "junta" con el CopyMemory

Ahora, todo eso ordenando por index, lo cual es mas rapido trabajar con integer que con strings largo (x ej)

Luego tu te encargas de como mostrarlos....

Espero que sea asi, sino corrigeme leandro  ;D ;D

LeandroA

  • Administrador
  • Petabyte
  • *****
  • Mensajes: 1128
  • Reputación: +151/-8
    • Ver Perfil
Re:Ordenar un UDT Array
« Respuesta #4 en: Abril 20, 2010, 04:18:29 pm »
Exacto, en el post principal donde dice "este" hace refecia a un link donde usaba el metodo burbuja y decia que era lento ya que va moviendo la dimencion del array por la dimencion del array y depaso copia todo, tal como dice Raul este va creando un index y luego a la hora de mostrarlo es cuando lo ordena.