Classificação / Ordenação /Pesquisa de Dados
Memória Interna
• Bibliografia – Referências • Conceitos
– Conceitos / Definições
– Algoritmo para pesquisa em um vetor
• Relembrando COMPLEXIDADE • Métodos de Ordenação
– Tipos de Ordenação – Trocas
– Métodos Simples e mais usados. – Algoritmo para pesquisa em um vetor
• Apresentação Gráfica
• Busca Sequencial em um Vetor Ordenado • Busca por meio de Pesquisa Binária
– Método de Inserção – Método de Seleção – QuickSORT
Bibliografia
• MANZANO, José Augusto N. G.; OLIVEIRA, Jayr Figueiredo. Algoritmos: lógica para desenvolvimento de programação de computadores. 17.ed. São Paulo: Érica, 2005.
• ASCENCIO, Ana Fernanda Gomes; VENERUCHI, Edilene Aparecida.
Fundamentos de programação de computadores: algoritmos, C/C++ e C/C++. São Paulo: Prentice Hall, 2002.
• FERRARI, Fabricio; CECHINEL, Cristian; Apostila de Introdução a Algoritmos e Estrutura de Dados. Universidade Federal do Pampa. Disponível em
http://www.dcc.ufam.edu.br/david/dmdocuments/Introducao-a-algoritmos.pdf
• MELLO, S. Ronaldo; Aulas disponíveis na WEB para a disciplina de Estrutura de Dados da Universidade Federal de Santa Catarina
• Compara Algoritmos de Ordenação
http://pt.wikipedia.org/wiki/Quicksort#Compara.C3.A7.C3.A3o_com_outros_algorit mos_de_ordena.C3.A7.C3.A3o
• http://www2.dcc.ufmg.br/disciplinas/aeds2/ • FEOFILLOFF, Paulo. Projetos de Algoritmos.
http://www.ime.usp.br/~pf/algoritmos/
Conceitos
A ORDENAÇÃO/CLASSIFICAÇÃO é um processo bastante utilizado na Computação, e fundamental para Algoritmos e Estrutura de Dados.
E de conhecimento que dados ordenados garantem uma melhor performance no desempenho dos algoritmos de pesquisa em uma Estrutura de Dados.
Processos mais conhecidos:
busca seqüencial
Evita a varredura completa de uma lista de dados, caso eles estejam ordenados;
Algoritmos extremamente simples.
busca binária
“A complexidade da ordenação da Estrutura de Dados não
deve exceder a complexidade da computação a ser feita
na Estrutura da Dados sem o processo de ordenação”
Exemplo: deseja-se realizar uma única pesquisa a um vetor
busca seqüencial
O(n)
ordenação
O(n log n) Algoritmo mais eficiente
Complexidade
- RELEMBRANDOA preocupação com a complexidade de algoritmos está
Inerente ao processo de projetar algoritmos eficazes e
eficientes.
Devemos desenvolver um algoritmo e depois analisar a
sua complexidade para verificar a sua eficiência.
Mas o recomendado é projetar e pensar os
algoritmos eficientes desde a sua concepção e idealização.
Complexidade
Geralmente um algoritmo é avaliado em termos:
•
tempo de execução
•
espaço (ou memória) utilizada.
O tempo é considerado como absoluto (minutos, segundos, etc.). Mas depende do equipamento. Já o espaço é facilmente mensurável mas não é tão eficiente.
O recomendado é medir o número de operações
consideradas relevantes realizadas pelo algoritmo e matematicamente colocada em relação a uma função de n (numero de operações).
Complexidade
Geralmente a avaliação considera o pior caso, que é o maior
número possível de operações usadas para qualquer entrada de tamanho n.
Mas também podem ser consideradas para o melhor caso e o caso médio.
Algoritmo 1: f1(n) = 500n + 4000 operações Algoritmo 2: f2(n) = 2n2 + 5n operações
Dependendo do valor de n, o Algoritmo 1 pode requerer mais ou menos operações que o Algoritmo 2.
Complexidade
Dada uma função g(n), denotamos por O(g(n)) é o conjunto das Funções relacionadas ao algoritmo.
{ f (n) : constantes c e n0 tais que (0 ≤ f (n) ≤ cg(n)) para n ≥ n0:}
Isto é, para valores de n suficientemente grandes, f (n) é igual ou menor que g(n). Como abuso de notação, vamos escrever f (n) = O(g(n)) ao invés de f (n) € O(g(n)).
Algoritmo 1: f1(n) = 500n + 4000 = O(n)
Algoritmo 2: f2(n) = 2n2 + 5n = O(n2)
Um polinômio de grau y é de ordem O(ny ). Como uma constante pode ser
considerada como um polinômio de grau 0, então dizemos que uma constante é O(n0) ou seja O(1).
Tipos de Ordenação
Ordenação por troca
BubbleSort - método da bolha – o mais simples.
QuickSort - método da troca e partição – o mais usado.
Ordenação por inserção
InsertionSort - método da inserção direta com deslocamento.
BinaryInsertionSort - método da inserção direta binária.
Ordenação por seleção
SelectionSort - método da seleção direta.
HeapSort - método da seleção utilizando árvore.
Outros métodos muito utilizados
MergeSort - método da intercalação.BucketSort - método da distribuição por chave.
•Outros algoritmos de ordenação::
– Count sort
– Shell sort
– Radix Sort
– Cocktail Sort
Métodos de Ordenação
Um contexto:
Utilizamos os algoritmos para ordenar e encontrar um número inteiro em um vetor de inteiros.
Elemento do vetor:
objeto que possui um atributo chave/inteiro que deve ser mantido ordenado
Um método:
Um método comum é por meio de trocas de elementos e uma função troca(x,y) realiza a troca dos elementos presentes nas posições x e y
Métodos de Troca
Classifica início
vetor inteiro[ ];
n inteiro; /* tamanho do vetor */
Classifica (REF v[ ] inteiro); início
n v.lenght;
se n < 1 então Exceção VetorVazio(); vetor v;
ordena(); v vetor;
fim;
ordena();
início
. . .
método troca(x inteiro, y inteiro); início
aux inteiro; aux vetor[x]; vetor[x] vetor[y]; vetor[y] aux;
fim;
fim;
Algoritmos que utilizam
o método de troca duas posições do VETOR.
Métodos Simples
São três
BubbleSort – Método Bolha
InsertionSort – Método por inserção
SelectionSort – Método por seleção
Características
Algoritmos simples e de fácil implementação.
Baixa eficiência e alta complexidade.
BubbleSort - Método da Bolha
BubbleSort ou Método da Bolha
é um método simples de troca que ordena por meio de sucessivas trocas entre posições adjacentes do vetor
Características:
Ordena trocando pares adjacentes de elementos sempre que o próximo elemento for menor que o anterior
Após uma varredura completa, o maior elemento está corretamente posicionado no vetor e não precisa mais ser
comparado após a enésima varredura, os i maiores elementos estarão ordenados.
Exemplo de funcionamento: http://math.hws.edu/TMCM/java/xSortLab
/* desconsidera elementos */ /* a direita já ordenados */
Bubblesort – Método Bolha
void bolha(int n, int *vet) {
int i,j,temp;
for (i=n-1; i >=1; i--)
for (j=0; j<i; j++)
if(vet[j]>vet[j+1]) {
temp = vet[j];
vet[j] = vet[j+1];
vet[j+1] = temp;
} /* if */
}
Algoritmo mais eficiente.
void bubble(int v[], int tam) { int i, aux,trocou;
do {
tam--;
trocou = 0; //usado para otimizar o algoritmo for(i = 0; i < tam; i++)
if(v[i] > v[i + 1]) { aux=v[i];
v[i]=v[i+1]; v[i+1]=aux; trocou = 1; }
Para um vetor de n elementos, n – 1 varreduras são feitas para a ordenação
9
14
7
6
10
9
7
6
10
14
7
6
9
10
14
6
7
9
10
14
5
7
9
10
14
5
7
9
10
14
1a V: n – 1 comparações
2a V: n – 2 comparações
. . .
(n-2)a V: 2 comparações
(n-1)a V: 1 comparação Bubblesort – Método Bolha
Simulação
Bubblesort – Método Bolha
1. Definida pelo número de comparações necessárias
para a ordenação (relacionada ao tamanho do vetor).
2. Número de comparações:
(n - 1) + (n – 2) + ... + 2 + 1
3. Complexidade (para qualquer caso):
i = 1 n - 1
i
=
(n - 1) n2
O(n
Pesquisa sequencial em VETOR ordenado e não ordenado
int buscaele(int n, int *vet, int ele) {
int i = 0;
// printf("Vet[%d]=%d\n Elem=%d\n N=%d \n",i,vet[i],ele,n); while (i < n && vet[i] != ele) {
i++;
printf("Comparacao %d \n",i); }
if (i < n) printf("Vet[%d]=%d\nElem=%d\n",i,vet[i],ele); if (n == i)
return -1; // elemento não encontrado else return i; //elemento na posição i
}
int buscaord(int n, int *vet, int num) {
int i;
if (num < vet[0] && num > vet[n-1]) // teste extremos do vetor return -1; // elemento não está no vetor
i = 0;
while (vet[i] < num) {
printf("Comparacao %d \n",i); i ++;
}
if ( vet[i] == num) // encontrou o elemento return i; // na posição i
Pesquisa sequencial em VETOR ordenado e não ordenado
A B C E H M O P T Z
Procurar por P
1. Foram realizadas 8 comparações!
2. Se eu estivesse procurando o item Z, o número de
comparações seria a quantidade de elementos no vetor
Pesquisa Binária
ALGORITMO
Divida o vetor em duas metades:
1. Se o elemento for igual ao item que está na metade do vetor, ou da parte que está sendo manipulada, sucesso; porém
2. Se for menor, divida novamente a primeira metade do vetor e encontre o ponto médio. Se for
o elemento, sucesso.
3. Se for maior procure na segunda metade do vetor e encontre o ponto médio. Se for o elemento, sucesso.
4. Caso contrário redivida a parte do vetor e retorne em 1.
Pesquisa Binária
int buscaBIN(int tam, int *vet, int num) { int ini = 0;
int i =0; /* somente utilizado para apresentar número de comparações */ int fim = tam - 1;
int meio;
while (ini <= fim) {
printf("Comparacao %d \n",i); i++;
meio = (fim + ini) / 2; if (num < vet[meio]) fim = meio -1;
else if (num > vet[meio]) ini = meio + 1;
else
return meio; }
Pesquisa Binária
Procurar por P
I X I X FF
A B C E H M O P T Z
1. 2 Comparações!
Ordenação
InsertionSort – Método Inserção
InsertionSort
é um método simples de inserção
Características do método:
Considera duas partes ou dois segmentos
(sub-vetores) no vetor original: a primeira parte
ordenada (aumenta) e a segunda não-ordenada
(diminui), e o processo ordena através da inserção de
um elemento por vez (primeiro elemento) do
e
5e
9. . .
e
8e
2parte ordenada parte não-ordenado
e
5e
8e
9. . .
e
2Antes da aplicação do método o segmento ordenado
contém apenas o primeiro elemento do vetor
InsertionSort – Método Inserção
A OD OO RR EE NN A i = 4
A
O R D E N
6
2 3 4 5
1
i = 3 O R D E N A
A
D E O R N
i = 5
A
D E N O R
i = 6
R
A D E N O
Res.: Chaves Iniciais
O R
A
O R D E N
InsertionSort – Método Inserção
void insertionSort(int v[], int n) { int i, j, chave;
for(j=1; j<n; j++) { chave = v[j]; i = j-1;
while(i >= 0 && v[i] > chave){ v[i+1] = v[i];
i--; }
v[i+1] = chave; }
Realiza uma busca seqüencial na parte ordenada
para inserir corretamente um elemento da parte
não-ordenada.
Nesta busca, realiza trocas entre elementos adjacentes
para ir acertando a posição do elemento a ser inserido
Exemplo de operação:
http://math.hws.edu/TMCM/java/xSortLab
InsertionSort – Método Inserção
i = 1
n - 1
i
=
(n - 1) n
2
O(n
2
)
- piorInsertionSort – Método Inserção x BubbleSort – Método Bolha
Tipo
Melhor caso
Pior caso
Método de
Inserção
O(n)
O(n
2)
Método
Bolha
SeletionSort - Método de Seleção
SelectionSort
é um método simples de seleção
O algoritmo de seleção ordena por meio de sucessivas
seleções do elemento de menor valor em uma parte
não-ordenada do vetor e o posiciona no final da
parte já ordenada.
e
2e
5e
8. . .
e
6SeletionSort - Método de Seleção
SelectionSort
é um método simples de seleção
O algoritmo de seleção ordena por meio de sucessivas
seleções do elemento de menor valor em uma parte
não-ordenada do vetor e o posiciona no final da
parte já ordenada.
Exemplo de execução:
http://math.hws.edu/TMCM/java/xSortLab
Complexidade:
n - 1i
=
(n - 1) n
O(n
2)
Principal característica do método é a pesquisa
sequencial
pelo menor
SeletionSort - Método de Seleção
Principal característica do método é a pesquisa seqüencial pelo menor valor na parte não-ordenada do vetor a cada iteração
14
10
6
7
9
6
10
14
7
9
6
7
14
10
9
SeletionSort - Método de Seleção
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; }
QuickSort - Informações Gerais
1. É o algoritmo de ordenação interna mais rápido que se conhece para uma ampla variedade de situações e é o mais utilizado.
2. Proposto em 1960 e publicado em 1962.
3. A idéia básica é dividir o problema de ordenar um conjunto com n itens em dois problemas menores.
4. Os problemas menores são ordenados independentemente.
QuickSort - O algoritmo
1. A parte mais delicada do método é o processo de partição. 2. O vetor Vet [Esq..Dir] é rearranjado por meio da escolha
arbitrária de um pivô x.
3. O vetor Vet é particionado em duas partes: 1. Parte esquerda: chaves ≤ x.
2. Parte direita: chaves ≥ x.
4. Já que a escolha de um pivô x é arbitrariamente.
5. Percorra o vetor a partir da esquerda até que Vet[i] ≥ x. 6. Percorra o vetor a partir da direita até que Vet[j] ≤ x. 7. Troque Vet[i] com Vet[j].
8. Continue este processo até os apontadores i e j se cruzarem. 9. Ao final, do algoritmo de partição o vetor Vet[Esq..Dir] está
particionado de tal forma que:
1. Os itens em Vet[Esq], Vet[Esq + 1], ..., A[j] são menores ou iguais a x;
QuickSort - O algoritmo
3
6
4
5
1
7
2
3
2
4
1
5
7
6
Primeira partição
1
2
4
3
5
7
6
Segunda partição
1
2
3
4
5
7
6
terceira partição
.
.
.
Continua...
QuickSort
1
2
3
4
5
7
6
3
2
4
1
5
6
7
quarta partição
1
2
4
3
5
6
7
quinta partição
1
2
3
4
5
6
7
QuickSort
A
O R D E N
6
2 3 4 5
1
i = 2 A R D E N O
O
A D R E N
i = 3
Chaves Iniciais D
1. O pivô é escolhido como sendo A[(i+j) div 2] Inicialmente, i=1 e j=6, e então x=A[3] = D
1. A varredura a partir da posição 1 pára no item O e a varredura a partir da posição 6 pára em A, sendo os dois itens trocados
2. A varredura a partir da posição 2 pára em R e a varredura a partir da posição 5 pára no item D, e então os dois itens são trocados 3. Neste instante i e j se cruzam (i=3 e j=2), o que encerra o
QuickSort
A
O R D E N
i = 1 A D R E N O
O
E R N
i = 3
O N R
i = 4
R O
i = 5
Chaves Iniciais
A D
i = 2
R
A D E N O
QuickSort
void quicksort (int v[], int primeiro, int ultimo){ int i, j, m, aux;
i=primeiro; j=ultimo; m=v[(i+j)/2]; do{
while (v[i] < m) i++; while (v[j] > m) j--; if (i<=j){ aux=v[i]; v[i]=v[j]; v[j]=aux; i++; j--; }
} while (i<=j); if (primeiro<j)
quicksort(v,primeiro,j); if (ultimo>i)
QuickSort
void swap(int* a, int* b) { int tmp;
tmp = *a; *a = *b; *b = tmp; }
int partition(int vec[], int left, int right) { int i, j;
i = left;
for (j = left + 1; j <= right; ++j) { if (vec[j] < vec[left]) {
++i; swap(&vec[i], &vec[j]); } } swap(&vec[left], &vec[i]); return i; }
void quickSort(int vec[], int left, int right) { int r;
if (right > left) {
r = partition(vec, left, right); quickSort(vec, left, r - 1);
quickSort(vec, r + 1, right); }
QuickSort - Complexidade
Melhor caso:
C(n) = 2C(n/2) + n = n log n
Esta situação ocorre quando cada partição dividida são proporcionais (mesmo tamanho). C(n) é a função que conta o número de
comparações.
Mediano:
C(n) ≈ 1,386n log n – 0,846n
Em média o tempo de execução do Quicksort é O(n log n).
Pior caso:
C(n) = O(n2)
O pior caso ocorre quando o pivôs são escolhidos nos
Algumas conclusões
• Como visto existem muitos métodos de ordenação em memória interna. • A estabilidade , à ordem em que dados repetidos vão aparecer, também é
determinante.. Quando esta ordem é mantida diz-se que o algoritmo é estável.
• Qual algoritmo a ser utilizado vai depender da quantidade e do grau de ordenação(ou, desordenação dos dados.
• Fator IMPORTANTE a se considerar é a complexidade destes algoritmos. Esta medida se refere ao tempo estimado para que a ordenação ocorra.
• Existem várias páginas na Internet tratando deste assunto. Muitas delas contem animações que mostram como o algoritmo se comporta.
• Alguns links:
– http://pt.wikipedia.org/wiki/Algoritmos_de_ordena%C3%A7%C3%A3o – http://www.ime.usp.br/~pf/algoritmos/aulas/ordena.html
– animações
Outras Recomendações para Leitura
• http://www.fsma.edu.br/si/edicao9/
FSMA_SI_2012_1_Principal_1.pdf
• A. Drozdek, Estruturas de dados e algoritmos em C++. São
Paulo: Pioneira Thomson Learning, 2005.
• S. L. Gonzaga de Oliveira, Algoritmos e seus fundamentos,
Lavras: Editora UFLA, 2011.
• M. T. Goodrich, R. Tamassia, Projeto de Algoritmos:
Perguntas, considerações e comentários