Tarea tipo burbuja


130

En clase estamos haciendo algoritmos de clasificación y, aunque los entiendo bien cuando hablo de ellos y escribo pseudocódigo, tengo problemas para escribir código real para ellos.

Este es mi intento en Python:

mylist = [12, 5, 13, 8, 9, 65]

def bubble(badList):
    length = len(badList) - 1
    unsorted = True

    while unsorted:
        for element in range(0,length):
            unsorted = False
            if badList[element] > badList[element + 1]:
                hold = badList[element + 1]
                badList[element + 1] = badList[element]
                badList[element] = hold
                print badList
            else:
                unsorted = True

print bubble(mylist)

Ahora, esto (por lo que puedo decir) se ordena correctamente, pero una vez que termina, se repite indefinidamente.

¿Cómo se puede corregir este código para que la función finalice correctamente y clasifique correctamente una lista de cualquier tamaño (razonable)?

PD: Sé que realmente no debería tener impresiones en una función y debería tener una devolución, pero aún no lo he hecho ya que mi código aún no funciona.


29
@KM - ¿Debería sacar tu césped?
Aiden Bell

123
La publicación es esencialmente: "Tengo problemas para codificar, esto es lo que hice, no funciona". Obviamente hay un implícito "¿Alguien puede darme algunos consejos por favor?" A diferencia de muchas preguntas de tarea, esta (a) está bien escrita, (b) es sincera acerca de ser tarea, y (c) incluye un buen intento de resolver el problema. No creo que la falta de un signo de interrogación real disminuya demasiado ...
John Fouhy

36
La clasificación de burbujas se utiliza como herramienta de aprendizaje porque es el algoritmo de clasificación más fácil de entender para la mayoría de las personas. Es un buen punto de entrada para aprender sobre la clasificación y los algoritmos en general. Si solo enseñáramos cosas que la gente realmente usaría, la discusión sobre la clasificación comenzaría y terminaría con "usar la rutina de clasificación de la biblioteca".
Bill the Lizard

38
Esta pregunta es un póster de cómo hacer una buena pregunta de "tarea". Para el punto de John Fouhy, hay un ejemplo de código, está bien escrito y el póster está tratando de facilitarnos la ayuda. Bien hecho, joshhunt.
Jarret Hardie

20
La clasificación de burbujas no es un algoritmo de clasificación fácil de entender para las personas. Tanto por mi propia experiencia como por mi experiencia en la enseñanza, puedo decir con confianza que la ordenación por inserción, la ordenación por selección, la ordenación mínima (clasificación de elementos mínimos), incluso (para algunos estudiantes) la combinación y la clasificación rápida son más fáciles de entender; después de todo, corresponden a algo formas naturales de ordenar una lista, pero la clasificación de burbujas es simplemente artificial. Además, la ordenación de burbujas es propensa a muchos errores fuera de uno y errores de bucle infinito, como esta pregunta aquí. Como dice Knuth, "el tipo de burbuja parece no tener nada que recomendar, excepto un nombre pegadizo ..."
ShreevatsaR

Respuestas:


127

Para explicar por qué su script no funciona en este momento, cambiaré el nombre de la variable unsortedasorted .

Al principio, tu lista aún no está ordenada. Por supuesto, nos pusimos sortedaFalse .

Tan pronto como comenzamos el whileciclo, asumimos que la lista ya está ordenada. La idea es esta: en cuanto encontramos dos elementos que no están en el orden correcto, volvemos sorteda False. solosorted permanecerá True si no hay elementos en el orden incorrecto .

sorted = False  # We haven't started sorting yet

while not sorted:
    sorted = True  # Assume the list is now sorted
    for element in range(0, length):
        if badList[element] > badList[element + 1]:
            sorted = False  # We found two elements in the wrong order
            hold = badList[element + 1]
            badList[element + 1] = badList[element]
            badList[element] = hold
    # We went through the whole list. At this point, if there were no elements
    # in the wrong order, sorted is still True. Otherwise, it's false, and the
    # while loop executes again.

También hay pequeños problemas menores que ayudarían a que el código sea más eficiente o legible.

  • En el forciclo, usas la variable element. Técnicamente, elementno es un elemento; Es un número que representa un índice de lista. Además, es bastante largo. En estos casos, simplemente use un nombre de variable temporal, como i"index".

    for i in range(0, length):
  • El rangecomando también puede tomar solo un argumento (llamado stop). En ese caso, obtienes una lista de todos los enteros de 0 a ese argumento.

    for i in range(length):
  • La Guía de estilo de Python recomienda que las variables se nombren en minúsculas con guiones bajos. Este es un pequeño detalle para un pequeño guión como este; es más para acostumbrarte a lo que el código de Python se parece más a menudo.

    def bubble(bad_list):
  • Para intercambiar los valores de dos variables, escríbalas como una asignación de tupla. El lado derecho se evalúa como una tupla (por ejemplo, (badList[i+1], badList[i])es (3, 5)) y luego se asigna a las dos variables en el lado izquierdo ( (badList[i], badList[i+1])).

    bad_list[i], bad_list[i+1] = bad_list[i+1], bad_list[i]

Póngalo todo junto y obtendrá esto:

my_list = [12, 5, 13, 8, 9, 65]

def bubble(bad_list):
    length = len(bad_list) - 1
    sorted = False

    while not sorted:
        sorted = True
        for i in range(length):
            if bad_list[i] > bad_list[i+1]:
                sorted = False
                bad_list[i], bad_list[i+1] = bad_list[i+1], bad_list[i]

bubble(my_list)
print my_list

(Por cierto, también eliminé tu declaración impresa).


1
Solo en ese último fragmento de código, bubble no devuelve nada, por lo que el resultado final es que se imprime 'None'. Probablemente quieras devolver la lista o hacer bubble (my_list) y luego imprimir my_list.
Tung Nguyen

9
+1 consejo bien estructurado y claro. Es genial verte guiar al lector por lo que hiciste y por qué en lugar de solo escribir una solución rápida.
Tom Leys

1
Soy un programador de C #, así que esto podría deberse a que no obtengo Python, pero ¿no necesitas algo en el bucle while para restar 1 de la longitud para obtener un algoritmo normal de clasificación de burbujas?
Martin Brown

20
Esta es una implementación ingenua (pero no incorrecta) de Bubble Sort. Después de cada iteración del whilebucle, el elemento más grande "aparece" al final de la lista. Como tal, después de una iteración, el último elemento está definitivamente en el lugar correcto (y no se moverá por iteraciones sucesivas). Al restar 1 de la longitud, está optimizando el algoritmo al ordenar solo la sublista que aún no está ordenada (los length-nelementos más avanzados de la lista). Elegí omitir esta optimización, ya que es más una optimización que una parte vital del algoritmo.
Wesley

2
Put it all together, and you get this:... bueno, te perdiste este:The range command can also take just one argument (named stop).
Peter Perháč

10

El objetivo de la clasificación de burbujas es mover los elementos más pesados en la parte inferior en cada ronda, mientras se mueven los elementos más ligeros hacia arriba. En el bucle interno, donde compara los elementos, no tiene que iterar la lista completa en cada turno . El más pesado ya está colocado en último lugar. La variable intercambiada es una verificación adicional para que podamos marcar que la lista ahora está ordenada y evitar continuar con cálculos innecesarios.

def bubble(badList):
    length = len(badList)
    for i in range(0,length):
        swapped = False
        for element in range(0, length-i-1):
            if badList[element] > badList[element + 1]:
                hold = badList[element + 1]
                badList[element + 1] = badList[element]
                badList[element] = hold
                swapped = True
        if not swapped: break

    return badList

Su versión 1, corregida:

def bubble(badList):
    length = len(badList) - 1
    unsorted = True
    while unsorted:
        unsorted = False
        for element in range(0,length):
            #unsorted = False
            if badList[element] > badList[element + 1]:
                 hold = badList[element + 1]
                 badList[element + 1] = badList[element]
                 badList[element] = hold
                 unsorted = True
                 #print badList
             #else:
                 #unsorted = True

     return badList

8

Esto es lo que sucede cuando usa un nombre de variable de significado negativo, necesita invertir sus valores. Lo siguiente sería más fácil de entender:

sorted = False
while not sorted:
    ...

Por otro lado, la lógica del algoritmo está un poco apagada. Debe verificar si dos elementos se intercambiaron durante el ciclo for. Así es como lo escribiría:

def bubble(values):
    length = len(values) - 1
    sorted = False
    while not sorted:
        sorted = True
        for element in range(0,length):
            if values[element] > values[element + 1]:
                 hold = values[element + 1]
                 values[element + 1] = values[element]
                 values[element] = hold
                 sorted = False
    return values

1
Es un poco malo que no haya un botón "INCORRECTO" que pueda presionar para obtener esta respuesta. Creo que esta pregunta y las respuestas, y especialmente la votación, deben presentarse la próxima vez que Joel Spolsky hable sobre lo bien que ha sintonizado las interacciones sociales en stackoverflow.
Daniel Martin

@Daniel: puedes hacer lo que otras personas con suficiente reputación (100) pueden hacer: rechazar la respuesta incorrecta. Hay un germen de verdad: las condiciones negadas consagradas en las variables de bandera son malas. Sin embargo, no es toda la respuesta: creo que @McWafflestix tiene razón.
Jonathan Leffler

2
Ustedes tienen razón, respondí prematuramente sobre esto. Lo siento por eso.
Martin Cote

2
@ Martin - y debo señalar que estoy más sorprendido / sorprendido por la votación que por la respuesta. El sistema de reputación lo alienta a obtener esa primera respuesta de inmediato. La parte rota es cómo se vota una respuesta incorrecta.
Daniel Martin

2
Sospecho que la mayoría de la gente vota sin entender realmente la pregunta en primer lugar (al igual que la forma en que respondí la pregunta). OTOH, la persona que hace la pregunta tiene el privilegio de elegir la respuesta "correcta" después.
Martin Cote

7

Su uso de la variable sin clasificar es incorrecto; desea tener una variable que le indique si ha intercambiado dos elementos; Si lo ha hecho, puede salir de su bucle, de lo contrario, debe volver a hacerlo. Para arreglar lo que tiene aquí, simplemente ponga "unsorted = false" en el cuerpo de su caso if; retire su caso más; y pon "unsorted = true antes de tu forciclo.


5
def bubble_sort(l):
    for passes_left in range(len(l)-1, 0, -1):
        for index in range(passes_left):
            if l[index] < l[index + 1]:
               l[index], l[index + 1] = l[index + 1], l[index]
    return l

1
Creo que la pregunta era más similar a "¿Cómo se puede solucionar este código?", No "¿cuál es su tipo de burbuja?"
Josh Hunt

44
tienes toda la razón, pero hacerlo de la manera correcta es más importante
mtasic85

66
Es cierto, quizás, mtasico ... pero cualquier cosa etiquetada como tarea se modifica más instructivamente en lugar de reescribirse (especialmente cuando el OP la etiqueta como tarea).
Jarret Hardie

1
Esta es una reescritura perfecta del libro de texto C burbuja que la mayoría de la gente estudia. Yo escribí lo mismo.
Lakshman Prasad

2
agregar buena información es útil en mi opinión. tan buena respuesta ... pensé que podrías usar flag para romper lo antes posible.
Grijesh Chauhan

3

# Una función muy simple, se puede optimizar (obviamente) disminuyendo el espacio del problema de la segunda matriz. Pero la misma complejidad O (n ^ 2).

def bubble(arr):
    l = len(arr)        
    for a in range(l):
        for b in range(l-1):
            if (arr[a] < arr[b]):
            arr[a], arr[b] = arr[b], arr[a]
    return arr 

Es un poco menos complicado con la forma en que puede intercambiar valores en Python: arr[a], arr[b] = arr[b], arr[a]
Makoto

1

Tienes un par de errores allí. El primero es de longitud y el segundo está en el uso de sin clasificar (como lo indica McWafflestix). Probablemente también desee devolver la lista si va a imprimirla:

mylist = [12, 5, 13, 8, 9, 65]

def bubble(badList):
    length = len(badList) - 2
    unsorted = True

    while unsorted:
        for element in range(0,length):
            unsorted = False

            if badList[element] > badList[element + 1]:
                hold = badList[element + 1]
                badList[element + 1] = badList[element]
                badList[element] = hold
                print badList
                unsorted = True

    return badList

print bubble(mylist)

eta: Tienes razón, lo anterior está lleno de errores como el infierno. Mi mal por no probar a través de algunos ejemplos más.

def bubble2(badList):
    swapped = True
    length = len(badList) - 2

    while swapped:
        swapped = False
        for i in range(0, length):
            if badList[i] > badList[i + 1]:

                # swap
                hold = badList[i + 1]
                badList[i + 1] = badList[i]
                badList[i] = hold

                swapped = True

    return badList

¿No debería "unsorted = False" estar fuera del ciclo for?
Svante

Tuvo algunos problemas más que eso;)
Trevor Oke

1

Soy un principiante fresco, comencé a leer sobre Python ayer. Inspirado por tu ejemplo, creé algo tal vez más en el estilo de los 80 lazos, pero de todos modos funciona

lista1 = [12, 5, 13, 8, 9, 65]

i=0
while i < len(lista1)-1:
    if lista1[i] > lista1[i+1]:
        x = lista1[i]
        lista1[i] = lista1[i+1]
        lista1[i+1] = x
        i=0
        continue
    else:
        i+=1

print(lista1)

1

El problema con el algoritmo original es que si tuviera un número más bajo en la lista, no lo colocaría en la posición ordenada correcta. El programa debe volver al principio cada vez para asegurarse de que los números se ordenen por completo.

Simplifiqué el código y ahora funcionará para cualquier lista de números, independientemente de la lista e incluso si hay números repetidos. Aquí está el código

mylist = [9, 8, 5, 4, 12, 1, 7, 5, 2]
print mylist

def bubble(badList):
    length = len(badList) - 1
    element = 0
    while element < length:
        if badList[element] > badList[element + 1]:
            hold = badList[element + 1]
            badList[element + 1] = badList[element]
            badList[element] = hold
            element = 0
            print badList
        else:
            element = element + 1

print bubble(mylist)

1
def bubble_sort(l):
    exchanged = True
    iteration = 0
    n = len(l)

    while(exchanged):
        iteration += 1
        exchanged = False

        # Move the largest element to the end of the list
        for i in range(n-1):
            if l[i] > l[i+1]:
                exchanged = True
                l[i], l[i+1] = l[i+1], l[i]
        n -= 1   # Largest element already towards the end

    print 'Iterations: %s' %(iteration)
    return l

1
Burbuja elemento más grande hasta el final. Y disminuya el contador final, "n" para que no tenga que compararlo nuevamente. Continúe con el ciclo while siempre que haya intercambios. Peor caso: O (N ^ 2) Mejor caso: O (N)
Zile Rehman

1
def bubbleSort(alist):
if len(alist) <= 1:
    return alist
for i in range(0,len(alist)):
   print "i is :%d",i
   for j in range(0,i):
      print "j is:%d",j
      print "alist[i] is :%d, alist[j] is :%d"%(alist[i],alist[j])
      if alist[i] > alist[j]:
         alist[i],alist[j] = alist[j],alist[i]
return alist

alist = [54,26,93,17,77,31,44,55,20, -23, -34,16,11,11,11]

print bubbleSort (lista)


Sangra correctamente la muestra de código: esto es, por supuesto, especialmente importante en Python. Es posible que también desee explicar por qué vale la pena considerar su solución teniendo en cuenta que también hay una respuesta con 100 votos
kdopen

1
def bubble_sort(a):
    t = 0
    sorted = False # sorted = False because we have not began to sort
    while not sorted:
    sorted = True # Assume sorted = True first, it will switch only there is any change
        for key in range(1,len(a)):
            if a[key-1] > a[key]:
                sorted = False
                t = a[key-1]; a[key-1] = a[key]; a[key] = t;
    print a

1

Un ejemplo más simple:

a = len(alist)-1
while a > 0:
    for b in range(0,a):
        #compare with the adjacent element
        if alist[b]>=alist[b+1]:
            #swap both elements
            alist[b], alist[b+1] = alist[b+1], alist[b]
    a-=1

Esto simplemente toma los elementos de 0 a a (básicamente, todos los elementos sin clasificar en esa ronda) y lo compara con su elemento adyacente, y realiza un intercambio si es mayor que su elemento adyacente. Al final de la ronda, se ordena el último elemento y el proceso se ejecuta nuevamente sin él, hasta que se hayan ordenado todos los elementos.

No hay necesidad de una condición, ya sortsea ​​verdadera o no.

Tenga en cuenta que este algoritmo toma en consideración la posición de los números solo cuando se intercambia, por lo que los números repetidos no lo afectarán.

PD. Sé que ha pasado mucho tiempo desde que se publicó esta pregunta, pero solo quería compartir esta idea.


1
arr = [5,4,3,1,6,8,10,9] # array not sorted

for i in range(len(arr)):
    for j in range(i, len(arr)):
        if(arr[i] > arr[j]):
            arr[i], arr[j] = arr[j], arr[i]

            print (arr)

0
def bubble_sort(li):
    l = len(li)
    tmp = None
    sorted_l = sorted(li)
    while (li != sorted_l):
        for ele in range(0,l-1):
            if li[ele] > li[ele+1]:
                tmp = li[ele+1]
                li[ele+1] = li [ele]
                li[ele] = tmp
    return li

0
def bubbleSort ( arr ):
    swapped = True 
    length = len ( arr )
    j = 0

    while swapped:
        swapped = False
        j += 1 
        for i in range ( length  - j ):
            if arr [ i ] > arr [ i + 1 ]:
                # swap
                tmp = arr [ i ]
                arr [ i ] = arr [ i + 1]
                arr [ i + 1 ] = tmp 

                swapped = True

if __name__ == '__main__':
    # test list
    a = [ 67, 45, 39, -1, -5, -44 ];

    print ( a )
    bubbleSort ( a )
    print ( a )

0
def bubblesort(array):
    for i in range(len(array)-1):
        for j in range(len(array)-1-i):
            if array[j] > array[j+1]:
                array[j], array[j+1] = array[j+1], array[j]
    return(array)

print(bubblesort([3,1,6,2,5,4]))

1
Si bien este código puede responder la pregunta, proporcionar un contexto adicional con respecto a cómo y / o por qué resuelve el problema mejoraría el valor a largo plazo de la respuesta.
Alexander

0

Considero agregar mi solución porque alguna solución aquí es tener

  1. mayor tiempo
  2. mayor complejidad espacial
  3. o haciendo demasiadas operaciones

entonces es debería ser

Entonces, aquí está mi solución:


def countInversions(arr):
    count = 0
    n = len(arr)
    for i in range(n):
        _count = count
        for j in range(0, n - i - 1):
            if arr[j] > arr[j + 1]:
                count += 1
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
        if _count == count:
            break
    return count

0

Si alguien está interesado en una implementación más corta utilizando una lista de comprensión:

def bubble_sort(lst: list) -> None:
    [swap_items(lst, i, i+1) for left in range(len(lst)-1, 0, -1) for i in range(left) if lst[i] > lst[i+1]]


def swap_items(lst: list, pos1: int, pos2: int) -> None:
    lst[pos1], lst[pos2] = lst[pos2], lst[pos1]

0

Aquí hay una variación diferente del tipo de burbuja sin forbucle. Básicamente estás considerando el lastIndexde arrayy lentamentedecrementing hasta su primer índice de la matriz.

El algorithmcontinuará moviéndose a través de la matriz de esta manera hasta que se realice un pase completo sin que swapsocurra nada .

La burbuja es básicamente Quadratic Time: O(n²)en lo que respecta al rendimiento.

class BubbleSort: 
  def __init__(self, arr):
    self.arr = arr;

  def bubbleSort(self):
    count = 0;
    lastIndex = len(self.arr) - 1;
    
    while(count < lastIndex):
      if(self.arr[count] > self.arr[count + 1]):
        self.swap(count)  
      count = count + 1;

      if(count == lastIndex):
        count = 0;
        lastIndex = lastIndex - 1;   

  def swap(self, count):
    temp = self.arr[count];
    self.arr[count] = self.arr[count + 1];
    self.arr[count + 1] = temp;
    
arr = [9, 1, 5, 3, 8, 2]
p1 = BubbleSort(arr)

print(p1.bubbleSort())

-1

Las respuestas proporcionadas por the-fury y Martin Cote solucionaron el problema del bucle infinito, pero mi código aún no funcionaría correctamente (para una lista más grande, no se ordenaría correctamente). Terminé abandonando la unsortedvariable y usé un contador en su lugar.

def bubble(badList):
    length = len(badList) - 1
    n = 0
    while n < len(badList):
        for element in range(0,length):
            if badList[element] > badList[element + 1]:
                hold = badList[element + 1]
                badList[element + 1] = badList[element]
                badList[element] = hold
                n = 0
            else:
                n += 1
    return badList

if __name__ == '__main__':
    mylist = [90, 10, 2, 76, 17, 66, 57, 23, 57, 99]
    print bubble(mylist)

Si alguien pudiera proporcionar sugerencias sobre cómo mejorar mi código en los comentarios, sería muy apreciado.


Puede acelerar una clasificación de burbujas omitiendo la parte de su lista que sabe que ya está ordenada (debido a las iteraciones anteriores). Ver en.wikipedia.org/wiki/Bubble_sort#Alternative_implementations
Blorgbeard saldrá

3
de nuevo, todo lo que realmente necesita hacer es usar un booleano (llámelo intacto). declararlo fuera de tu ciclo; bucle hasta no tocado = verdadero. dentro de su ciclo while, establezca intacto como verdadero; en el cuerpo de tu if, establece intacto como falso. Al hacer esto, puede deshacerse de su caso más. de esta manera, si alguna vez cambia dos elementos, su ciclo continuará; si no lo hace, el bucle no lo hará.
Paul Sonier

-1

Prueba esto

a = int(input("Enter Limit"))


val = []

for z in range(0,a):
    b = int(input("Enter Number in List"))
    val.append(b)


for y in range(0,len(val)):
   for x in range(0,len(val)-1):
       if val[x]>val[x+1]:
           t = val[x]
           val[x] = val[x+1]
           val[x+1] = t

print(val)

-1

idk si esto podría ayudarte después de 9 años ... es un simple programa de clasificación de burbujas

    l=[1,6,3,7,5,9,8,2,4,10]

    for i in range(1,len(l)):
        for j in range (i+1,len(l)):
            if l[i]>l[j]:
                l[i],l[j]=l[j],l[i]

-1
def merge_bubble(arr):
    k = len(arr)
    while k>2:
        for i in range(0,k-1):
            for j in range(0,k-1):
                if arr[j] > arr[j+1]:
                    arr[j],arr[j+1] = arr[j+1],arr[j]

        return arr
        break
    else:
        if arr[0] > arr[1]:
            arr[0],arr[1] = arr[1],arr[0]
        return arr 

-1
def bubble_sort(l):
    for i in range(len(l) -1):
        for j in range(len(l)-i-1):
            if l[j] > l[j+1]:
                l[j],l[j+1] = l[j+1], l[j]
    return l

Sería mejor agregar alguna explicación a su código.
Masoud Rahimi

-1
def bubble_sorted(arr:list):
    while True:
        for i in range(0,len(arr)-1):
            count = 0
            if arr[i] > arr[i+1]:
                count += 1
                arr[i], arr[i+1] = arr[i+1], arr[i]
        if count == 0:
            break
    return arr
arr = [30,20,80,40,50,10,60,70,90]
print(bubble_sorted(arr))
#[20, 30, 40, 50, 10, 60, 70, 80, 90]

-3

def bubbleSort(a): def swap(x, y): temp = a[x] a[x] = a[y] a[y] = temp #outer loop for j in range(len(a)): #slicing to the center, inner loop, python style for i in range(j, len(a) - j):
#find the min index and swap if a[i] < a[j]: swap(j, i) #find the max index and swap if a[i] > a[len(a) - j - 1]: swap(len(a) - j - 1, i) return a

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.