Classificação de séries de classificação por algoritmo de bolha e teste de desempenho

Primeiro, olhe para o tipo de bolha

Os algoritmos de classificação são frequentemente usados ​​como uma prática introdutória para o aprendizado de algoritmos, e a classificação por bolhas é o mais simples deles. Nosso tópico hoje é classificação por bolhas. Sua ideia básica é tão simples quanto um peixe soprando bolhas.


Imagine que há um peixe na parte inferior da matriz. A cada rodada, ele cuspiu uma bolha. A bolha irá flutuar de uma extremidade da matriz para a outra. Durante o processo de flutuação, a bolha irá capturar a maior parte do matriz a ser classificada. Mova-o para o topo e, em seguida, remova este elemento da parte da matriz a ser classificada .

Na próxima rodada, escolha o maior dos elementos restantes a serem classificados e use bolhas para colocá-lo no topo novamente. Desta forma, após n rodadas de bolhas. Descendo do topo da matriz, o maior elemento, o segundo maior elemento e o terceiro maior elemento estão em ordem. A matriz inteira está ordenada. Claro, se você quiser inverter a ordem, escolha o menor elemento em cada rodada . Apenas absorva isso.

O processo de uma rodada de borbulhamento consiste em encontrar o maior elemento na rodada de borbulhamento, comparando e trocando constantemente dois elementos adjacentes e movendo-o para o topo.


O processo específico é imaginar um ponteiro, e o elemento apontado pelo ponteiro é chamado de elemento atual . O ponteiro primeiro aponta para o primeiro elemento e compara o tamanho entre o elemento atual e o próximo elemento. Se o elemento atual for maior do que o próximo elemento, o elemento atual e o próximo elemento são trocados. E mova o ponteiro uma posição para trás, continue a comparar com o próximo elemento, até o último elemento. Desta forma, a primeira rodada de borbulhamento é concluída. Após a primeira rodada de borbulhamento, o elemento na extrema direita é o maior. Na segunda rodada de borbulhamento, partindo do primeiro elemento, a comparação e a troca são realizadas em sequência, e a comparação continua até o penúltimo elemento. No final da segunda rodada, o penúltimo elemento à direita é o segundo maior ... Após N rodadas de borbulhamento, toda a matriz é ordenada do pequeno ao grande

O diagrama é o seguinte

Suponha que você vá classificar a seguinte matriz

Primeiro borbulhar

O ponteiro aponta para o primeiro elemento primeiro, compara o elemento atual com o próximo elemento e descobre que 9 é maior que 5 e, em seguida, troca os dois

O ponteiro volta um lugar

Continue a comparar o tamanho do elemento atual e o próximo elemento, descubra que 9 é maior que 7, troque-o

O ponteiro continua a se mover um pouco para trás, continua a comparar e trocar e, finalmente, 9 é borbulhado para a extrema direita e a primeira rodada da bolha termina

A segunda rodada de borbulhamento começa, coloque o ponteiro no primeiro elemento e comece a repetir o processo da primeira rodada (observe que a segunda rodada só precisa borbulhar da penúltima posição, porque após cada rodada, o mais à direita O comprimento da sequência ordenada na lateral será 1 bit mais)

Se for verificado que 5 é menor que 7, ele não é trocado. Ponteiro se move para trás

Descobriu que 7 é maior que 3, troque

Ponteiro se move para trás

Verifica-se que 7 é maior que 1, e a troca ... Finalmente, 8 é borbulhado para a extrema direita

Continue para a terceira rodada, 7 é borbulhado na extrema direita

Na quarta rodada, 6 atinge a extrema direita

Finalmente, toda a matriz é ordenada

De acordo com essa ideia, escreva o código da seguinte maneira

public void bubbleSort(int[] array) {
    
    
	for (int i = array.length - 1; i >= 0; i--) {
    
    
		for (int j = 0; j < i; j++) {
    
    
			if (array[j] > array[j + 1]) {
    
    
				swap(array, j , j + 1);
			}
		}
	}
}
public void swap(int[] array,int i,int j) {
    
    
    int temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}

O loop externo começa na última posição da matriz e representa a posição final de cada rodada (a primeira rodada de bolhas para na última posição, a segunda rodada de bolhas para na penúltima posição e assim por diante). O loop interno é uma rodada de borbulhamento. Cada rodada de borbulhamento começa na primeira posição, se compara sequencialmente e troca com a próxima posição e prossegue para a posição de parada da rodada de borbulhamento. Claro, o código acima grava apenas a realização da parte central e não é perfeito. Por exemplo, no bubbleSortmétodo, você deve primeiro determinar se a arrayvariável é null, e no swapmétodo, você deve determinar arrayse é nulle verificar se a isoma jestá fora dos limites.

Ideias de otimização

Ideia Um

Na verdade, há espaço para otimização na implementação do tipo de bolha acima. Por exemplo, se não houver troca de elemento em uma determinada rodada de borbulhamento. Isso significa que a matriz já está ordenada como um todo e não há necessidade de rodadas de bolhas subsequentes. Modificar o código, pouco antes do início de cada borbulhante rodada, adicione uma variável de sinalizador boolean boolean sorted = true, enquanto o borbulhar rodada elemento de comutação ocorreu, será sortedvariável para false. Portanto, uma vez que após o final de cada rodada de borbulhamento, adicione um julgamento lógico, se o julgamento sortedfor true, o término antecipado do tipo, escreva o código abaixo.

public void bubbleSortV1(int[] array) {
    
    
    boolean sorted;
	for (int i = array.length - 1; i >= 0; i--) {
    
    
        sorted = true;
		for (int j = 0; j < i; j++) {
    
    
			if (array[j] > array[j + 1]) {
    
    
				swap(array, j , j + 1);
                sorted = false;
			}
		}
        if(sorted) {
    
    
            break;
        }
	}
}

Ideia dois

Se o acima for a otimização com uma granularidade maior (otimização global para o ciclo externo, todo o processo termina mais cedo quando as condições são satisfeitas), ainda há espaço para otimização com uma granularidade menor (otimização durante cada rodada de borbulhamento). Na implementação original, após cada rodada de borbulhamento, o comprimento da sequência ordenada mais à direita é incrementado em um. Ou seja, a primeira rodada de borbulhamento precisa ser trocada e comparada até a última posição; a segunda rodada de borbulhamento precisa ser trocada e comparada até a penúltima posição ... No entanto, cada rodada de borbulhamento precisa apenas fazer as bolhas flutuarem para uma sequência ordenada O limite pode ser encerrado e podemos decidir a posição de parada da próxima rodada de borbulhamento de acordo com a situação real de cada rodada. Em vez de ter que alcançar uma posição fixa de parada a cada rodada.

Por exemplo, a seguinte matriz

Após a primeira rodada de borbulhamento, a matriz torna-se

A última vez que as posições foram trocadas foram as posições 3 e 4. Depois disso, elas foram apenas comparadas e não trocadas , indicando que as posições após 4 eram todas sequências ordenadas. Então, a posição final da segunda rodada de bubbling não precisa ser a penúltima posição, mas só pode ir para a posição da última troca que ocorreu na rodada anterior de bubbling (à direita da posição onde ocorreu a última troca ocorrido, ou seja, há Sequência). Ou seja, para cada rodada de borbulhamento, uma nova variável para registrar a posição onde ocorreu a última troca é adicionada para indicar a posição final da próxima rodada de borbulhamento. Escreva o código da seguinte maneira

public void bubbleSortV2(int[] array) {
    
    
	boolean sorted;
	int sortedSequenceBorder = array.length - 1;
	while (true) {
    
    
		sorted = true;
		int lastSwapPos = 0;
		for (int i = 0 ; i < sortedSequenceBorder; i++) {
    
    
			if (array[i] > array[i + 1]) {
    
    
				swap(array, i, i + 1);
				sorted = false;
				lastSwapPos = i;
			}
		}
		if (sorted) {
    
    
			break;
		}
		sortedSequenceBorder = lastSwapPos;
	}
}

Observe que não importa o quão otimizado, o número de trocas de elementos para classificação por bolha permanece inalterado, as medidas de otimização reduzem apenas o número de comparações desnecessárias. Os exemplos a seguir são fornecidos e você pode verificar por si mesmo

Teste de performance

Em tese, devido à introdução de medidas de otimização para os dois últimos, a eficiência deveria ser superior à da versão não otimizada, ou seja, a eficiência deveria ser

bubbleSortV2 > bubbleSortV1 > bubbleSort

No entanto, em testes reais, verifica-se que às vezes esse não é o caso, porque as medidas de otimização adicionam julgamentos adicionais durante cada rodada de borbulhamento, o que requer uma certa quantidade de desempenho, e se a matriz for classificada, use medidas de otimização reduzir o desempenho de comparação inútil O custo é menor que o custo de desempenho causado pela introdução de julgamentos adicionais, ou seja, quando o benefício é menor que o custo, o desempenho de V1 e V2 não precisa necessariamente ser maior que a versão não otimizada (e também precisa considerar a situação real da máquina de tempo de execução). No entanto, quando o tamanho do array é grande, as medidas de otimização podem reduzir mais o número de comparações e o benefício é maior, e o desempenho será melhor do que a versão não otimizada.

A seguir está um teste de desempenho para as três versões de classificação por bolha. O teste usa uma matriz gerada aleatoriamente, o tamanho da matriz varia de 100, 400, 700 ... a 14800 (o tamanho da matriz começa em 100 e o tamanho aumenta sequencialmente em 300, um total de 50 conjuntos de matrizes são testados ) Para evitar os fatores de influência da máquina em tempo de execução, o teste é repetido 20 vezes para cada grupo de arrays, e o desempenho médio é obtido. O gráfico de linha de desempenho desenhado é o seguinte

Pode ser visto que conforme o tamanho do array aumenta, o desempenho da versão otimizada é significativamente melhor do que a versão não otimizada e o desempenho da versão V2 é ligeiramente melhor do que o da V1

Expandir

Além disso, existe uma variante da classificação borbulhante chamada classificação coquetel . Sua ideia é o borbulhamento bidirecional. As rodadas ímpares vão da esquerda para a direita, e o maior elemento é borbulhado na extrema direita, e as rodadas pares são da direita para a esquerda. O menor elemento borbulha na extremidade esquerda. A classificação do coquetel é solicitada no meio da matriz e, quando as duas extremidades estão fora de ordem, é possível melhorar o desempenho. A seguir está sua implementação de código, muito semelhante à classificação por bolha

	public void cockTailSort(int[] array) {
    
    
		boolean moveRight = true;
		int rightBorder = array.length - 1;
		int leftBorder = 0;
		boolean sorted = false;
		while (!sorted) {
    
    
			sorted = true;
			if (moveRight) {
    
    
				for (int i = leftBorder; i < rightBorder; i++) {
    
    
					if (array[i] > array[i + 1]) {
    
    
						swap(array, i, i + 1);
						sorted = false;
					}
				}
				rightBorder--;
				moveRight = false;
			} else {
    
    
				for (int i = rightBorder; i > leftBorder; i--) {
    
    
					if (array[i] < array[i - 1]) {
    
    
						swap(array, i, i - 1);
						sorted = false;
					}
				}
				leftBorder++;
				moveRight = true;
			}
		}
	}

Incorpore a classificação de coquetéis ao teste de desempenho para ver como ele se compara à classificação normal de bolhas

Pode-se ver que o desempenho da seleção de coquetéis é ligeiramente melhor do que a seleção normal de bolhas

Acho que você gosta

Origin blog.csdn.net/vcj1009784814/article/details/109000707
Recomendado
Clasificación