Classificação por inserção vs algoritmos de classificação por bolha


87

Estou tentando entender alguns algoritmos de classificação, mas estou lutando para ver a diferença na classificação por bolha e no algoritmo de classificação por inserção.

Eu sei que ambos são O (n 2 ), mas me parece que a classificação por bolha apenas borbulha o valor máximo da matriz para o topo de cada passagem, enquanto a classificação por inserção apenas afunda o valor mais baixo para baixo a cada passagem. Eles não estão fazendo exatamente a mesma coisa, mas em direções diferentes?

Para classificação por inserção, o número de comparações / trocas potenciais começa em zero e aumenta a cada vez (ou seja, 0, 1, 2, 3, 4, ..., n), mas para classificação por bolha esse mesmo comportamento acontece, mas no final de a classificação (ou seja, n, n-1, n-2, ... 0) porque a classificação por bolha não precisa mais ser comparada com os últimos elementos à medida que são classificados.

Por tudo isso, porém, parece um consenso que o tipo de inserção é melhor em geral. Alguém pode me dizer o porquê?

Edit: Estou interessado principalmente nas diferenças em como os algoritmos funcionam, não tanto em sua eficiência ou complexidade assintótica.


1
Isso está bem documentado em outro lugar: consulte, por exemplo, en.wikipedia.org/wiki/Sorting_algorithm . Bastante inútil para duplicar aqui e uma boa resposta será expansiva.
Bathsheba

@Bathsheba 75 pessoas que votaram positivamente e 88k que viram a pergunta parecem discordar; )
parsecer

@parsecer: Ha! Agora vou ter que revisar as respostas. A resposta mais votada no momento é útil; Não tenho certeza sobre os outros. Aqui está alguns pontos de reputação perdidos por downvoting de resposta. A afirmação "É por isso que a classificação por inserção é mais rápida do que a classificação por bolha" na resposta aceita não é necessariamente verdadeira.
Bathsheba

@Bathsheba Oh não
parsecer

Respostas:


41

Na ordenação por bolha na iª iteração, você tem ni-1 iterações internas (n ^ 2) / 2 no total, mas na ordenação por inserção você tem no máximo i iterações na i'ésima etapa, mas i / 2 em média, já que você pode parar o loop interno antes, depois de encontrar a posição correta para o elemento atual. Então você tem (soma de 0 an) / 2 que é (n ^ 2) / 4 total;

É por isso que a classificação por inserção é mais rápida do que a classificação por bolha.


2
A explicação do algoritmo está na web em todo lugar, eu acho.
sasha.sochka

4
sim, mas parece que o OP ainda não
detecta

15
Bem, você pode supor que eu entendo os fundamentos . O que eu queria era uma comparação, e isso é muito bom. Portanto, a ideia é que, enquanto a classificação por inserção faz com que o iº elemento afunde e a classificação por bolha faz com que ele borbulhe, a classificação por inserção não faz com que caia bem no fundo, apenas faz com que caia na posição correta em a seção já classificada. Assim, faz menos comparações / trocas. Isso está certo?
Migwell

2
O que? "Então você tem (soma de 0 an) / 2 que é (n ^ 2) / 4 total" Isso requer alguma explicação, por favor! 0 + 1 + 2 + 3 + 4 + 5 = 15; 15/2 = 7,5; 7,5 * 4 = 30; sqrt (30) = jargão
John Smith

@JohnSmith Acredito que haja um pequeno erro na resposta. A soma de 1 a n é n * (n + 1) / 2, pois é um número triangular. Procure o número triangular para obter mais explicações. Então, dividido por 2 é apenas n * (n + 1) / 2.
CognizantApe

124

Ordem de inserção

Após i iterações, os primeiros i elementos são ordenados.

Em cada iteração, o próximo elemento é borbulhado pela seção classificada até chegar ao ponto certo:

sorted  | unsorted
1 3 5 8 | 4 6 7 9 2
1 3 4 5 8 | 6 7 9 2

O 4 é borbulhado na seção classificada

Pseudo-código:

for i in 1 to n
    for j in i downto 2
        if array[j - 1] > array[j]
            swap(array[j - 1], array[j])
        else
            break

Tipo de bolha

Após i iterações, os últimos i elementos são os maiores e ordenados.

Em cada iteração, examine a seção não classificada para encontrar o máximo.

unsorted  | biggest
3 1 5 4 2 | 6 7 8 9
1 3 4 2 | 5 6 7 8 9

O 5 é borbulhado da seção não classificada

Pseudo-código:

for i in 1 to n
    for j in 1 to n - i
         if array[j] > array[j + 1]
             swap(array[j], array[j + 1])

Observe que as implementações típicas terminam mais cedo se nenhuma troca for feita durante uma das iterações do loop externo (já que isso significa que a matriz está classificada).

Diferença

Na classificação por inserção, os elementos são borbulhados na seção classificada, enquanto na classificação por bolha os máximos são borbulhados para fora da seção não classificada.


10
Obrigado, isso é muito claro! Acho que a principal coisa que eu precisava destacar é que a instrução break em Insertion Sort significa que ela pode encerrar cada iteração antecipadamente: ou seja, quando encontrar sua posição na seção classificada. A classificação por bolha requer que a troca continue até que o maior elemento na seção não classificada alcance a seção classificada, então nunca terminará antes. É um resumo fantástico, portanto, +1
Migwell

4
Acho que essa deve ser a melhor resposta :)
Adelin

2
Mais 1 pela clareza, pelo valor didático e pelos invariantes do loop principal de cada algoritmo. É uma pena que não contenha explicitamente a comparação da complexidade (expressa em função de n ), de qualquer forma considero uma resposta melhor do que a aceita, pois a partir disso vejo a diferença.
Honza Zidek

Posso perguntar por que você troca seu item em seu Pseudo código de inserção a cada etapa? if (a [j-1]> a [j]) então a [j] = a [j-1] ELSE if (a [j-1] <e && a [j]> e) do que a [j] = e; quebrar; , onde e é o item que precisa ser classificado. Com esta solução, você não troca itens já ordenados, apenas copia-os. Espero sua explicação, já que estou um pouco confuso.
Karoly

@Karoly, escolhi minha versão porque é mais simples. O seu é um pouco mais rápido, é bom que você o indique. Wikipedia descreve ambas as versões.
tomo

16

Outra diferença, não vi aqui:

A classificação por bolha tem 3 atribuições de valor por troca : você deve construir uma variável temporária primeiro para salvar o valor que deseja empurrar para a frente (nº 1), e depois escrever a outra variável de troca no local em que acabou de salvar o valor de (nº 2) e então você tem que escrever sua variável temporária no outro local (nº 3). Você tem que fazer isso para cada local - você deseja avançar - para classificar sua variável no local correto.

Com a ordenação por inserção, você coloca sua variável para ordenar em uma variável temporária e, em seguida, coloca todas as variáveis ​​na frente daquele ponto 1 ponto para trás, contanto que você alcance o ponto correto para sua variável. Isso perfaz 1 atribuição de valor por local . No final, você escreve sua variável temporária no local.

Isso faz com que atribuições de valor muito menos também.

Este não é o maior benefício de velocidade, mas acho que pode ser mencionado.

Espero, me expressei compreensível, se não, desculpe, não sou um nativo da Grã-Bretanha


1
"e, em seguida, colocar todas as variáveis ​​na frente desse ponto 1 ponto para trás" - e isso também não requer uma carga de atribuições para deslocar os dados? (assumindo que os dados são armazenados contiguamente de qualquer maneira, não uma lista vinculada)
Mark K Cowan

@MarkKCowan, sim, é onde a classificação por inserção faz a atribuição por 'ponto', como o usuário acima colocou. Basicamente, a classificação por inserção pode ser escrita com uma atribuição no loop interno, enquanto o bubblesort tem 3 atribuições no loop interno.
JSQuareD

9

A principal vantagem da classificação por inserção é que é um algoritmo online. Você não precisa ter todos os valores no início. Isso pode ser útil ao lidar com dados vindos da rede ou de algum sensor.

Tenho a sensação de que isso seria mais rápido do que outros n log(n)algoritmos convencionais . Porque a complexidade seria, n*(n log(n))por exemplo, ler / armazenar cada valor de stream ( O(n)) e, em seguida, classificar todos os valores ( O(n log(n))) resultando emO(n^2 log(n))

Ao contrário, usar Insert Sort precisa O(n)ler os valores do stream e O(n)colocar o valor no lugar correto, portanto, é o O(n^2)único. Outra vantagem é que você não precisa de buffers para armazenar valores, você os classifica no destino final.


Se estiver tudo bem para uma passagem em ordem dos dados ser algo diferente de simplesmente digitalizar um array, você pode classificar rapidamente com muito mais eficiência. por exemplo, insira elementos em uma árvore binária conforme você os recebe. Isso dá a você O(n log(n))um trabalho total executado para ter uma coleção classificada em cada etapa do caminho. (Um percurso em ordem em qualquer ponto é O(m)). Se você só precisa de um resultado classificado no final, mas deseja sobrepor o cálculo de classificação com o tempo de transferência dos dados, um heap pode ser bom. (E funciona no local, como classificação por inserção).
Peter Cordes

De qualquer forma, nem a classificação por bolha nem por inserção são ideais para isso, com tamanhos de problema grandes o suficiente para que a O(f(n))classe de complexidade importe mais do que detalhes de implementação e fatores constantes.
Peter Cordes

Correção: Uma pilha não é boa para isso. Ele faz a maior parte do trabalho de classificação conforme você remove os elementos em ordem classificada, e é por isso que o cultivo é tão barato. O objetivo aqui é ter a maior parte do trabalho concluído até que o último elemento chegue.
Peter Cordes

De qualquer forma, se você precisa manter um array ordenado para ninserções, então realmente se resume a qual algoritmo é melhor para ordenar um array quase ordenado onde há um elemento não ordenado no topo. Muitos O(n log(n))algoritmos de classificação estão O(n)no caso quase classificado, então não é verdade que você precise sum(M=1..n, O(M * log(M)) )trabalhar. Isso realmente seria O(n^2 log(n)), mas com a escolha certa do algoritmo, eles serão O(n^2)um trabalho total. A classificação por inserção é a mais eficiente para isso.
Peter Cordes

7

O Bubble Sort não está online (ele não pode classificar um fluxo de entradas sem saber quantos itens haverá) porque ele realmente não mantém o controle de um máximo global dos elementos classificados. Quando um item for inserido, você precisará começar a borbulhar desde o início


5

bem a classificação por bolha é melhor do que a classificação por inserção apenas quando alguém está procurando os k principais elementos de uma grande lista de números, ou seja, na classificação por bolha após k iterações você obterá os k principais elementos. No entanto, após k iterações na classificação por inserção, isso apenas garante que esses k elementos sejam classificados.


2

Embora ambas as classificações sejam O (N ^ 2). As constantes ocultas são muito menores na classificação por inserção. As constantes ocultas referem-se ao número real de operações primitivas realizadas.

Quando a classificação por inserção tem melhor tempo de execução?

  1. A matriz está quase classificada - observe que a classificação por inserção faz menos operações neste caso do que a classificação por bolha.
  2. A matriz é de tamanho relativamente pequeno: a classificação por inserção você move os elementos ao redor, para colocar o elemento atual. Isso só é melhor do que a classificação por bolha se o número de elementos for pequeno.

Observe que a classificação por inserção nem sempre é melhor do que a classificação por bolha. Para obter o melhor dos dois mundos, você pode usar a classificação por inserção se o array for pequeno e, provavelmente, mesclar classificação (ou quicksort) para arrays maiores.


2
Se o número de elementos não for pequeno, como a classificação por bolha seria melhor? Meu entendimento é que se você deslizar em IS ou trocar em BS dependeria se o elemento comparado é maior (IS) ou menor (BS) e não no número de elementos. Por favor, me corrija se estiver errado.
Mustafa

1

Número de troca em cada iteração

  • A classificação por inserção faz no máximo 1 troca em cada iteração .
  • A classificação por bolha faz 0 para n trocas em cada iteração.

Acessando e alterando a parte classificada

  • A classificação por inserção acessa (e altera quando necessário) a parte classificada para encontrar a posição correta de um número em consideração.
  • Quando otimizado, o Bubble-sort não acessa o que já está classificado.

Online ou não

  • A classificação por inserção está online. Isso significa que a classificação por inserção recebe uma entrada por vez antes de colocá-la na posição apropriada. Não é necessário apenas comparar adjacent-inputs.
  • O Bubble-sort não está online. Ele não opera uma entrada de cada vez. Ele lida com um grupo de entradas (se não todas) em cada iteração. A classificação por bolha apenas compara e trocaadjacent-inputs em cada iteração.

0

A classificação por bolha é quase inútil em todas as circunstâncias. Em casos de uso, quando a classificação por inserção pode ter muitas trocas, a classificação por seleção pode ser usada porque garante menos de N vezes de troca. Como a classificação por seleção é melhor do que a classificação por bolha, a classificação por bolha não tem casos de uso.


0

classificação de inserção:

1.Na troca de classificação de inserção não é necessária.

2. a complexidade de tempo da classificação por inserção é Ω (n) para o melhor caso e O (n ^ 2) para o pior caso.

3. menos complexo em comparação com o tipo de bolha.

4.exemplo: insira livros na biblioteca, organize os cartões.

tipo de bolha: 1.Swapping necessário no tipo de bolha.

2. a complexidade de tempo da classificação por bolha é Ω (n) para o melhor caso e O (n ^ 2) para o pior caso.

3.mais complexo em comparação com o tipo de inserção.


1
Por que a troca não é necessária? Ele troca elementos para colocar um elemento na posição correta. E eu não diria que esse tipo de bolha é mais complexo.
parsecer

-1

A ordenação por inserção pode ser resumida como " Procure o elemento que deve estar na primeira posição (o mínimo), crie algum espaço deslocando os próximos elementos e coloque-o na primeira posição. Bom. Agora, olhe para o elemento que deve estar na 2ª posição. ... "e assim por diante ...

A classificação por bolha opera de maneira diferente, o que pode ser resumido como " Contanto que eu encontre dois elementos adjacentes que estejam na ordem errada, eu os troco ".


Isso ajuda com a classificação por inserção, mas sua explicação sobre a classificação por bolha não inclui os loops reais, então não posso compará-los. A ordenação por inserção também tem a regra. Desde que eu encontre dois elementos adjacentes que estão na ordem errada, eu os troco , é a maneira como os loops operam que é diferente.
Migwell

3
Não é esse tipo de seleção?
Harold
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.