No Description

sorting.py 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. """
  2. Carlos J Corrada Bravo
  3. Este programa calcula el promedio de tiempo de ejecucion de cuatro algoritmos de ordenamiento
  4. La variable maxValor define el valor maximo de los elementos de la lista
  5. La variable largoLista define el largo de las listas a ordenar
  6. La variable veces define las veces que se va a hacer el ordenamiento
  7. Al final se imprimen los promedios de cada algortimo
  8. """
  9. from random import randint
  10. import time
  11. from copy import deepcopy
  12. import sys
  13. from heapq import heapify, heappush
  14. # This function was created to prevent program from stopping before recursion finished
  15. # Changes python's recursion limit
  16. class recursion_depth:
  17. def __init__(self, limit):
  18. self.limit = limit
  19. self.default_limit = sys.getrecursionlimit()
  20. def __enter__(self):
  21. sys.setrecursionlimit(self.limit)
  22. def __exit__(self, type, value, traceback):
  23. sys.setrecursionlimit(self.default_limit)
  24. # Mergesort algorithm
  25. def mergeSort(lista): # Ángel G. Romero Rosario on 10082022
  26. def merge(l1, l2):
  27. if len(l1) == 0:
  28. return l2
  29. elif len(l2) == 0:
  30. return l1
  31. elif l1[0] < l2[0]:
  32. return l1[0:1] + merge(l1[1:],l2) # If l1[0] < l2[0] save l1[0] first to the list and call the function again
  33. else:
  34. return l2[0:1] + merge(l1, l2[1:]) # If l2[0] < l1[0] save l2[0] first to the list and call the function again
  35. if len(lista) <= 1: # If there are no more items, return lista
  36. return lista
  37. else:
  38. mid = len(lista) // 2 # Find the middle in lista and call function to merge lista
  39. return merge(mergeSort(lista[:mid]), mergeSort(lista[mid:]))
  40. def heapSort(lista):
  41. #definan el algoritmo de ordenamiento heapsort
  42. # Dylan A. Cedres Rivera
  43. # Nuevo heap para insertar los elementos de lista creada con numeros aleatorios
  44. myHeap = []
  45. heapify(myHeap)
  46. # Se copian los elementos de lista al heap y se ordenan de menor a mayor los elementos con cada push.
  47. # Todos los elementos se les asigna un signo contrario al que tienen, para poder crear un MaxHeap, de manera
  48. # que los numeros mas grandes se convierten en los mas pequenos.
  49. # Si se quiere hacer un MinHeap, la instruccion de multiplicar por -1 no es neceseria
  50. for element in lista:
  51. heappush(myHeap, -1 * element)
  52. # print("lista antes de 'heapificar'", lista)
  53. # Este loop se utiliza para crear un MaxHeap, de manera que le devuelve el signo original que tenian los
  54. # elementos antes de que se anadieran al heap.
  55. # Esto significa que los elementos mas pequenos, se convierten en los mas grandes, dejando la forma de un MaxHeap,
  56. # con el numero mas grande quedando como el nodo padre del arbol binario.
  57. # Si se quiere hacer un MinHeap, este loop no se necesita.
  58. for i in range(len(myHeap)):
  59. myHeap[i] = myHeap[i] * -1
  60. # print("lista 'heapificada'", myHeap)
  61. # Copia los elementos del heap ordenado de vuelta a la lista inicialmente generada y la devuelve
  62. lista = myHeap
  63. return lista
  64. return lista
  65. def quickSort(lista):
  66. #definan el algoritmo de ordenamiento quicksort
  67. if(len(lista) != 0):
  68. if(len(lista) == 1):
  69. return lista
  70. else:
  71. p = lista[0]
  72. for i in lista[1:]:
  73. if(p > i):
  74. x = i
  75. del lista[lista.index(i)]
  76. lista.insert(lista.index(p), x)
  77. l = quickSort(lista[ :lista.index(p)])
  78. m = quickSort(lista[lista.index(p) + 1:])
  79. if(m != None and l != None):
  80. return l + lista[lista.index(p):lista.index(p) + 1] + m
  81. elif(m == None):
  82. return l + lista[lista.index(p):lista.index(p) + 1]
  83. elif(l == None):
  84. return lista[lista.index(p):lista.index(p) + 1] + m
  85. # inplace
  86. # complexity: O(N^2)
  87. def shellSort(lst):
  88. # initial gap
  89. gap = len(lst)
  90. while 0 < gap:
  91. # sort every sublist with given gap
  92. for start in range(gap):
  93. f = range(start, len(lst), gap)
  94. s = range(start + gap, len(lst), gap)
  95. # bubble sort on sublist
  96. swapped = True
  97. while swapped:
  98. swapped = False
  99. # iterate through every adjacent pair in sublist
  100. for c, n in zip(f, s):
  101. if lst[n] < lst[c]:
  102. lst[c], lst[n] = lst[n], lst[c]
  103. swapped = True
  104. # reduce gap towards 0
  105. gap = gap // 2
  106. return lst
  107. # timeCode function/thunk -> (duration, return value)
  108. # measures the time it takes for a function/thunk to return
  109. def timeCode(fn):
  110. t1 = time.perf_counter()
  111. res = fn()
  112. duration = time.perf_counter() - t1
  113. return (duration, res)
  114. maxValor = 1000 #define el valor maximo de los elementos de la lista
  115. largoLista = 1000 #define el largo de las listas a ordenar
  116. veces = 100 #define las veces que se va a hacer el ordenamiento
  117. acumulaMerge = 0 #variable para acumular el tiempo de ejecucion del mergesort
  118. acumulaHeap = 0 #variable para acumular el tiempo de ejecucion del heapsort
  119. acumulaQuick = 0 #variable para acumular el tiempo de ejecucion del quicksort
  120. acumulaShell = 0 #variable para acumular el tiempo de ejecucion del shellsort
  121. for i in range(veces):
  122. mergelista = [randint(0,maxValor) for r in range(largoLista)] #creamos una lista con valores al azar
  123. heaplista = deepcopy(mergelista)
  124. quicklista = deepcopy(mergelista)
  125. searchlista = deepcopy(mergelista)
  126. with recursion_depth(1500): # This function excedes python's recursion limit
  127. acumulaMerge += timeCode(lambda: mergeSort(mergelista))[0]
  128. acumulaHeap += timeCode(lambda: heapSort(heaplista))[0]
  129. acumulaQuick += timeCode(lambda: quickSort(quicklista))[0]
  130. acumulaShell += timeCode(lambda: shellSort(searchlista))[0]
  131. #imprimos los resultados
  132. print(f"Promedio de tiempo de ejecucion de {str(veces)} listas de largo {str(largoLista)}")
  133. print(f"MergeSort {str(acumulaMerge / veces)} segundos")
  134. print(f"HeapSort {str(acumulaHeap / veces)} segundos")
  135. print(f"QuickSort {str(acumulaQuick / veces)} segundos")
  136. print(f"ShellSort {str(acumulaShell / veces)} segundos")