Bubble Sort Homework


130

Na aula, estamos desenvolvendo algoritmos de classificação e, embora eu os entenda bem ao falar sobre eles e ao escrever pseudocódigo, estou tendo problemas para escrever o código real para eles.

Esta é a minha tentativa em 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)

Agora, isso (tanto quanto eu posso dizer) classifica corretamente, mas uma vez concluído, ele faz um loop indefinidamente.

Como esse código pode ser corrigido para que a função termine corretamente e classifique corretamente uma lista de qualquer tamanho (razoável)?

PS: Eu sei que realmente não deveria ter impressões em uma função e deveria ter um retorno, mas ainda não o fiz, pois meu código ainda não funciona.


29
@KM - Ele deveria pegar o seu gramado?
Aiden Bell

123
O post é essencialmente: "Estou com problemas para codificar, foi o que fiz, não funciona". Obviamente, existe um implícito "Alguém pode me dar algumas dicas, por favor?" Ao contrário de muitas perguntas sobre trabalhos de casa, esta (a) é bem escrita, (b) é franca quanto à tarefa de casa e (c) inclui uma boa tentativa de resolver o problema. Eu não acho que a falta de um real lhes retirar ponto de interrogação muito grande ..
John Fouhy

36
A classificação por bolha é usada como uma ferramenta de aprendizado porque é o algoritmo de classificação mais fácil para a maioria das pessoas entender. É um bom ponto de entrada para aprender sobre classificação e algoritmos em geral. Se apenas ensinássemos coisas que as pessoas realmente usariam, a discussão sobre classificação começaria e terminaria com "usar a rotina de classificação da biblioteca".
Bill Bill Lizard

38
Esta pergunta é um exemplo de como fazer boas perguntas sobre "trabalhos de casa". Para John Fouhy, há um exemplo de código, está bem escrito, e o pôster está se esforçando para facilitar a ajuda. Muito bem, Joshhunt.
Jarret Hardie

20
A classificação por bolha não é um algoritmo de classificação fácil para as pessoas entenderem. Tanto na minha própria experiência quanto no ensino da experiência, posso dizer com confiança que ordenação por inserção, seleção, min-ordenação (classificação mínima de elementos) e até (para alguns alunos) a fusão e a classificação rápida são mais fáceis de entender - afinal, elas correspondem a algo maneiras naturais de classificar uma lista, mas a classificação por bolhas é apenas artificial. Além disso, a classificação de bolhas é propensa a muitos erros isolados por um e erros de loop infinito, como esta pergunta aqui. Como Knuth diz, "o tipo de bolha parece não ter nada para recomendá-lo, exceto um nome cativante ..."
ShreevatsaR

Respostas:


127

Para explicar por que seu script não está funcionando no momento, vou renomear a variável unsortedpara sorted.

No início, sua lista ainda não está classificada. É claro que começamos sorteda False.

Assim que iniciamos o whileloop, assumimos que a lista já está classificada. A idéia é a seguinte: assim que encontrarmos dois elementos que não estão na ordem correta, sortedvoltamos a False. sortedpermanecerá True apenas se não houver elementos na ordem errada .

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.

Também existem pequenos problemas que ajudariam o código a ser mais eficiente ou legível.

  • No forloop, você usa a variável element. Tecnicamente, elementnão é um elemento; é um número que representa um índice de lista. Além disso, é bastante longo. Nesses casos, basta usar um nome de variável temporário, como ipara "índice".

    for i in range(0, length):
  • O rangecomando também pode receber apenas um argumento (nomeado stop). Nesse caso, você obtém uma lista de todos os números inteiros de 0 a esse argumento.

    for i in range(length):
  • O Guia de Estilo do Python recomenda que as variáveis ​​sejam nomeadas em minúsculas com sublinhados. Este é um detalhe muito pequeno para um pequeno script como este; é mais para você se acostumar com o que o código Python mais se assemelha.

    def bubble(bad_list):
  • Para trocar os valores de duas variáveis, escreva-as como uma atribuição de tupla. O lado direito é avaliado como uma tupla (por exemplo, (badList[i+1], badList[i])é (3, 5)) e, em seguida, é atribuído às duas variáveis ​​no lado esquerdo ( (badList[i], badList[i+1])).

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

Coloque tudo junto e você terá o seguinte:

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

(A propósito, também removi sua declaração impressa.)


1
Apenas nesse último trecho de código, o balão não retorna nada; portanto, o resultado final é que 'Nenhum' é impresso. Você provavelmente deseja retornar a lista ou fazer bolha (my_list) e depois imprimir my_list.
Tung Nguyen

9
+1 conselhos bem estruturados e claros. É ótimo ver você orientar o leitor sobre o que você fez e por que, em vez de apenas escrever uma solução rápida.
Tom Leys

1
Eu sou um programador de C #, então isso pode ser apenas porque eu não entendo o Python, mas você não precisa de algo no loop while para subtrair 1 do comprimento para obter um algoritmo normal de classificação de bolhas?
Martin Brown

20
Esta é uma implementação ingênua (mas não incorreta) do Bubble Sort. Após cada iteração do whileloop, o maior elemento "borbulha" até o final da lista. Assim, após uma iteração, o último elemento está definitivamente no lugar certo (e não será movido por iterações sucessivas). Ao subtrair 1 do comprimento, você está otimizando o algoritmo classificando apenas a sublist que ainda não foi classificada (os length-nelementos mais à frente da lista). Optei por pular essa otimização, pois é mais uma otimização do que uma parte vital do algoritmo.
234 Wesley Wesley

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

10

O objetivo do tipo de bolha é mover os itens mais pesados na parte inferior de cada rodada, enquanto move os itens mais leves para cima. No loop interno, onde você compara os elementos, não precisa repetir a lista inteira a cada turno . O mais pesado já está colocado por último. A variável trocada é uma verificação extra para que possamos marcar que a lista está classificada agora e evitar continuar com cálculos desnecessários.

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

Sua versão 1, corrigida:

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

Isso é o que acontece quando você usa o nome da variável com significado negativo, é necessário inverter seus valores. O seguinte seria mais fácil de entender:

sorted = False
while not sorted:
    ...

Por outro lado, a lógica do algoritmo está um pouco errada. Você precisa verificar se dois elementos foram trocados durante o loop for. Aqui está como eu escreveria:

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
É uma pena que não haja um botão "ERRADO" que eu possa pressionar para esta resposta. Acho que essa pergunta e as respostas - e especialmente a votação - precisam ser apresentadas na próxima vez em que Joel Spolsky fala sobre o quão bem ele ajustou as interações sociais no fluxo de pilha.
303 Daniel Martin

@ Daniel: você pode fazer o que outras pessoas com reputação suficiente (100) podem fazer - reduzir a resposta errada. Existe um germe de verdade - as condições negadas consagradas nas variáveis ​​da flag são ruins. Mas não é a resposta toda - acho que o @McWafflestix está certo.
23611 Jonathan Leffler

2
Vocês estão certos, eu respondi prematuramente neste. Me desculpe por isso.
Martin Cote

2
@ Martin - e devo salientar que estou mais surpreso / chocado com a votação do que a resposta. O sistema de reputação incentiva você a obter a primeira resposta imediatamente. A parte quebrada é como uma resposta incorreta é votada.
307 Daniel Martin

2
Suspeito que a maioria das pessoas vote sem realmente entender a pergunta (exatamente como respondi à pergunta). OTOH, a pessoa que faz a pergunta tem o privilégio de escolher a resposta 'certa' depois.
Martin Cote

7

Seu uso da variável Unsorted está errado; você deseja ter uma variável que informe se você trocou dois elementos; se você tiver feito isso, poderá sair do loop, caso contrário, precisará fazer o loop novamente. Para consertar o que você tem aqui, basta colocar o "unsorted = false" no corpo do seu caso if; remova o seu caso; e coloque "unsorted = true" antes do seu forloop.


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
Eu acredito que a pergunta era mais parecida com 'Como esse código pode ser corrigido', e não 'qual é o seu tipo de bolha?'
21119 Josh Hunt

4
você está absolutamente certo, mas fazê-lo de maneira correta é mais importante
mtasic85

6
É verdade, talvez, mtasic ... mas qualquer coisa marcada como lição de casa é mais instrutivamente aprimorada do que reescrita (especialmente quando é marcada como tarefa pelo OP).
Jarret Hardie

1
Esta é uma reescrita perfeita do tipo de bolha C do livro-texto que a maioria das pessoas estuda. Eu escrevi o mesmo
Lakshman Prasad

2
adicionar boas informações é útil na minha opinião. resposta tão boa .. pensei que você poderia usar sinalizador para quebrar o mais cedo possível.
Grijesh Chauhan

3

#Uma função muito simples, pode ser otimizada (obviamente) diminuindo o espaço problemático da 2ª matriz. Mas a mesma complexidade 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 

É um pouco menos elaborando com a maneira que você pode trocar valores em Python: arr[a], arr[b] = arr[b], arr[a]
Makoto

1

Você tem alguns erros lá. O primeiro tem o comprimento e o segundo está no uso de itens não classificados (conforme declarado por McWafflestix). Você provavelmente também deseja retornar a lista se quiser imprimi-la:

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: Você está certo, o acima é buggy pra caramba. Meu mal por não testar através de mais alguns exemplos.

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

O "unsorted = False" não deveria estar fora do loop for?
Svante 21/05

Ele tinha alguns mais problemas do que isso;)
Trevor Oke

1

Eu sou um novato fresco, comecei a ler sobre Python ontem. Inspirado no seu exemplo, criei algo talvez mais no estilo das 80 gravatas, mas, no entanto, meio que 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

O problema com o algoritmo original é que, se você tivesse um número mais baixo na lista, ele não o levaria à posição correta. O programa precisa voltar no início de cada vez para garantir que os números sejam classificados por todo o caminho.

Simplifiquei o código e agora ele funcionará para qualquer lista de números, independentemente da lista e mesmo se houver números repetidos. Aqui está o 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
Elemento bolha maior até o fim. E diminua o contador final, "n" para que você não precise compará-lo novamente. Continue com o loop while enquanto houver trocas. Pior caso: O (N ^ 2) Melhor 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)


Recue seu exemplo de código corretamente: isso é, obviamente, especialmente importante no Python. Você também pode querer explicar por que sua solução vale a pena considerar considerando há também uma resposta com 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

Um exemplo mais simples:

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

Isso simplesmente leva os elementos de 0 a a (basicamente, todos os elementos não classificados nessa rodada) e o compara com seu elemento adjacente e faz uma troca se for maior que seu elemento adjacente. No final da rodada, o último elemento é classificado e o processo é executado novamente sem ele, até que todos os elementos tenham sido classificados.

Não há necessidade de uma condição se sort verdadeira ou não.

Observe que esse algoritmo leva em consideração a posição dos números somente ao trocar, portanto, números repetidos não o afetam.

PS. Sei que faz muito tempo que essa pergunta foi publicada, mas eu só queria compartilhar essa ideia.


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
Embora esse código possa responder à pergunta, fornecer um contexto adicional sobre como e / ou por que resolve o problema melhoraria o valor a longo prazo da resposta.
Alexander Alexander

0

Eu considero adicionar minha solução, porque cada solução aqui está tendo

  1. maior tempo
  2. maior complexidade de espaço
  3. ou fazendo muitas operações

então é deve ser

Então, aqui está a minha solução:


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

Se alguém estiver interessado em uma implementação mais curta usando uma compreensão de lista:

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

Aqui está uma variação diferente do tipo de bolha sem forloop. Basicamente, você está considerando o lastIndexdo arraye lentamentedecrementing até o primeiro índice da matriz.

O algorithmcontinuará a se mover pela matriz assim até que uma passagem inteira seja feita sem que swapsocorra.

A bolha é tipo é basicamente Quadratic Time: O(n²)quando se trata de desempenho.

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

As respostas fornecidas por the-fury e Martin Cote resolveram o problema do loop infinito, mas meu código ainda não funcionava corretamente (para uma lista maior, ele não seria classificado corretamente). Acabei abandonando a unsortedvariável e usei um contador.

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)

Se alguém puder fornecer dicas sobre como melhorar meu código nos comentários, isso será muito apreciado.


Você pode acelerar uma classificação de bolha ignorando a parte da sua lista que você sabe que já está classificada (devido às iterações anteriores). Veja en.wikipedia.org/wiki/Bubble_sort#Alternative_implementations
Blorgbeard saiu

3
novamente, tudo o que você realmente precisa fazer é usar um booleano (chame de intocado). declare-o fora do seu loop; até intocado = verdadeiro. dentro do seu loop while, configure intocado para ser verdadeiro; no corpo do seu if, defina intocado para ser falso. Fazendo isso, você pode abandonar o seu caso. dessa maneira, se você alternar dois elementos, seu loop continuará; caso contrário, o loop não será.
2119 Paul Sonier

-1

Tente isto

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 se isso pode ajudá-lo após 9 anos ... é um programa simples de classificação de bolhas

    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

Seria melhor adicionar alguma explicação ao seu 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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.