DEV Community

Cover image for Entendendo Bubble Sort
Mr Punk da Silva
Mr Punk da Silva

Posted on • Edited on

Entendendo Bubble Sort

O que é Bubble Sort?

O Bubble Sort é um algoritmo de ordenação simples que funciona comparando elementos adjacentes e trocando-os se estiverem na ordem errada. O nome vem do fato de que os elementos menores "borbulham" para o início da lista, assim como bolhas de ar sobem para a superfície da água.

Como funciona?

O algoritmo funciona da seguinte forma:

  1. Compara elementos adjacentes no array
  2. Troca os elementos se estiverem na ordem errada (o maior vai para a direita)
  3. Repete o processo para todos os pares adjacentes
  4. Continua as iterações até que nenhuma troca seja necessária

Diagramação

Configura aqui

https://raw.githubusercontent.com/mrpunkdasilva/learn-sorting-algorithms/d4f220e951a76b8bf0b892b816e461e6053dbdde/Writerside/images/bubbleSort_annotated.png

Exemplo Visual

Considerando o array: [64, 34, 25, 12, 22, 11, 90]

Iteração 1:

  • Compara 64 e 34: 64 > 34 → Troca: [34, 64, 25, 12, 22, 11, 90]
  • Compara 64 e 25: 64 > 25 → Troca: [34, 25, 64, 12, 22, 11, 90]
  • Compara 64 e 12: 64 > 12 → Troca: [34, 25, 12, 64, 22, 11, 90]
  • Compara 64 e 22: 64 > 22 → Troca: [34, 25, 12, 22, 64, 11, 90]
  • Compara 64 e 11: 64 > 11 → Troca: [34, 25, 12, 22, 11, 64, 90]
  • Compara 64 e 90: 64 < 90 → Sem troca: [34, 25, 12, 22, 11, 64, 90]
  • Resultado: O maior elemento (90) está na posição correta

Iteração 2:

  • Compara 34 e 25: 34 > 25 → Troca: [25, 34, 12, 22, 11, 64, 90]
  • Compara 34 e 12: 34 > 12 → Troca: [25, 12, 34, 22, 11, 64, 90]
  • Compara 34 e 22: 34 > 22 → Troca: [25, 12, 22, 34, 11, 64, 90]
  • Compara 34 e 11: 34 > 11 → Troca: [25, 12, 22, 11, 34, 64, 90]
  • Compara 34 e 64: 34 < 64 → Sem troca
  • Resultado: Os dois maiores elementos estão nas posições corretas

Iteração 3:

  • Compara 25 e 12: 25 > 12 → Troca: [12, 25, 22, 11, 34, 64, 90]
  • Compara 25 e 22: 25 > 22 → Troca: [12, 22, 25, 11, 34, 64, 90]
  • Compara 25 e 11: 25 > 11 → Troca: [12, 22, 11, 25, 34, 64, 90]
  • Compara 25 e 34: 25 < 34 → Sem troca

O processo continua até que nenhuma troca seja necessária, resultando em: [11, 12, 22, 25, 34, 64, 90]


Implementação

Nossa implementação educativa inclui saídas detalhadas para ajudar no aprendizado.

Você pode encontrar uma implementação completa e educativa do Bubble Sort em:

- 📁 Domus/Domus-1/bubbleSort.cpp

Função Principal - Bubble Sort Algorithm

void bubbleSortAlgorithm(int dataArray[], int arraySize) { cout << "========================================" << endl; cout << "STARTING BUBBLE SORT ALGORITHM" << endl; cout << "========================================" << endl; cout << "Initial array: "; for(int displayIndex = 0; displayIndex < arraySize; displayIndex++) { cout << dataArray[displayIndex] << " "; } cout << endl << endl; int totalNumberOfSwaps = 0; int totalNumberOfComparisons = 0; bool hasSwapped = true; int iterationCount = 0; while (hasSwapped && iterationCount < arraySize - 1) { iterationCount++; hasSwapped = false; cout << ">>> ITERATION " << iterationCount << " <<<" << endl; cout << "Comparing adjacent elements..." << endl; for (int currentIndex = 0; currentIndex < arraySize - iterationCount; currentIndex++) { int nextIndex = currentIndex + 1; totalNumberOfComparisons++; cout << "Comparing dataArray[" << currentIndex << "] = " << dataArray[currentIndex] << " with dataArray[" << nextIndex << "] = " << dataArray[nextIndex]; if (dataArray[currentIndex] > dataArray[nextIndex]) { cout << " -> " << dataArray[currentIndex] << " > " << dataArray[nextIndex] << ", need to swap!" << endl; swapElements(dataArray, currentIndex, nextIndex); hasSwapped = true; totalNumberOfSwaps++; } else { cout << " -> " << dataArray[currentIndex] << " <= " << dataArray[nextIndex] << ", no swap needed" << endl; } } cout << "Array state after iteration " << iterationCount << ": "; for(int displayIndex = 0; displayIndex < arraySize; displayIndex++) { if (displayIndex >= arraySize - iterationCount) { cout << "[" << dataArray[displayIndex] << "] "; // Already sorted elements } else { cout << dataArray[displayIndex] << " "; // Not yet sorted elements } } cout << endl; cout << "Elements in final position: " << iterationCount << "/" << arraySize << endl; if (!hasSwapped) { cout << "No swaps performed in this iteration - array is sorted!" << endl; } cout << "--------------------------------" << endl; } cout << "========================================" << endl; cout << "BUBBLE SORT ALGORITHM COMPLETED!" << endl; cout << "Total number of iterations: " << iterationCount << endl; cout << "Total number of comparisons: " << totalNumberOfComparisons << endl; cout << "Total number of swaps performed: " << totalNumberOfSwaps << endl; cout << "========================================" << endl; } 
Enter fullscreen mode Exit fullscreen mode

Função para Trocar Elementos

void swapElements(int dataArray[], int firstPosition, int secondPosition) { cout << " -> Swapping elements: " << dataArray[firstPosition] << " (position " << firstPosition << ") <-> " << dataArray[secondPosition] << " (position " << secondPosition << ")" << endl; int temporaryValue = dataArray[firstPosition]; dataArray[firstPosition] = dataArray[secondPosition]; dataArray[secondPosition] = temporaryValue; cout << " -> After swap: position " << firstPosition << " = " << dataArray[firstPosition] << ", position " << secondPosition << " = " << dataArray[secondPosition] << endl; } 
Enter fullscreen mode Exit fullscreen mode

Versão Otimizada do Bubble Sort

void optimizedBubbleSortAlgorithm(int dataArray[], int arraySize) { cout << "========================================" << endl; cout << "STARTING OPTIMIZED BUBBLE SORT ALGORITHM" << endl; cout << "========================================" << endl; int totalNumberOfSwaps = 0; int totalNumberOfComparisons = 0; for (int iteration = 0; iteration < arraySize - 1; iteration++) { bool hasSwapped = false; cout << ">>> ITERATION " << (iteration + 1) << " <<<" << endl; for (int currentIndex = 0; currentIndex < arraySize - iteration - 1; currentIndex++) { totalNumberOfComparisons++; if (dataArray[currentIndex] > dataArray[currentIndex + 1]) { swapElements(dataArray, currentIndex, currentIndex + 1); hasSwapped = true; totalNumberOfSwaps++; } } // Early termination if no swaps occurred if (!hasSwapped) { cout << "No swaps in this iteration - array is already sorted!" << endl; break; } cout << "Array after iteration " << (iteration + 1) << ": "; for(int displayIndex = 0; displayIndex < arraySize; displayIndex++) { cout << dataArray[displayIndex] << " "; } cout << endl << "--------------------------------" << endl; } cout << "Total comparisons: " << totalNumberOfComparisons << endl; cout << "Total swaps: " << totalNumberOfSwaps << endl; } 
Enter fullscreen mode Exit fullscreen mode

Características do Algoritmo

Complexidade de Tempo

  • Melhor caso: O(n) - Array já ordenado (com otimização)
  • Caso médio: O(n²) - Comportamento típico
  • Pior caso: O(n²) - Array ordenado inversamente

Complexidade de Espaço

  • O(1) - Algoritmo in-place, usa apenas memória constante adicional

Propriedades Importantes

Propriedade Valor
Estável ✅ Sim
In-place ✅ Sim
Adaptivo ✅ Sim (com otimização)
Comparações O(n²)
Trocas O(n²)

Por que o Bubble Sort É Estável?

O que significa "Estabilidade" em algoritmos de ordenação?

Um algoritmo de ordenação é estável quando mantém a ordem relativa dos elementos que possuem valores iguais. Ou seja, se dois elementos têm o mesmo valor, aquele que aparece primeiro no array original deve aparecer primeiro no array ordenado.

Exemplo Prático de Estabilidade

Considere um array de cartas onde cada carta tem um valor e um naipe:

Array inicial: [5♠, 3♦, 5♥, 2♣, 3♠]

Vamos ordenar por valor numérico apenas, ignorando o naipe:

✅ Bubble Sort (estável):

[2♣, 3♦, 3♠, 5♠, 5♥]

  • Note que 3♦ vem antes de 3♠ (mantém ordem original)
  • E 5♠ vem antes de 5♥ (mantém ordem original)

Por que o Bubble Sort mantém a estabilidade?

O Bubble Sort mantém a estabilidade porque:

  1. Compara apenas elementos adjacentes
  2. Só troca elementos se o da esquerda for MAIOR que o da direita
  3. Nunca troca elementos iguais

Demonstração com números simples:

Array: [4, 2a, 2b, 1] (onde 2a e 2b têm o mesmo valor, mas origens diferentes)

Iteração 1:

  • Compara 4 e 2a: 4 > 2a → Troca: [2a, 4, 2b, 1]
  • Compara 4 e 2b: 4 > 2b → Troca: [2a, 2b, 4, 1]
  • Compara 4 e 1: 4 > 1 → Troca: [2a, 2b, 1, 4]

Iteração 2:

  • Compara 2a e 2b: 2a == 2bSem troca (preserva ordem!)
  • Compara 2b e 1: 2b > 1 → Troca: [2a, 1, 2b, 4]

Iteração 3:

  • Compara 2a e 1: 2a > 1 → Troca: [1, 2a, 2b, 4]

Resultado final: [1, 2a, 2b, 4] ✅ Ordem original mantida!

Exemplo Prático com Dados Reais

struct Pessoa { string nome; int idade; int numeroChegada; // Para identificar ordem original }; // Array inicial (ordenado por chegada): // 1. João, 25 anos // 2. Maria, 30 anos  // 3. Pedro, 25 anos // 4. Ana, 20 anos // Após Bubble Sort por idade: // 1. Ana, 20 anos // 2. João, 25 anos <- João mantém prioridade sobre Pedro // 3. Pedro, 25 anos <- Pedro vem depois (ordem original preservada) // 4. Maria, 30 anos 
Enter fullscreen mode Exit fullscreen mode

Importância da Estabilidade

A estabilidade é crucial quando:

  • Ordenação múltipla: Primeiro por um campo, depois por outro
  • Preservação de contexto: Manter informações sobre ordem original
  • Interfaces de usuário: Comportamento previsível para o usuário
  • Dados com metadados: Timestamps, IDs, etc.

Comparação com Algoritmos Instáveis

Algoritmo Estável? Motivo
Bubble Sort ✅ Sim Só troca adjacentes se forem diferentes
Selection Sort ❌ Não Troca elementos distantes
Insertion Sort ✅ Sim Insere mantendo ordem
Quick Sort ❌ Não Particionamento pode alterar ordem
Merge Sort ✅ Sim Merge preserva ordem quando iguais

Implementação que Garante Estabilidade

void stableBubbleSort(int arr[], int n) { for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { // CRUCIAL: usar > e não >= if (arr[j] > arr[j + 1]) { // Não troca elementos iguais! swap(arr[j], arr[j + 1]); } } } } 
Enter fullscreen mode Exit fullscreen mode

🔑 Ponto-chave: Use > (maior que) e nunca >= (maior ou igual) na condição de troca para manter a estabilidade!


Vantagens vs. Disvantagens

Vantagens

  • Simples de implementar e entender
  • Estável: Mantém a ordem relativa de elementos iguais
  • In-place: Não requer memória adicional
  • Adaptivo: Com otimização pode detectar arrays já ordenados
  • Funciona bem com arrays pequenos
  • Detecta facilmente se o array já está ordenado

Desvantagens

  • Complexidade O(n²): Ineficiente para arrays grandes
  • Muitas trocas: Pode fazer até O(n²) trocas no pior caso
  • Lento na prática: Mesmo entre algoritmos O(n²)
  • Não recomendado para dados em produção
  • Elementos pequenos "borbulham" lentamente para o início

Quando Usar?

O Bubble Sort é adequado quando:

  • Arrays muito pequenos (< 10 elementos)
  • Estabilidade é crucial (manter ordem relativa de elementos iguais)
  • Detecção de ordenação é importante (pode parar cedo se já ordenado)
  • Fins educacionais (aprender conceitos de ordenação)
  • Simplicidade extrema é mais importante que eficiência
  • Protótipos rápidos onde performance não é crítica

Comparação com Outros Algoritmos

Algoritmo Melhor Caso Caso Médio Pior Caso Estável Trocas
Bubble Sort O(n) O(n²) O(n²) O(n²)
Selection Sort O(n²) O(n²) O(n²) O(n)
Insertion Sort O(n) O(n²) O(n²) O(n²)
Merge Sort O(n log n) O(n log n) O(n log n) -
Quick Sort O(n log n) O(n log n) O(n²) O(n log n)

Variações do Bubble Sort

1. Bubble Sort Otimizado (com Flag)

Adiciona uma flag para detectar quando o array já está ordenado e para antecipadamente.

void optimizedBubbleSort(int arr[], int n) { for (int i = 0; i < n - 1; i++) { bool hasSwapped = false; for (int j = 0; j < n - i - 1; j++) { if (arr[j] > arr[j + 1]) { swap(arr[j], arr[j + 1]); hasSwapped = true; } } // Se não houve trocas, array está ordenado if (!hasSwapped) { break; } } } 
Enter fullscreen mode Exit fullscreen mode

2. Cocktail Sort (Bubble Sort Bidirecional)

Funciona em ambas as direções alternadamente, melhorando a performance em alguns casos.

void cocktailSort(int arr[], int n) { bool hasSwapped = true; int start = 0; int end = n - 1; while (hasSwapped) { hasSwapped = false; // Esquerda para direita for (int i = start; i < end; i++) { if (arr[i] > arr[i + 1]) { swap(arr[i], arr[i + 1]); hasSwapped = true; } } end--; if (!hasSwapped) break; // Direita para esquerda for (int i = end; i > start; i--) { if (arr[i] < arr[i - 1]) { swap(arr[i], arr[i - 1]); hasSwapped = true; } } start++; } } 
Enter fullscreen mode Exit fullscreen mode

3. Bubble Sort Recursivo

Implementação recursiva que "borbulha" o maior elemento e ordena recursivamente o restante.

void recursiveBubbleSort(int arr[], int n) { // Caso base if (n == 1) return; // Uma passada para colocar o maior elemento no final for (int i = 0; i < n - 1; i++) { if (arr[i] > arr[i + 1]) { swap(arr[i], arr[i + 1]); } } // Chama recursivamente para os primeiros n-1 elementos recursiveBubbleSort(arr, n - 1); } 
Enter fullscreen mode Exit fullscreen mode

4. Odd-Even Sort (Brick Sort)

Variação que compara elementos em posições ímpares/pares alternadamente.

void oddEvenSort(int arr[], int n) { bool isSorted = false; while (!isSorted) { isSorted = true; // Compara elementos em posições ímpares for (int i = 1; i <= n - 2; i += 2) { if (arr[i] > arr[i + 1]) { swap(arr[i], arr[i + 1]); isSorted = false; } } // Compara elementos em posições pares for (int i = 0; i <= n - 2; i += 2) { if (arr[i] > arr[i + 1]) { swap(arr[i], arr[i + 1]); isSorted = false; } } } } 
Enter fullscreen mode Exit fullscreen mode

Exercícios Práticos

Exercício 1: Implementação Básica

Implemente o Bubble Sort para ordenar um array de strings por ordem alfabética.

💡 Solução do Exercício 1

#include #include using namespace std; // Função para trocar duas strings void swapStrings(string arr[], int pos1, int pos2) { cout &lt;&lt; " -&gt; Trocando \"" &lt;&lt; arr[pos1] &lt;&lt; "\" com \"" &lt;&lt; arr[pos2] &lt;&lt; "\"" &lt;&lt; endl; string temp = arr[pos1]; arr[pos1] = arr[pos2]; arr[pos2] = temp; } // Bubble Sort para strings void bubbleSortStrings(string arr[], int size) { cout &lt;&lt; "Ordenando strings por ordem alfabética usando Bubble Sort:" &lt;&lt; endl; for (int i = 0; i &lt; size - 1; i++) { cout &lt;&lt; "\n&gt;&gt;&gt; ITERAÇÃO " &lt;&lt; (i + 1) &lt;&lt; " &lt;&lt;&lt;" &lt;&lt; endl; bool hasSwapped = false; for (int j = 0; j &lt; size - i - 1; j++) { cout &lt;&lt; "Comparando \"" &lt;&lt; arr[j] &lt;&lt; "\" com \"" &lt;&lt; arr[j + 1] &lt;&lt; "\""; if (arr[j] &gt; arr[j + 1]) { cout &lt;&lt; " -&gt; \"" &lt;&lt; arr[j] &lt;&lt; "\" &gt; \"" &lt;&lt; arr[j + 1] &lt;&lt; "\", precisa trocar!" &lt;&lt; endl; swapStrings(arr, j, j + 1); hasSwapped = true; } else { cout &lt;&lt; " -&gt; \"" &lt;&lt; arr[j] &lt;&lt; "\" &lt;= \"" &lt;&lt; arr[j + 1] &lt;&lt; "\", sem troca" &lt;&lt; endl; } } cout &lt;&lt; "Array após iteração " &lt;&lt; (i + 1) &lt;&lt; ": "; for (int k = 0; k &lt; size; k++) { if (k &gt;= size - i - 1) { cout &lt;&lt; "[\"" &lt;&lt; arr[k] &lt;&lt; "\"] "; } else { cout &lt;&lt; "\"" &lt;&lt; arr[k] &lt;&lt; "\" "; } } cout &lt;&lt; endl; if (!hasSwapped) { cout &lt;&lt; "Nenhuma troca realizada - array já está ordenado!" &lt;&lt; endl; break; } } } int main() { const int SIZE = 6; string nomes[SIZE] = {"Maria", "João", "Ana", "Pedro", "Carlos", "Beatriz"}; cout &lt;&lt; "Array inicial: "; for (int i = 0; i &lt; SIZE; i++) { cout &lt;&lt; "\"" &lt;&lt; nomes[i] &lt;&lt; "\" "; } cout &lt;&lt; endl &lt;&lt; endl; bubbleSortStrings(nomes, SIZE); cout &lt;&lt; "\n========================================" &lt;&lt; endl; cout &lt;&lt; "RESULTADO FINAL:" &lt;&lt; endl; cout &lt;&lt; "Array ordenado: "; for (int i = 0; i &lt; SIZE; i++) { cout &lt;&lt; "\"" &lt;&lt; nomes[i] &lt;&lt; "\" "; } cout &lt;&lt; endl; cout &lt;&lt; "========================================" &lt;&lt; endl; return 0; } 
Enter fullscreen mode Exit fullscreen mode

Exercício 2: Bubble Sort com Contador de Operações

Modifique o algoritmo Bubble Sort para contar e exibir o número total de comparações e trocas realizadas.

💡 Solução do Exercício 2

#include using namespace std; struct BubbleSortStats { int comparisons; int swaps; int iterations; }; void bubbleSortWithStats(int arr[], int size, BubbleSortStats&amp; stats) { stats.comparisons = 0; stats.swaps = 0; stats.iterations = 0; cout &lt;&lt; "Bubble Sort com estatísticas detalhadas:" &lt;&lt; endl; for (int i = 0; i &lt; size - 1; i++) { stats.iterations++; cout &lt;&lt; "\n&gt;&gt;&gt; ITERAÇÃO " &lt;&lt; stats.iterations &lt;&lt; " &lt;&lt;&lt;" &lt;&lt; endl; bool hasSwapped = false; for (int j = 0; j &lt; size - i - 1; j++) { stats.comparisons++; cout &lt;&lt; "Comparação " &lt;&lt; stats.comparisons &lt;&lt; ": " &lt;&lt; arr[j] &lt;&lt; " vs " &lt;&lt; arr[j + 1]; if (arr[j] &gt; arr[j + 1]) { // Realizar troca int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; stats.swaps++; hasSwapped = true; cout &lt;&lt; " -&gt; Troca " &lt;&lt; stats.swaps &lt;&lt; " realizada!" &lt;&lt; endl; } else { cout &lt;&lt; " -&gt; Sem troca necessária" &lt;&lt; endl; } } cout &lt;&lt; "Array após iteração " &lt;&lt; stats.iterations &lt;&lt; ": "; for (int k = 0; k &lt; size; k++) { cout &lt;&lt; arr[k] &lt;&lt; " "; } cout &lt;&lt; endl; if (!hasSwapped) { cout &lt;&lt; "Otimização: Array já ordenado, parando antecipadamente!" &lt;&lt; endl; break; } } } int main() { int numeros[] = {64, 34, 25, 12, 22, 11, 90}; int tamanho = sizeof(numeros) / sizeof(numeros[0]); BubbleSortStats estatisticas; cout &lt;&lt; "Array inicial: "; for (int i = 0; i &lt; tamanho; i++) { cout &lt;&lt; numeros[i] &lt;&lt; " "; } cout &lt;&lt; endl; bubbleSortWithStats(numeros, tamanho, estatisticas); cout &lt;&lt; "\n========================================" &lt;&lt; endl; cout &lt;&lt; "ESTATÍSTICAS FINAIS:" &lt;&lt; endl; cout &lt;&lt; "Iterações realizadas: " &lt;&lt; estatisticas.iterations &lt;&lt; endl; cout &lt;&lt; "Total de comparações: " &lt;&lt; estatisticas.comparisons &lt;&lt; endl; cout &lt;&lt; "Total de trocas: " &lt;&lt; estatisticas.swaps &lt;&lt; endl; cout &lt;&lt; "Array final: "; for (int i = 0; i &lt; tamanho; i++) { cout &lt;&lt; numeros[i] &lt;&lt; " "; } cout &lt;&lt; endl; cout &lt;&lt; "========================================" &lt;&lt; endl; return 0; } 
Enter fullscreen mode Exit fullscreen mode

Exercício 3: Bubble Sort Bidirecional (Cocktail Sort)

Implemente uma variação do Bubble Sort que funciona nas duas direções.

💡 Solução do Exercício 3

#include using namespace std; void cocktailSort(int arr[], int size) { cout &lt;&lt; "Implementando Cocktail Sort (Bubble Sort Bidirecional):" &lt;&lt; endl; bool hasSwapped = true; int start = 0; int end = size - 1; int iteration = 0; while (hasSwapped) { iteration++; hasSwapped = false; cout &lt;&lt; "\n&gt;&gt;&gt; ITERAÇÃO " &lt;&lt; iteration &lt;&lt; " - DIREÇÃO →" &lt;&lt; endl; // Passada da esquerda para direita for (int i = start; i &lt; end; i++) { cout &lt;&lt; "Comparando " &lt;&lt; arr[i] &lt;&lt; " com " &lt;&lt; arr[i + 1]; if (arr[i] &gt; arr[i + 1]) { swap(arr[i], arr[i + 1]); hasSwapped = true; cout &lt;&lt; " -&gt; Trocado!" &lt;&lt; endl; } else { cout &lt;&lt; " -&gt; Sem troca" &lt;&lt; endl; } } if (!hasSwapped) { break; } end--; cout &lt;&lt; "\n&gt;&gt;&gt; ITERAÇÃO " &lt;&lt; iteration &lt;&lt; " - DIREÇÃO ←" &lt;&lt; endl; // Passada da direita para esquerda for (int i = end; i &gt; start; i--) { cout &lt;&lt; "Comparando " &lt;&lt; arr[i] &lt;&lt; " com " &lt;&lt; arr[i - 1]; if (arr[i] &lt; arr[i - 1]) { swap(arr[i], arr[i - 1]); hasSwapped = true; cout &lt;&lt; " -&gt; Trocado!" &lt;&lt; endl; } else { cout &lt;&lt; " -&gt; Sem troca" &lt;&lt; endl; } } start++; cout &lt;&lt; "Array após iteração " &lt;&lt; iteration &lt;&lt; ": "; for (int j = 0; j &lt; size; j++) { cout &lt;&lt; arr[j] &lt;&lt; " "; } cout &lt;&lt; endl; } } int main() { int numeros[] = {5, 1, 4, 2, 8, 0, 2}; int tamanho = sizeof(numeros) / sizeof(numeros[0]); cout &lt;&lt; "Array inicial: "; for (int i = 0; i &lt; tamanho; i++) { cout &lt;&lt; numeros[i] &lt;&lt; " "; } cout &lt;&lt; endl; cocktailSort(numeros, tamanho); cout &lt;&lt; "\nArray final ordenado: "; for (int i = 0; i &lt; tamanho; i++) { cout &lt;&lt; numeros[i] &lt;&lt; " "; } cout &lt;&lt; endl; return 0; } 
Enter fullscreen mode Exit fullscreen mode

Exercício 4: Análise de Performance

Compare o desempenho do Bubble Sort com e sem otimização de parada antecipada.

🤔 Desafio Extra

Implemente uma versão do Bubble Sort que:

  1. Conta operações (comparações e trocas)
  2. Para automaticamente quando detecta que está ordenado
  3. Mostra estatísticas detalhadas no final
  4. Funciona com diferentes tipos de dados (int, float, string)

🏆 Solução do Desafio Extra

#include <iostream> #include <string> #include <vector> #include <chrono> #include <iomanip> using namespace std; using namespace std::chrono; // Estrutura para armazenar estatísticas de ordenação struct SortingStats { int comparisons = 0; int swaps = 0; int iterations = 0; double timeElapsed = 0.0; bool optimizedExit = false; }; // Template para Bubble Sort genérico com estatísticas template<typename T> void advancedBubbleSort(T arr[], int size, SortingStats& stats) { auto start = high_resolution_clock::now(); cout << "\n========================================" << endl; cout << "ADVANCED BUBBLE SORT WITH STATISTICS" << endl; cout << "========================================" << endl; stats = {0, 0, 0, 0.0, false}; // Reset statistics cout << "Array inicial: "; for (int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl << endl; bool hasSwapped = true; while (hasSwapped && stats.iterations < size - 1) { hasSwapped = false; stats.iterations++; cout << ">>> ITERAÇÃO " << stats.iterations << " <<<" << endl; for (int i = 0; i < size - stats.iterations; i++) { stats.comparisons++; cout << "Comparação " << stats.comparisons << ": " << arr[i] << " vs " << arr[i + 1]; if (arr[i] > arr[i + 1]) { // Realizar troca T temp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = temp; stats.swaps++; hasSwapped = true; cout << " -> Troca " << stats.swaps << " realizada!" << endl; } else { cout << " -> Sem troca necessária" << endl; } } cout << "Estado do array: "; for (int i = 0; i < size; i++) { if (i >= size - stats.iterations) { cout << "[" << arr[i] << "] "; } else { cout << arr[i] << " "; } } cout << endl; if (!hasSwapped) { stats.optimizedExit = true; cout << "🎯 OTIMIZAÇÃO: Array já ordenado! Parando antecipadamente." << endl; } cout << "--------------------------------" << endl; } auto end = high_resolution_clock::now(); auto duration = duration_cast<microseconds>(end - start); stats.timeElapsed = duration.count() / 1000.0; // Convert to milliseconds cout << "\n========================================" << endl; cout << "ESTATÍSTICAS DETALHADAS" << endl; cout << "========================================" << endl; cout << "Elementos no array: " << size << endl; cout << "Iterações realizadas: " << stats.iterations << endl; cout << "Total de comparações: " << stats.comparisons << endl; cout << "Total de trocas: " << stats.swaps << endl; cout << "Tempo de execução: " << fixed << setprecision(3) << stats.timeElapsed << " ms" << endl; cout << "Otimização ativada: " << (stats.optimizedExit ? "✅ Sim" : "❌ Não") << endl; cout << "Eficiência: " << fixed << setprecision(2) << ((double)stats.swaps / stats.comparisons * 100) << "% das comparações resultaram em trocas" << endl; cout << "\nArray final ordenado: "; for (int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl; cout << "========================================" << endl; } // Função para testar com diferentes tipos de dados void testWithIntegers() { cout << "\n🔢 TESTE COM NÚMEROS INTEIROS" << endl; int numeros[] = {64, 34, 25, 12, 22, 11, 90}; int tamanho = sizeof(numeros) / sizeof(numeros[0]); SortingStats stats; advancedBubbleSort(numeros, tamanho, stats); } void testWithFloats() { cout << "\n🔢 TESTE COM NÚMEROS DECIMAIS" << endl; float decimais[] = {3.14f, 2.71f, 1.41f, 1.73f, 0.57f}; int tamanho = sizeof(decimais) / sizeof(decimais[0]); SortingStats stats; advancedBubbleSort(decimais, tamanho, stats); } void testWithStrings() { cout << "\n📝 TESTE COM STRINGS" << endl; string nomes[] = {"Maria", "João", "Ana", "Pedro", "Carlos"}; int tamanho = sizeof(nomes) / sizeof(nomes[0]); SortingStats stats; advancedBubbleSort(nomes, tamanho, stats); } void testWithAlreadySorted() { cout << "\n✅ TESTE COM ARRAY JÁ ORDENADO (Demonstração de Otimização)" << endl; int ordenado[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int tamanho = sizeof(ordenado) / sizeof(ordenado[0]); SortingStats stats; advancedBubbleSort(ordenado, tamanho, stats); } void testWithReverseSorted() { cout << "\n❌ TESTE COM ARRAY INVERSAMENTE ORDENADO (Pior Caso)" << endl; int reverso[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; int tamanho = sizeof(reverso) / sizeof(reverso[0]); SortingStats stats; advancedBubbleSort(reverso, tamanho, stats); } // Função para comparar performance void performanceComparison() { cout << "\n📊 COMPARAÇÃO DE PERFORMANCE" << endl; cout << "=============================" << endl; // Teste com diferentes tamanhos vector<int> sizes = {5, 10, 15}; for (int size : sizes) { cout << "\n🔍 Testando com " << size << " elementos:" << endl; // Criar array aleatório int* arr = new int[size]; for (int i = 0; i < size; i++) { arr[i] = rand() % 100; } SortingStats stats; advancedBubbleSort(arr, size, stats); cout << "Resultado: " << stats.iterations << " iterações, " << stats.comparisons << " comparações, " << stats.swaps << " trocas em " << stats.timeElapsed << " ms" << endl; delete[] arr; } } int main() { cout << "==================================================" << endl; cout << "BUBBLE SORT AVANÇADO - DESAFIO EXTRA COMPLETO" << endl; cout << "==================================================" << endl; // Teste com diferentes tipos de dados testWithIntegers(); testWithFloats(); testWithStrings(); // Testes especiais para demonstrar otimizações testWithAlreadySorted(); testWithReverseSorted(); // Comparação de performance performanceComparison(); cout << "\n🎉 Todos os testes foram concluídos com sucesso!" << endl; cout << "📚 Este exemplo demonstra:" << endl; cout << " ✅ Contagem de operações" << endl; cout << " ✅ Parada antecipada (otimização)" << endl; cout << " ✅ Estatísticas detalhadas" << endl; cout << " ✅ Suporte a diferentes tipos de dados" << endl; cout << " ✅ Medição de tempo de execução" << endl; cout << " ✅ Análise de eficiência" << endl; return 0; } 
Enter fullscreen mode Exit fullscreen mode

Explicação da Solução

Esta solução avançada implementa todos os requisitos do desafio:

1. Contagem de Operações
  • Struct SortingStats armazena comparações, trocas, iterações e tempo
  • Cada operação é contada e exibida em tempo real
2. Parada Antecipada
  • Flag hasSwapped detecta quando não há mais trocas
  • Para automaticamente, economizando iterações desnecessárias
3. Estatísticas Detalhadas
  • Número total de operações realizadas
  • Tempo de execução em milissegundos
  • Percentual de eficiência (trocas/comparações)
  • Indicação se a otimização foi ativada
4. Suporte a Diferentes Tipos
  • Template genérico funciona com int, float, string
  • Testes demonstram funcionamento com cada tipo
5. Recursos Extras
  • Visualização do processo de ordenação
  • Testes com casos especiais (já ordenado, inverso)
  • Comparação de performance com diferentes tamanhos
  • Medição precisa de tempo de execução

Esta implementação é ideal para estudos avançados de algoritmos e análise de performance!


Conclusão

O Bubble Sort é um algoritmo fundamental para aprender os conceitos de ordenação devido à sua simplicidade conceitual e facilidade de implementação. Embora não seja eficiente para arrays grandes, é excelente para fins educacionais e situações específicas onde a estabilidade é crucial.

O algoritmo demonstra claramente os conceitos de:

  • Comparação de elementos adjacentes
  • Algoritmos estáveis vs. instáveis
  • Otimizações algorítmicas (parada antecipada)
  • Análise de complexidade no melhor e pior caso
  • Trade-offs entre simplicidade e eficiência

Quando usar Bubble Sort:

  • Arrays muito pequenos (< 10 elementos)
  • Situações educacionais
  • Quando a estabilidade é essencial
  • Como base para entender algoritmos mais complexos

Top comments (2)

Collapse
 
bruno_freschi_097efd99fd6 profile image
Bruno Freschi

Que post massa, conteúdo muito bom!

Collapse
 
mrpunkdasilva profile image
Mr Punk da Silva • Edited

Obrigado mano

Tenho outros conteúdos se quiser dar uma olhada, espero que tenha sido útil!