400 likes | 490 Views
Programação II. Prof. Mateus Raeder. Transparências baseadas nos originais da profa. Patrícia Jaques. Universidade do Vale do Rio dos Sinos - São Leopoldo -. Classificação de Dados. Classificação. Processo de organizar itens em ordem (de)crescente, segundo algum critério
E N D
Programação II Prof. Mateus Raeder Transparências baseadas nos originais da profa. Patrícia Jaques Universidade do Vale do Rio dos Sinos- São Leopoldo -
Classificação de Dados Programação II – Prof. Mateus Raeder
Classificação • Processo de organizar itens em ordem (de)crescente, segundo algum critério • Também chamado de ordenação • Aplicações de Sorting • Preparação de dados para facilitar pesquisas futuras • Exemplo: dicionários e listas telefônicas • Agrupar itens que apresentam mesmos valores • Para eliminação de elementos repetidos • Batimento entre itens presentes em mais de um arquivo • Para combinação de dados presentes nos vários arquivos • Para consolidação dos vários arquivos em um único Programação II – Prof. Mateus Raeder
Definições • Sejam R1, R2, …, RN , N ítens (chamados registros) • Cada registro Ri, é formado por uma chaveCi e por informações ditas satélites • A ordenação dos registros é feita definindo-se uma relação de ordem “<“ sobre os valores das chaves • O objetivo da ordenação é determinar uma permutação dos índices 1 i1, i2, …, iN N das chaves, tal que Ci1 Ci2 … CiN. • Um conjunto de registros é chamado de arquivo Programação II – Prof. Mateus Raeder
Relação de Ordem • Uma relação de ordem “<“ (leia-se precede) deve satisfazer as seguintes condições para quaisquer valores a, b e c: (i) Uma e somente uma das seguintes possibilidades é verdadeira: a < b, a = b ou b < a (lei da tricotomia) (ii) Se a < b e b < c, então a < c (transitividade) • As propriedades (i) e (ii) definem o conceito de ordem linear ou ordem total Programação II – Prof. Mateus Raeder
Exercício • Escreva um algoritmo para classificar um conjunto de 5 números em ordem crescente. Programação II – Prof. Mateus Raeder
Formas de Representação do Resultado • Reorganização Física • Encadeamento • Vetor Indireto de Ordenação (VIO) Programação II – Prof. Mateus Raeder
chave chave 1 10 1 7 2 19 2 10 3 13 3 12 4 12 4 13 5 7 5 19 (a) antes da classificação (b) após a classificação Reorganização Física Programação II – Prof. Mateus Raeder
cabeça da lista 5 chave 1 10 2 19 3 13 4 12 5 7 Encadeamento chave 1 10 4 2 19 0 3 2 13 4 12 3 5 7 1 (a) antes da classificação (b) após a classificação Programação II – Prof. Mateus Raeder
1 1 7 5 2 2 10 1 3 3 12 4 13 3 4 4 5 5 2 19 Vetor Indireto de Ordenação Chave VIO Chave 10 19 13 12 7 Programação II – Prof. Mateus Raeder
Métodos de Classificação • Classificação por Inserção • Inserção Direta • ShellSort • Classificação por Trocas (permutação) • BubbleSort • QuickSort • Classificação por Seleção • Seleção Direta • HeapSort Programação II – Prof. Mateus Raeder
Classificação por Inserção • A classificação é obtida porque os elementos são inseridos na sua posição correta. • Algoritmos: • Inserção Direta • ShellSort Programação II – Prof. Mateus Raeder
Inserção Direta • Mais simples • Normalmente utilizado para um conjunto pequeno de dados, pois apresenta baixa eficiência • Divide o vetor em 2 segmentos: • o primeiro contendo os elementos já ordenados • o segundo contendo os elementos ainda não ordenados • Funcionamento: Pega o primeiro elemento do segmento não ordenado e procura seu lugar no segmento ordenado. • No início: o 1º segmento terá apenas 1 elemento Programação II – Prof. Mateus Raeder
Inserção Direta 18 15 7 9 23 16 14 Vetor original 18 15 7 9 23 16 14 Divisão inicial Não ordenado Ordenado 15 18 7 9 23 16 14 Primeira iteração 7 15 18 9 23 16 14 Segunda iteração ... Programação II – Prof. Mateus Raeder
Inserção Direta 0 1 2 3 4 5 6 18 15 7 9 23 16 14 public static void insertionSort (int a[]) { for (int i = 1; i < a.length; i++) { int j = i; // pos do 1º elemento no seg. não ord. int B = a[i]; // 1º elemento no seg. não ord. while ((j > 0) && (a[j-1] > B)) { a[j] = a[j-1]; j--; } a[j] = B; } } // do método buscando a posição do 1º elemento do segmento não ordenado no segmento ordenado Programação II – Prof. Mateus Raeder
ShellSort • Proposto por Ronald Shell em 1959. • Explora as seguintes características do método de inserção direta: • desempenho aceitável quando o número de chaves é pequeno; • desempenho aceitável quando as chaves já possuem uma ordenação parcial. • É considerado uma extensão do método de inserção direta, pois se diferencia deste apenas no nro. de segmentos considerados. • Realiza classificações parciais do vetor a cada iteração, favorecendo o desempenho dos passos seguintes. Programação II – Prof. Mateus Raeder
ShellSort • Método de classificação: • No primeiro passo, o vetor C [ n ] é dividido em h segmentos, de tal forma que cada um possua n / h chaves • Cada um dos segmentos é classificado por inserção direta, separadamente • No passoseguinte, o incremento h é diminuído (a metade do valor anterior, se este era potência inteira de 2) incrementos decrescente • No último passo, h = 1 h=22=4 h=21=2 h=20=1 3 passos Programação II – Prof. Mateus Raeder
ShellSort • Testes empíricos sugerem que a melhor escolha para os valores de h é a sequência • <(3t-1)/2, ..., 13, 4, 1> onde • ht = 3ht-1+1 • 3*0+1 = 1 • 3*1+1 = 4 • 3*4+1 = 13 • 3*13+1 = 40 Programação II – Prof. Mateus Raeder
17 25 49 12 18 23 45 38 53 42 27 13 11 ShellSort 0 1 2 3 4 5 6 7 8 9 10 11 12 Original 0 1 2 3 4 5 6 7 8 9 10 11 12 Primeiro passo: h = 4 11 23 27 12 17 25 45 13 18 42 49 45 53 1 2 341 2 341 2 341 0 1 2 3 4 5 6 7 8 9 10 11 12 Último passo: h=1 11 12 13 17 18 23 25 27 38 42 45 49 53 Programação II – Prof. Mateus Raeder
ShellSort public static void shellSort(int a[]) { int h = 1; // acha o maior valor possível para h while ((h * 3 + 1) < a.length) h = 3 * h + 1; // h=4 while( h > 0 ) { // para cada segmento de elem. (há h segm.) for (int i = h; i < a.length; i++) { int B = a[i]; int j = i; // compara B com o elemento antes dele no conjunto //e assim por diante até achar o lugar de B while ((j >= h) && (a[j - h] > B)) { a[j] = a[j - h]; j -= h; } a[j] = B; } h = h / 3; } } 0 1 2 3 4 5 6 7 8 9 10 11 12 11 23 27 12 17 25 45 13 18 42 49 45 53 Programação II – Prof. Mateus Raeder 1 2 341 2 341 2 341
Classificação por Trocas • Caracterizam-se por efetuarem a classificação por comparação entre pares de chaves, trocando-as de posição caso estejam fora de ordem no par. • Algoritmos: • BubbleSort • QuickSort Programação II – Prof. Mateus Raeder
Método da Bolha (BubbleSort) Exemplo: Suponha que se deseja classificar em ordem crescente o seguinte vetor de chaves: 28 26 30 24 25 Primeira Varredura 28 26 30 24 25 compara par (28, 26) : troca 26 28 30 24 25 compara par (28, 30) : não troca 26 28 30 24 25 compara par (30, 24) : troca 26 28 24 30 25 compara par (30, 25) : troca 26 28 24 25 30 fim da primeira varredura Programação II – Prof. Mateus Raeder
Método da Bolha (BubbleSort) Segunda Varredura 26 28 24 25 30 compara par (26, 28) : não troca 26 28 24 25 30 compara par (28, 24) : troca 26 24 28 25 30 compara par (28, 25) : troca 26 24 25 28 30 fim da segunda varredura Terceira Varredura 26 24 25 28 30 compara par (26, 24) : troca 24 26 25 28 30 compara par (26, 25) : troca 24 25 26 28 30 fim da terceira varredura Programação II – Prof. Mateus Raeder
Método da Bolha (BubbleSort) public static void bubbleSort(int a[]) { for (int i = a.length-1; i>0; i--) {// nro de varreduras for (int j = 0; j<i; j++) { // percorre vetor if (a[j] > a[j+1]) {// troca par de posição int T = a[j]; a[j] = a[j+1]; a[j+1] = T; } } } } Programação II – Prof. Mateus Raeder
Método da Bolha (BubbleSort) Considerando o seguinte vetor : 13 11 25 23 10 18 21 1) Em quantas varreduras o vetor é classificado ? 2) Como identificar, a partir da última varredura, quantas chaves já estão classificadas? Programação II – Prof. Mateus Raeder
Método da Bolha (BubbleSort) Considerando o seguinte vetor : 13 11 25 23 10 18 21 1) Em quantas varreduras o vetor é classificado ? 2) Como identificar, a partir da última varredura, quantas chaves já estão classificadas? Observe que a quantidade de chaves, a partir da última, que pode ser ignorada de uma varredura para a outra é conhecida pela posição na qual ocorreu a última troca. A partir daquele ponto o vetor já se encontra classificado! Programação II – Prof. Mateus Raeder
Método da Bolha (BubbleSort) Uma melhoria no algoritmo, para parar caso já esteja ordenado: public static void bubbleSort(int a[]) { for (int i = a.length-1; i>0; i--) { // nro. de varreduras boolean flipped = false; for (int j = 0; j<i; j++) { if (a[j] > a[j+1]) { // troca par de posição int T = a[j]; a[j] = a[j+1]; a[j+1] = T; flipped = true; } } if (!flipped) return; } } Programação II – Prof. Mateus Raeder
Método da Bolha (BubbleSort) • Análise do Desempenho do melhor caso • aquele no qual as chaves já se encontram na ordem desejada • na primeira varredura o método já terá descoberto que o vetor já se encontra ordenado • número de comparações efetuadas ? • n-1 • Análise do desempenho do pior caso • chaves do vetor se encontram na ordem inversa a desejada • a cada varredura apenas uma chave será colocada no seu lugar definitivo; as demais se deslocarão uma posição para a esquerda (em ordenação crescente) Programação II – Prof. Mateus Raeder
Método QuickSort A idéia básica é a de dividir o problema, de ordenar um conjunto de n itens em dois problemas menores. A seguir, os problemas menores são ordenados independentemente e depois os resultados são combinados para produzir a solução do problema maior! (Ziviani, 1996) Programação II – Prof. Mateus Raeder
QuickSort • 1) Dividir • Escolher um elemento da array como pivô (x); • Particionar: • elementos < pivô primeira parte • elementos > pivô segunda parte Programação II – Prof. Mateus Raeder
QuickSort • Princípio de classificação • inicialmente, o vetor de chaves C é particionado em três segmentos S1, S2 e S3 • S2 terá comprimento 1 e conterá uma chave denominada particionadora ou pivô • S1 terá comprimento 0 e conterá todas as chaves cujos valores são menores ou iguais ao da chave particionadora. Esse segmento está posicionado à esquerda de S2 • S3 terá comprimento 0 e conterá todas as chaves cujos valores são maiores do que o da chave particionadora. Esse segmento está posicionado à direita de S2 Programação II – Prof. Mateus Raeder
QuickSort Vetor Inicial : C [ 1 .. n ] n 1 Vetor Particionado n 1 K - 1 k K + 1 S1 S2 S3 Onde: C [ i ] C [ k ] , para i = 1, … , k - 1 C [ i ] > C [ k ] , para i = k + 1 , … , n Programação II – Prof. Mateus Raeder
QuickSort • Princípio de classificação (continuação … ) • o processo de particionamento é reaplicado aos segmentos S1 e S2 e a todos os segmentos correspondentes daí resultantes, que tiverem comprimento 1 • quando não restarem segmentos a serem particionados, o vetor estará ordenado • qual é a chave particionadora ideal ? Como escolher essa chave ? Programação II – Prof. Mateus Raeder
QuickSort • Escolhendo a chave particionadora ... • para simplificar o algoritmo de particionamento, pode-se arbitrar que a chave que se encontra na posição inicial do vetor a ser particionado será a particionadora • se existe conhecimento prévio sobre a distribuição dos valores das chaves e o vetor já se encontra parcialmente ordenado, a chave que se encontra na posição central do vetor pode ser a eleita Programação II – Prof. Mateus Raeder
QuickSort public static void quickSort (int[] a, int lo, int hi){ int i=lo, j=hi, h; int x=a[(lo+hi)/2]; // partition do { while (a[i]<x) i++; while (a[j]>x) j--; if (i<=j) { h=a[i]; a[i]=a[j]; a[j]=h; i++; j--; } } while (i<=j); // recursion if (lo<j) quickSort(a, lo, j); if (i<hi) quickSort(a, i, hi); } Programação II – Prof. Mateus Raeder
lo hi x=a[4] j i j j i i i j i j i j 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 Quick Sort quicksort(a, 0, a.length-1) void quicksort (int[] a, int lo, int hi) { int i=lo, j=hi, h; int x=a[(lo+hi)/2]; // partition do { while (a[i]<x) i++; while (a[j]>x) j--; if (i<=j) { h=a[i]; a[i]=a[j]; a[j]=h; i++; j--; } } while (i<=j); // recursion if (lo<j) quicksort(a, lo, j); if (i<hi) quicksort(a, i, hi); } 0 1 2 3 4 5 6 7 8 9 quicksort(a, 0, 3) quicksort(a, 5, 9) Programação II – Prof. Mateus Raeder
lo lo hi hi x=a[1] x=a[7] i i i j i i j j j i j j i i Quick Sort void quicksort (int[] a, int lo, int hi) { int i=lo, j=hi, h; int x=a[(lo+hi)/2]; // partition do { while (a[i]<x) i++; while (a[j]>x) j--; if (i<=j) { h=a[i]; a[i]=a[j]; a[j]=h; i++; j--; } } while (i<=j); // recursion if (lo<j) quicksort(a, lo, j); if (i<hi) quicksort(a, i, hi); } 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 quicksort(a, 5, 8) quicksort(a, 0, 0) quicksort(a, 2, 3) Programação II – Prof. Mateus Raeder
lo hi hi lo x=a[6] x=a[2] i j i j i i i j i j j j Quick Sort void quicksort (int[] a, int lo, int hi) { int i=lo, j=hi, h; int x=a[(lo+hi)/2]; // partition do { while (a[i]<x) i++; while (a[j]>x) j--; if (i<=j) { h=a[i]; a[i]=a[j]; a[j]=h; i++; j--; } } while (i<=j); // recursion if (lo<j) quicksort(a, lo, j); if (i<hi) quicksort(a, i, hi); } 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 quicksort(a, 5, 6) Programação II – Prof. Mateus Raeder
Quick Sort Exercício: Suponha que se deseja classificar o seguinte vetor: G R E M I S T A Suponha que a chave particionadora está na posição no meio do vetor. Simule as iterações necessárias para a classificação, segundo o algoritmo apresentado. Programação II – Prof. Mateus Raeder
Classificação por Seleção • Caracterizam-se por procurarem, a cada iteração, a chave de menor (ou maior) valor do vetor e colocá-la na sua posição definitiva correta, qual seja, no início (ou no final) do vetor, por permutação com a que ocupa aquela posição! • Algoritmos: • Seleção Direta • HeapSort Programação II – Prof. Mateus Raeder