Visual Basic Foro
Programación => Visual Basic 6 => Mensaje iniciado por: LeandroA 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 (http://foro.elhacker.net/programacion_vb/obtener_el_id_del_ultimo_directorio_creado-t270580.0.html;msg1326262#msg1326262) para ordenar un array y era muy lento, luego BlackZeroX▓▓▒▒░░ me sugirio este otro método (http://foro.elhacker.net/empty-t272312.0.html) 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 (http://www.leandroascierto.com.ar/foro/index.php?topic=105.msg406#msg406) 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
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.
-
: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
-
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)
-
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
-
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.