Estrutura de Dados Algoritmos de Ordenação Prof. Othon M. N. Batista Mestre em Informática
Roteiro Introdução Ordenação por Inserção Insertion Sort Ordenação por Seleção Selection Sort Ordenação por Bolha Bubble Sort Ordenação por Mistura Merge Sort Ordenação por Árvore Heap Sort Ordenação Rápida Quick Sort
Introdução Como ordenam-se dois números??? Simples! Basta compará-los e saber qual é o maior ou menor e colocá-los na ordem desejada. Trecho de código em C: num1 = 100; num2 = 200; if (num1 > num2) maior = num1; else maior = num2; printf( Maior: %d\nmenor: %d\n, maior, menor);
Introdução E se forem três números para ordenar??? Já não é tão simples! A quantidade de comparações aumenta... Trecho de código em C: num1 = 100; num2 = 200; num3 = 150; if (num1 >= num2 && num1 >= num3) {maior1 = num1; if (num2 > num3) {maior2 = num2; maior3 = num3;} else {maior2 = num3; maior3 = num2;}}...
Introdução Continuando o raciocínio para vários números, não é viável testar um contra os outros desta forma! Portanto, precisamos de algoritmos que, dados vários valores que admitem ordem em uma estrutura linear (como um vetor), ordene-os o mais rápido possível. Como ordenar a lista de números: 200, 324, 123, 12, 1, 4, 6, 789, 34, 2345, 324, 100?
Ordenação por Inserção Insertion Sort Jogadores de baralho sabem ordenar as cartas ao recebê-las: a primeira carta está ordenada; com todas as outras: procure do fim para o início uma carta maior do que a recebida; mova todas as menores uma posição para cima; insira a nova carta.
Ordenação por Inserção Insertion Sort Cartas na mão: Carta nove de ouro recebida. Procure do fim para o início uma carta maior: Mova as cartas menores para a direita: Insira a carta recebida no local.
Ordenação por Inserção Insertion Sort Complexidade: para cada carta: procurar O(n) mover para cima O(n) inserir O(1) Para n cartas O(n2 )
Ordenação por Inserção Insertion Sort Trecho de código em C. O elemento a inserir está na última posição do vetor: void insertion_sort (int A[], int tamanho) { int i, k, elemento; for (k = 0; k < tamanho; ++ k) { elemento = A[k]; i = k 1; } } while ((i >= 0) && (A[i] > elemento)) { A [i + 1] = A [i]; i = i 1; A [i + 1] = elemento; }
Ordenação por Seleção Selection Sort A ordenação por seleção faz com que o menor (ou o maior) valor passe para a primeira posição, o segundo menor para a segunda posição, e assim sucessivamente... A complexidade do algoritmo no pior caso é de O(n 2 ).
Exemplo: Ordenação por Seleção Selection Sort Passo 1 (1 ao 5): 29 26 2 13 17 Menor = 2 Troca com 29! Passo 2 (2 ao 5): 2 26 29 13 17 Menor = 13 Troca com 26! Passo 3 (3 ao 5): 2 13 29 26 17 Menor = 17 Troca com 29! Passo 4 (4 ao 5): 2 13 17 26 29 Menor = 26 Troca com 26! Fim Vetor Ordenado 2 13 17 26 29
Ordenação por Seleção Selection Sort Trecho de código em C: void selection_sort(int num[], int tam) { int i, j, min; for (i = 0; i < (tam-1); i++) { min = i; for (j = (i+1); j < tam; j++) { if(num[j] < num[min]) { min = j; } } if (i!= min) { int swap = num[i]; num[i] = num[min]; num[min] = swap; } } }
Ordenação por Bolha Bubble Sort Um dos mais simples algoritmos de ordenação. Ler várias vezes os elementos de uma lista e a cada lida passar para o topo o maior (menor) elemento. Parece com as bolhas subindo em um reservatório de água. A complexidade do algoritmo é O(n2 ).
Exemplo: Ordenação por Bolha Bubble Sort Passo 1 (até 4): Passo 2 (até 3): 29 26 2 13 17 29 > 26 Troca! 26 29 2 13 17 29 > 2 Troca! 26 2 29 13 17 29 > 13 Troca! 26 2 13 29 17 29 > 17 Troca! 26 2 13 17 29 26 > 2 Troca! 2 26 13 17 29 26 > 13 Troca! 2 13 26 17 29 26 > 17 Troca! Continua...
Ordenação por Bolha Bubble Sort Passo 3 (até 2): Passo 4 (até 1): 2 13 17 26 29 2 < 13 Não troca! 2 13 17 26 29 13 < 17 Não troca! 2 13 17 26 29 2 < 13 Não troca! Fim Vetor Ordenado 2 13 17 26 29
Ordenação por Bolha Bubble Sort Código em C: void bubblesort (int *primeiro, int *ultimo) { bool naotrocou; int *posatual; for (; ultimo > primeiro; --ultimo) { naotrocou = true; for (posatual = primeiro; posatual < ultimo; ++posatual) { if (*posatual > *(posatual+1)) { troca (posatual, posatual+1); naotrocou = false; } } if (naotrocou) return; } }
Ordenação por Mistura Merge Sort O algoritmo de ordenação por mistura pertence a classe dividir e conquistar. Ele é um algoritmo recursivo composto por três partes: DIVIDIR: dividir a lista em duas partes; CONQUISTAR: ordenar cada parte com o algoritmo; COMBINAR: juntar as parte em uma lista ordenada. A complexidade do algoritmo é O(nlog 2 n).
Ordenação por Mistura Merge Sort Exemplo: 12 33 11 2 25 54 10 4 12 33 11 2 25 54 10 4 DIVIDIR 12 33 11 2 25 54 10 4 12 33 2 11 25 54 4 10 ORDENAR Continua...
Exemplo: Ordenação por Mistura Merge Sort 12 33 2 11 25 54 4 10 2 11 12 33 4 10 25 54 COMBINAR 2 4 10 11 12 25 33 54 Vetor Ordenado
Ordenação por Mistura Merge Sort Código em C: void mergesort(int vetor[], int tamanho) { int meio; } if (tamanho > 1) { meio = tamanho / 2; mergesort(vetor, meio); mergesort(vetor + meio, tamanho - meio); merge(vetor, tamanho); } A dificuldade deste algoritmo está em desenvolver uma função para misturar os dados já ordenados. Isso é um dos exercícios para você!!! J
Ordenação por Árvore Heap Sort A ordenação por árvore utiliza uma árvore binária com propriedades diferenciadas (heap) para ordenar os dados. Os elementos são ordenados na inserção, obedecendo uma das duas propriedades: heap máximo: que leva a uma ordenação crescente; heap mínimo: que leva a uma ordena decrescente. Após as inserções, eles podem ser removidos da árvore na ordem desejada.
Ordenação por Árvore Heap Sort A árvore que obedece o heap máximo tem o maior elemento na raiz. A árvore que obedece o heap mínimo tem o menor elemento na raiz. A complexidade do algoritmo é de O(nlog 2 n). O algoritmo pode utilizar um vetor para representar a árvore.
Ordenação Rápida Quick Sort Algoritmo de ordenação descoberto por C. A.R. Hoare em 1962. Mais um exemplo da técnica de programação denominada dividir e conquistar. O algoritmo divide-se em duas fases: partição: divide o trabalho pela metade (nem sempre); ordenação: ordena as metades.
Ordenação Rápida Quick Sort A complexidade divide-se em: particionamento: O(n) dividir os dados no meio: O(log2n) Total: O(n log n) A mesma que a ordenação em árvore!
Ordenação Rápida Quick Sort A partição consiste em descobrir um pivô de forma que quando comparados com ele: os elementos à esqueda do pivô sejam menores; os elementos à direita do pivô sejam maiores. elementos < pivô pivô elementos > pivô
Ordenação Rápida Quick Sort A ordenação consiste em recursivamente aplicar a partição e a ordenação em ambas as partes. pivô pivô pivô
Ordenação Rápida Quick Sort O algoritmo é recursivo, simples e intuitivo: quicksort (void *a, int inicio, int fim) { int pivo; /* Condição de término! */ if ( fim > inicio ) { pivo = particiona (a, inicio, fim); quicksort (a, inicio, pivo - 1); quicksort( a, pivo + 1, maior); } } Dividir Conquistar
Ordenação Rápida Quick Sort int particiona( int *a, int inicio, int fim ) { int esquerda, direita; int pivo_item, pivo_indice; pivo_item = a[inicio]; pivo_indice = esquerda = inicio; direita = fim; while ( esquerda < direita ) { /* Vai para a esquerda enquanto item < pivo */ while( a[esquerda] <= pivo_item) esquerda ++; /* Vai para a direita enquanto item > pivo */ while( a[direita] >= pivo_item) direita --; if ( esquerda < direita ) Troca(a, esquerda, direita); } /* direita e a posicao final do pivo */ a[inicio] = a[direita]; a[direita] = pivo_item; return direita; }
Ordenação Rápida Quick Sort Qualquer item pode ser o pivô. Neste caso foi escolhido o mais à esquerda. Início Fim
Ordenação Rápida Quick Sort Marcadores de direita e esquerda Esquerda Direita Início Pivô = 23 Fim
Ordenação Rápida Quick Sort Mover esquerda e direita até que se cruzem. Esquerda Direita Início Pivô = 23 Fim
Ordenação Rápida Quick Sort Mover esquerda até encontrar itens <= pivô Idem para a direita com itens >= pivô Esquerda Direita Início Pivô = 23 Fim
Ordenação Rápida Quick Sort Trocar os itens no lado errado do pivô Esquerda Direita Início Pivô = 23 Fim
Ordenação Rápida Quick Sort Esquerda passou da direita. Fim do laço. Direita Esquerda Início Pivô = 23 Fim
Ordenação Rápida Quick Sort Troca o pivô com posição direita atual. Direita Esquerda Início Pivô = 23 Fim
Ordenação Rápida Quick Sort Retorna direita como a nova posição do pivô. Direita Início Pivô = 23 Fim
Ordenação Rápida Quick Sort Pivô Pivô = 23 Direita Ordena a esquerda recursivamente... Ordena a direita recursivamente...