Estrutura de Dados II - 2021-1
UnB-\(\gamma\)
Table of Contents
- 1. Aulas
- 1.1. Aula 1 19_jul
- 1.2. Aula 2 21_jul ordenacao_elementar
- 1.3. Aula 3 26_jul merge_sort
- 1.4. Aula 4 28_jul exercicios
- 1.5. Aula 5 02_ago recap
- 1.6. Aula 6 04_ago sanidade
- 1.7. Aula 7 09_ago quicksort
- 1.8. Aula 8 11_ago quickselect
- 1.9. Aula 9 16_ago quicksort_final
- 1.10. Aula 10 18_ago hash
- 1.11. Aula 11 23_ago hash
- 1.12. Aula 12 25_ago
- 1.13. Aula 13 30_ago
- 1.14. Aula 14 01_set árvore
- 1.15. Aula 15 06_set exercício
- 1.16. Aula 16 08_set exercícios
- 1.17. Aula 17 13_set
- 1.18. Aula 18 15_set
- 1.19. Aula 19 20_set
- 1.20. Aula 20 22_set
- 1.21.
Aula 2127_set semana_academica - 1.22.
Aula 2229_set semana_academica - 1.23. Aula 23 06_out
- 1.24. Aula 24 04_out
- 1.25.
Aula 2511_out feriado - 1.26. Aula 26 13_out
- 1.27. Aula 27 18_out
- 1.28. Aula 28 20_out
- 1.29. Aula 29 25_out
- 1.30. Aula 30 27_out
- 1.31.
Aula 3101_nov feriado - 1.32. Aula 32 03_nov
- 2. Antes de Começar
- 3. Plano de Aulas
- 4. Monitor
- 5. Presença
- 6. Notas
Table of Contents
- 1. Aulas
- 1.1. Aula 1 19_jul
- 1.2. Aula 2 21_jul ordenacao_elementar
- 1.3. Aula 3 26_jul merge_sort
- 1.4. Aula 4 28_jul exercicios
- 1.5. Aula 5 02_ago recap
- 1.6. Aula 6 04_ago sanidade
- 1.7. Aula 7 09_ago quicksort
- 1.8. Aula 8 11_ago quickselect
- 1.9. Aula 9 16_ago quicksort_final
- 1.10. Aula 10 18_ago hash
- 1.11. Aula 11 23_ago hash
- 1.12. Aula 12 25_ago
- 1.13. Aula 13 30_ago
- 1.14. Aula 14 01_set árvore
- 1.15. Aula 15 06_set exercício
- 1.16. Aula 16 08_set exercícios
- 1.17. Aula 17 13_set
- 1.18. Aula 18 15_set
- 1.19. Aula 19 20_set
- 1.20. Aula 20 22_set
- 1.21.
Aula 2127_set semana_academica - 1.22.
Aula 2229_set semana_academica - 1.23. Aula 23 06_out
- 1.24. Aula 24 04_out
- 1.25.
Aula 2511_out feriado - 1.26. Aula 26 13_out
- 1.27. Aula 27 18_out
- 1.28. Aula 28 20_out
- 1.29. Aula 29 25_out
- 1.30. Aula 30 27_out
- 1.31.
Aula 3101_nov feriado - 1.32. Aula 32 03_nov
- 2. Antes de Começar
- 3. Plano de Aulas
- 4. Monitor
- 5. Presença
- 6. Notas
1. Aulas
1.1. Aula 1 19_jul
1.1.1. Tópicos
- Apresentação da disciplina em live no YouTube
- Apresentação do Plano de Aulas
- Previsão de Avaliações
- Método de cálculo de presença
- Método avaliativo e gradação
- Apresentação do Plano de Aulas
1.1.2. Material de apoio
Para a aula de hoje é recomendado que o aluno veja os vídeos disponibilizados na seção Antes de Começar
1.1.3. Exercícios básicos para relembrar
É possível que vários alunos tenham perdido a prática durante o período de férias, e isso faz com que a ferrugem dificulte o início da retomada de implementação de problemas. Para isso estou liberando uma lista pública com alguns problemas selecionados.
- Lista pública no CD-MOJ
- Resolva os exercícios propostos na PRIMEIRA lista pública do CD-MOJ.
Para ganhar credenciais de acesso à lista, envie uma mensagem para
@mojinho_bot
, no telegram AQUI, com o conteúdo:participar bcr-EDA2-2021_1-lista1-relembrando
1.2. Aula 2 21_jul ordenacao_elementar
Nesta aula vamos começar a trabalhar com algoritmos elementares de ordenação, em especial: BubbleSort; Selection Sort; Insertion Sort.
Antes de começar a trabalhar com os algoritmos de ordenação vamos definir as “regras do jogo”, o contexto, a terminologia e o arcabouço mínimo que se espera para começar a implementar os algoritmos de ordenação.
Nas seções abaixo você encontra todo o conjunto de vídeos explicando cada um dos algoritmos. Além disso temos na seção 1.2.2 um compilado dos tempos de execução dos algoritmos tratados. Por fim na seção 1.2.3 expõe um resumo sobre os algoritmos tratados na seção abaixo.
Não esqueça:
- Complemente o conteúdo passado nos vídeos com o material do professor Paulo Feofiloff sobre Algoritmos Elementares de Ordenação
- Resolva os exercícios propostos na seção de Exercícios
- A Implementação de vários algoritmos de Ordenação está disponível no Github para que você tome como referência.
1.2.1. Entenda os Algoritmos passo a passo
1.2.2. Tempo de execução dos Algoritmos Elementares de Ordenação
1.2.3. Sumarização dos algoritmos
1.2.4. Exercícios
- Lista pública no CD-MOJ
- Resolva os exercícios propostos na lista pública do CD-MOJ.
As credenciais de acesso à lista são as mesmas da primeira. Caso não tenha criado uma conta, envie uma mensagem para @mojinhobot, no telegram AQUI, com o conteúdo:
participar bcr-EDA2-2021_1-ordena-elementar
- Implemente
- cada um dos algoritmos discutidos em aula (evite consultar o material e deduza os passos);
- Compare o tempo de execução dos algoritmos
- Gere entradas aleatórias com 100000 elementos (experimente outras variações de tamanho também)
- Para gerar uma entrada aleatória em
bash
for((i=0;i<100000;i++)); do echo $RANDOM; done > aleatorio.in
- Caso prefira implementar em
C
srand(time(NULL)); for(int i=0;i<100000;i++) printf("%d\n",rand());
compile o código e execute da seguinte forma:
./meuprograma > aleatorio.in
- O seu programa deve ler o conjunto de números da entrada padrão, e você poderá verificar o tempo executado através dos comandos:
time ./bubblesort < aleatorio.in > bubblesort.out
- assim o seu programa irá ler o conteúdo do arquivo
aleatorio.in
como se fosse digitado pelo teclado e toda a saída será gravada no arquivobubblesort.out
(você pode trocar o nome do arquivo se assim desejar [recomendo um arquivo diferente para cada algoritmo implementado].
- Crie variações dos arquivos, gere arquivos maiores, menores, ordenados, ordenados reversamente… E compare o tempo entre esses arquivos, há diferença?
- Verifique a quantidade de operações executadas
- Modifique a sua implementação de forma a mostrar a quantidade de operações de troca e quantas comparações foram feitas.
- Compare o resultado com todos os algoritmos implementados para diversas entradas
- Escreva uma função que coloque em ordem lexicográfica um vetor de strings
- Resolva a Terceira questão desta prova
- Resolva a Segunda questão desta prova
- Defina o conceito de estabilidade de um algoritmo de ordenação.
- Liste quais algoritmos trabalhados nesta aula são estáveis e quais não são
- Ordenando um registro
Suponha que cada elemento de um vetor é um registro com dois campos: um inteiro e outro uma string:
struct registro { int aa; char *bb;};
Escreva uma função que rearranje o vetor de modo que os campos
aa
fiquem em ordem crescente. Escreva outra função que rearranje o vetor de modo que os camposbb
fiquem em ordem lexicográfica. - Execute o benchmark disponibilizado no Github
Faça o
git clone
do repositório https://github.com/bcribas/benchmark-ordenacao e siga as instruções doREADME
para executar o experimento com algumas implementações. - Você pode me ajudar com alguma das issues abaixo?
1.3. Aula 3 26_jul merge_sort
A aula de hoje é dedicada à resolução dos exercícios referentes aos Algoritmos Elementares de Ordenação divulgados na Aula 2.
Havendo dúvidas, os alunos podem enviar um e-mail ao professor, caso não haja dúvidas até às 8h50 a live de hoje não ocorrerá. No entanto, os alunos podem enviar as dúvidas ao professor durante todo o período da aula.
- Atualizações
- (Mon, 26 Jul 2021 08:51:06 -0300) Turma, por falta de dúvidas graves, não teremos a live hoje. Estarei respondendo e-mails de todos até o horário da aula.
1.4. Aula 4 28_jul exercicios
1.4.1. MergeSort explicado de outra maneira
1.4.2. Tópicos e materiais
Discussão e implementação do Algoritmo linearítmico de Ordenação MergeSort.
Nesta aula foi discutido o algoritmo MergeSort
, mas antes, iniciamos
a discussão sobre o funcionamento da função intercala
(merge
) que
é a base para o funcionamento do algoritmo de ordenação.
Na live foi implementada a intercalação que recebe dois ponteiros de
vetores e seus respectivos intervalos fechados [l,r]
(l
para
left
[ou elemento mais a esquerda] e r
para right
[ou elemento
mais a direita]) devolvendo um vetor alocado com os elementos dos dois
vetores, a
e b
, intercalados. A função implementada em aula segue
o conceito implementado abaixo:
1: Item *intercala(Item *a, int la, int ra, Item *b, int lb, int rb) 2: { 3: //Tamanhos dos vetores a e b 4: int ta=(ra-la+1); 5: int tb=(rb-lb+1); 6: 7: Item *c=malloc(sizeof(Item)*(ta+tb)); 8: 9: //intervalos do vetor c 10: int lc=0; 11: int rc=(ta+tb-1); 12: 13: int ia=la, ib=lb,ic=lc; 14: 15: while(ia<=ra && ib<=rb) 16: { 17: if(lesseq(a[ia],b[ib])) 18: c[ic++]=a[ia++]; 19: else 20: c[ic++]=b[ib++]; 21: } 22: while(ia<=ra) 23: c[ic++]=a[ia++]; 24: while(ib<=rb) 25: c[ic++]=b[ib++]; 26: return c; 27: }
Esta implementação difere, ligeiramente, da versão feita no vídeo
indicado como MergeSort
(no início da aula), que faz com que a função
de intercalação receba um único vetor com os índices l,m,r
(left,middle,right).
O efeito da intercalação é o mesmo, porém, a implementação feita em
aula exige que o vetor c
seja manipulado dentro do procedimento
mergesort
, diferentemente do outro vídeo.
A complexidade assintótica não é modificada e tão pouco agrega overhead adicional entre as versões. Fica interessante ter a manipulação diferente dos elementos para ter uma visão ampla da implementação.
Dessa forma o mergesort
, em aula, foi implementado da seguinte
forma:
28: void mergesort(Item *v,int l,int r) 29: { 30: if(l>=r) return; 31: int meio=(l+r)/2; 32: mergesort(v,l,meio); 33: mergesort(v,meio+1,r); 34: //principal diferença do intercala não ser in-place 35: Item *c=intercala(v,l,meio,v,meio+1,r); 36: for(int i=0;i<r-l+1;i++) 37: v[l++]=c[i]; 38: free(c); 39: }
A principal diferença na mergesort
acontece a partir da linha
35, onde o nosso procedimento manipula o vetor resultante
da intercalação para dentro do vetor que está sendo ordenado.
Outra maneira de passar os parâmetros do vetor v
como se fossem dois
vetores realmente disjuntos, seria passando o ponteiro da posição
inicial de cada left
do vetor, substituindo a Linha 35
pela linha indicada abaixo:
1: Item *c=intercala(&v[l],0,meio-l,&v[meio+1],0,r-(meio+1));
O que acontece neste ponto é que passamos os ponteiros dos left
de
cada um dos vetores que devem ser intercalados, um deles começa em l
e o outro em meio+1
, o que precisamos calcular agora é qual seria o
novo right
de cada vetor, pois como cada vetor não começa no l
do
vetor original temos que recalcular o deslocamente de cada parte,
ficando meio-l
para a primeira metade e r-(meio+1)
para a segunda
metade.
- Material de apoio
- O aluno também pode acompanhar o material de MergeSort do prof. Paulo Feofiloff
- Veja a página de comparação dos algoritmos de ordenação
1.4.3. Exercícios
- Lista pública no CD-MOJ
- Resolva os exercícios propostos na lista Mergesort pública do CD-MOJ.
Para ganhar credenciais de acesso à lista, envie uma mensagem para @mojinhobot, no telegram AQUI, com o conteúdo:
participar bcr-EDA2-2021_1-mergesort
- Se você já conta para a outra lista (disponibilizada na Aula 1), pode utilizar as mesmas credenciais.
- Implemente o algoritmo da Intercalação (merge)
- Implemente o algoritmo de ordenaçao por intercalação (mergesort)
- Escreva uma função que
- receba vetores disjuntos
x[0..m-1]
ey[0..n-1]
, ambos em ordem crescente, e produza um vetorz[0..m+n-1]
que contenha o resultado da intercalação dos dois vetores dados.- É claro que
z
estará em ordem crescente.
- É claro que
- Escreva duas versões da função: uma iterativa e uma recursiva.
- receba vetores disjuntos
- Exercícios baseados do Professor Paulo Feofiloff
- A respeito do problema da Intercalação (merge)
O problema da intercalação (merge) é clássico na computação e consiste em resolver o seguinte problema: dados vetores crescentes
v[p .. q-1]
ev[q .. r-1]
, rearranjarv[p .. r-1]
em ordem crescente.Uma leO é uma lista encadeada que contém uma sequência crescente de números inteiros. Escreva uma função que intercale duas leO dadas, produzindo assim uma terceira leO. Sua função não deve alocar novas células na memória, mas reaproveitar as células das duas listas dadas.
- Execute o benchmark disponibilizado no Github
Faça o
git clone
do repositório https://github.com/bcribas/benchmark-ordenacao e siga as instruções doREADME
para executar o experimento com algumas implementações.Recomendo que neste momento você execute da seguinte maneira
TIMEOUT=3 BINARY="dummy bubblesort selectionsort insertionsortslow insertionsort mergesort" make time.reverso time.ordenado
- Após a execução compare a diferença de execução entre os algoritmos e pondere suas implicações
- Modifique a sua implementação do MergeSort para que ela mostre a quantidade de comparações feitas e compare com execuções feitas com os algoritmos elementares
- O algoritmo MergeSort é estável?
- Um algoritmo de intercalação é estável se não altera a posição relativa de elementos iguais. A função
intercala
é estável? E se a comparaçãolesseq(a[ia],b[ib])
, for trocada porless(a[ia],b[ib])
? - Implemente uma versão modificada do MergeSort com que ele considere os números ímpares sempre maiores que os números pares HOT
Dessa maneira o vetor, sem ordenação, abaixo:
30 44 1 93 44 77
Ficaria ordenado da seguinte maneira:
30 44 44 1 77 93
1.5. Aula 5 02_ago recap
Nesta aula o professor irá conversar e discutir com os alunos alguns dos problemas disponibilizados nas listas de exercícios de fixação, liberadas em aulas anteriores.
Os alunos devem ler a maior parte dos problemas para que entendam a motivação de cada um deles.
Preste atenção. A aula de hoje é dividida em 2 partes: A primeira é assíncrona, e o aluno deverá ler e assistir as seções abaixo; Em seguida, às 8h45 inicia-se a parte síncrona com o professor.
1.5.1. Corte
1.5.2. Vídeo com TIMESTAMPS
Vídeo com TIMESTAMPS sobre vários problemas sendo resolvidos. Veja se a sua dúvida já não foi resolvida neste vídeo:
1.5.3. Explicação Número Proibido
A descrição do problema é bastante clara e não esconde o que precisa ser feito, no entanto é necessário que o aluno tenha alguma “malícia” algorítmica para entender como atacar o problema, mas vamos discutir isso com calma.
Primeiramente o enunciado explica que existe uma lista de números proibidos e eles possuem um tamanho bem específico, até \(140000\) números, e cada um deles é um número positivo entre \([0,2^{31}]\) (note que o intervalo é fechado), o que significa que esses números cabem em um número inteiro.
A entrada dos números inteiros é dada por um \(N\), indicando a quantidade de números proibidos, e depois os \(N\) numerais. O código para entrada é bastante direto e possui complexidade em \(\mathcal{O}(N)\), parecido com o código abaixo:
1: int proibidos[140000]; 2: int proibidos_ct; 3: scanf("%d",&proibidos_ct); 4: for(int i=0;i<proibidos_ct;i++) 5: scanf("%d",&proibidos[i]);
O código acima não tem nenhum segredo, mas o problema começa a apareser nas próximas linhas do enunciado.
O enunciado nos conta que o depois da lista de números proibidos acontecerá um número indeterminado de perguntas, e cada pergunta consiste em saber se um número dado pertence ao conjunto de números proibidos.
A informação da quantidade indeterminada de perguntas nos sugere que elas devem acontecer diversas vezes, muitas vezes mais que a quantidade de números proibidos. E é nesse ponto que você deve ficar encafifado.
Caso você já tenha levado um Time Limit Exceeded
, você percebeu que
o tempo limite de execução é de meros \(0,2495\) segundos, você
identifica isso dentro do log enviado pelo mojinho ao invocar o
comando getlog
.
Mas vou um pouco mais além e vou mostrar a informação presente nas máquinas. Hoje temos duas máquinas operando como juízes, a jaguapitanga e a ovomaltine (principal), veja a spec delas:
- jaguapitanga
- arch: x8664
- cpu: Intel(R) Celeron(R) CPU 3867U @ 1.80GHz
- memory: 8077352
- ovomaltine
- arch: x8664
- cpu: Intel(R) Core(TM) i5-4200U CPU @ 1.60GHz
- memory: 16315452
As máquina são pouco diferentes e o tempo de execução são:
- jaguapitanga
- c: .3980
- ovomaltine
- c: .2495
Mesmo a ovomaltine sendo mais rápida os tempos não são tão diferentes. Note que a jaguapitanga só é utilizada quando a ovomaltine fica fora do ar, opera como um backup.
Agora vou executar alguns experimentos na jaguapitanga para que consigamos ter uma noção dos tempos que as coisas levam.
Considerando uma ideia bobinha, por exemplo, um código com um vetor de \(140000\) elementos procurando um elemento que não existe, ou seja, efetuando uma busca sequencial. Como o problema nos fala que a quantidade de perguntas é indeterminada, vamos monstar um exemplo que procure \(140000\) vezes um número que não existe.
Como vamos utilizar uma busca sequencial, significa que vamos ter que percorrer o vetor de números proibidos inteiro para descobrir que o número não está lá, então podemos dizer que a busca sequencial é proporcional a \(\mathcal{O}(N)\) operações, como \(N\) é \(140000\) e vamos realizar \(140000\) buscas falhas temos operações propocionais a \(N^2\).
Vamos ver como se comporta um código bobinho desses:
1: #include <stdio.h> 2: #include <stdlib.h> 3: int achou(int num,int *v,int l,int r) 4: { 5: for(int i=l;i<=r;i++) 6: if(v[i]==num) 7: return 1; 8: return 0; 9: } 10: int main(void) 11: { 12: int vetor[140000]; 13: //preparando para gerar números aleatórios 14: srand(140000); 15: //preenchendo o vetor com números aleatórios inferiores a 1milhão 16: for(int i=0;i<140000;i++) 17: vetor[i]=rand()%1000000; 18: 19: //fazendo 140000 buscas pelo número 1milhão 20: for(int i=0;i<140000;i++) 21: if(!achou(1000000,vetor,0,140000-1)) 22: printf("nao\n"); 23: else 24: printf("sim\n"); 25: } 26:
Executando este código na jaguapitanga, e compilando com os mesmos parâmetros que usamos no MOJ o tempo de execução fica em enormes \(15,61\) segundos. Muito acima do tempo limite estipulado pelo MOJ.
Veja abaixo como foi executado:
ribas@jaguapitanga:/tmp$ make busca_bobinha CFLAGS='-O2 -static' cc -O2 -static busca_bobinha.c -o busca_bobinha ribas@jaguapitanga:/tmp$ time ./busca_bobinha > /dev/null real 0m15.616s user 0m15.607s sys 0m0.008s
O resultado é muito aquém ao que esperamos, pois o TL é de \(0,2495\) segundos. Como poderíamos reduzir este tempo?
Lá em EDA-1 você deve ter aprendido que existe um algoritmo que sabe fazer uma busca mais rapidamente que a busca sequencial. Esta é a busca binária. O problema é que a busca binária precisa de um vetor ordenado para poder realizar a busca rapidamente.
Então PARA TUDO! Precisamos ordenar esse vetor antes de fazer a busca!
Aprendemos diversos algoritmos de ordenação neste semestre e temos uma noção de como cada um se comporta.
Peguei rapidamente o Benchmark de Ordenação e resolvi experimentar na jaguapitanga primeiramente testando os clássicos:
bubblesort
- seletionsort
- insertionsort
- mergesort
Sabemos que somente o mergesort, dentre os listados acima, possui complexidade em \(\mathcal{O}(N \log{}(N))\), enquanto que os outros estão em \(\mathcal{O}(N^2)\).
Table 1: Tabela de tempos de execução para os algoritmos de ordenação para entradas de tamanhos entre \(2^8\) e \(2^{20}\), com tempo limite de execução em 20 segundos Alg/#Elementos 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 bubblesort 0.00 0.00 0.00 0.01 0.04 0.20 0.91 3.89 16.01 TLE TLE TLE TLE selectionsort 0.00 0.00 0.00 0.00 0.01 0.05 0.23 0.91 3.61 14.42 TLE TLE TLE insertionsort 0.00 0.00 0.00 0.00 0.00 0.01 0.04 0.16 0.67 2.79 11.69 TLE TLE mergesort 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.01 0.03 0.06 0.12 0.25 0.53
Para gerar a tabela acima o benchmark de ordenação foi executado da seguinte maneira na jaguapitanga:
TIMEOUT=20 BINARY="bubblesort selectionsort insertionsort mergesort" make time.aleatorio
Veja que os algoritmos quadráticos (os três primeiros) crescem na
proporção esperada, ou seja, ~4x
mais tempo é necessário para ordenar
um vetor com o dobro do tamanho.
Logo, é perceptível que somente o mergesort consegue ordenar o vetor dentro do limite de tempo tão justo, ou seja, sabemos que ele ordena \(262144\) elementos em \(0,12\) segundos.
Nesse ponto sabemos o que fazer! Para poder utilizar a busca binária devemos ordenar o vetor com o mergesort, para que seja possível sobrar mais tempo para realizar as consultas.
Modificando o Código da Busca Bobinha para ordenar com MergeSort e realizar a busca binária, ficaria da seguinte forma:
1: #include <stdio.h> 2: #include <stdlib.h> 3: //Mergesort e Intercala OMITIDOS! Use a versão disponibilizada na Aula 3, seção 3.1 4: 5: int buscabinaria(int num,int *v,int l,int r) 6: { 7: if(l>r) return -1; 8: int meio=(l+r)/2; 9: if(less(v[meio],num)) 10: return achou(num,v,meio+1,r); 11: else if(lesseq(v[meio],num)) 12: return meio; 13: else 14: return achou(num,v,l,meio-1); 15: } 16: int main(void) 17: { 18: int vetor[140000]; 19: //preparando para gerar números aleatórios 20: srand(140000); 21: //preenchendo o vetor com números aleatórios inferiores a 1milhão 22: for(int i=0;i<140000;i++) 23: vetor[i]=rand()%1000000; 24: 25: //Tenha cuidado com a chamada do MergeSort, o intervalo é FECHADO [l,r] 26: //por isso é subtraído 1 do tamanho do vetor, para ficar [0,139999] 27: //que representa os 140000 elementos. 28: mergesort(vetor,0,140000-1); 29: 30: //fazendo 140000 buscas pelo número 1milhão 31: for(int i=0;i<140000;i++) 32: if(!buscabinaria(1000000,vetor,0,140000-1)) 33: printf("nao\n"); 34: else 35: printf("sim\n"); 36: } 37:
O código acima possui a implementação da BuscaBinária e utiliza o MergeSort implementado na Aula 3.
Seguimos a execução conforme abaixo:
ribas@jaguapitanga:/tmp$ make busca2 CFLAGS='-O2 -static' cc -O2 -static busca2.c -o busca2 ribas@jaguapitanga:/tmp$ time ./busca2 >/dev/null real 0m0.032s user 0m0.028s sys 0m0.005s
O que antes demorava mais de \(15\) segundos, passou a executar em apenas \(0,032\) segundos, bem abaixo do tempo limite estipulado no sistema MOJ.
Implementado um código que utiliza esta estratégia sai do custo de \(\mathcal{O}(N^2)\) operações para \(\mathcal{O}(N log{}(N) + N log{}(N))\), pois a ordenação fica em \(\mathcal{O}(N log{}(N)\), e a busca binária fica em \(\mathcal{O}(log{}(N))\), sendo executada \(N\) vezes, pois são feitas \(140000\) perguntas.
A busca que implementamos neste exercício mental trata de uma entrada próxima do pior caso, e que força uma implementação simples a ficar com custo proporcional a \(\mathcal{O}(N^2)\), enquanto que podemos implementar de uma maneira mais eficiente apenas pensando nos custos envolvidos.
1.5.4. LIVE síncrona
LIVE começando às 8h45
1.6. Aula 6 04_ago sanidade
Sem perder a SANIDADE, resolva os exercícios REMOÇÃO e SANIDADE que, dentre todas as listas, está disponível na lista abaixo.
1.6.1. Lista pública no CD-MOJ
- Resolva os exercícios propostos na lista Sanidade e Remoção
Para ganhar credenciais de acesso à lista, envie uma mensagem para @mojinhobot, no telegram AQUI, com o conteúdo:
participar bcr-EDA2-2021_1-sanidade-e-remocao
- Se você já conta para a outra lista (disponibilizada na Aula 1), pode utilizar as mesmas credenciais.
1.7. Aula 7 09_ago quicksort
Segue nesta seção um conjunto de vídeos a respeito do QuickSort, e que serão tema das próximas aulas, assista para que possamos elevar a discussão a respeito deste algoritmo.
1.7.1. Exercícios
- Lista pública no CD-MOJ
- Resolva os exercícios propostos na lista QuickSort
Para ganhar credenciais de acesso à lista, envie uma mensagem para @mojinhobot, no telegram AQUI, com o conteúdo:
participar bcr-EDA2-2021_1-quicksort
- Se você já conta para a outra lista (disponibilizada na Aula 1), pode utilizar as mesmas credenciais.
- Escreva o algoritmo da separação
- Escreva uma função que rearranje um vetor
v[p..r]
de inteiros de modo que tenhamosv[p..j-1] <=0
ev[j..r] > 0
para algumj
emp..r+1
.
- Faz sentido exigir que
j
esteja emp..r
? - Procure fazer uma função rápida que não use vetor auxiliar.
- Repita o exercício depois de trocar
v[j..r] > 0
porv[j..r] >=0
. - Faz sentido exigir que
v[j]
seja0
?
- Faz sentido exigir que
- Um vetor
v[p..r]
está arrumado se existej
emp..r
tal quev[p..j-1] <=v[j] < v[j+1..r]
. Escreva um algoritmo que decida sev[p..r]
está arrumado. Em caso afirmativo, o seu algoritmo deve devolver o valor dej
. - Um programador inexperiente afirma que a seguinte implementação da função de separação rearranja o vetor v[p..r], com p < r, e devolve um índice j em p..r-1 tal que v[p..j] <= v[j+1..r].
int sep( int v[], int p, int r) { int q, i, j, t; i = p; q = (p + r) / 2; j = r; do { while (v[i] < v[q]) ++i; while (v[j] > v[q]) --j; if (i <= j) { t = v[i], v[i] = v[j], v[j] = t; ++i, --j; } } while (i <= j); return i; }
Mostre um exemplo onde essa função não dá o resultado esperado. E se trocarmos
return i
porreturn i-1
? É possível fazer algumas poucas correções de modo que a função dê o resultado esperado? - Qual o resultado da função separa quando os elementos de
v[p..r]
são todos iguais? E quandov[p..r]
é crescente? E quandov[p..r]
é decrescente? E quando cada elemento dev[p..r]
tem um de dois valores possíveis? - A função separa produz um rearranjo estável do vetor, ou seja, preserva a ordem relativa de elementos de mesmo valor? HOT
- Escreva uma versão recursiva da função separa.
- Implemente o QuickSort
- Submeta o vetor
77 55 33 99
indexado por1..4
à função quicksort. Teremos a seguinte sequência de invocações da função (observe a indentação):
quicksort( v,1,4) quicksort( v,1,2) quicksort( v,1,0) quicksort( v,2,2) quicksort( v,4,4)
Repita o exercício com o vetor
55 44 22 11 66 33
indexado por1..6
. - A função quicksort produz uma ordenação estável do vetor?
- Escreva uma versão não recursiva do algoritmo Quicksort. sol
- Execute todas as variações do QuickSort distribuídas no Benchmark de Ordenação e reflita sobre os resultados
1.8. Aula 8 11_ago quickselect
1.9. Aula 9 16_ago quicksort_final
Implementação e resolução dos exercícios de Ordenação.
1.9.1. Cortes com problemas resolvidos
1.10. Aula 10 18_ago hash
1.10.1. Exercícios
- Veja o material sobre hash do Prof. Paulo Feofiloff
- Você consegue aplicar as ideias de HASH nos exercícios
Remoção
eSanidade
? - Você consegue aplicar as ideias de HASH no exercício
Eleição U.R.S.A.L
? - Considere as técnicas de busca sequencial, busca binária e busca baseada em hashing:
- Descreva as vantagens e desvantagens de cada uma dessas técnicas, indicando em que situações você usaria cada uma delas.
- Qual é a eficiência de utilização da memória (relação entre o espaço necessário para dados e o espeço total necessário) para cada método?
- Sobre Tabelas HASH:
- É possível criar uma função HASH em que é garantido que nunca haverá colisão? Porquê?
- Quando existe colisão, quais estratégias podem ser utilizadas para contornad esse problema? Quando cada estratégia é melhor utilizada?
- Resolva os exerícios DESTA PROVA hot
1.11. Aula 11 23_ago hash
1.11.1. Vídeos adicionais sobre HASH
Os alunos devem finalizar os vídeos sobre HASH disponibilizados na Aula 10.
1.11.2. Exercícios
- Você consegue aplicar os conhecimentos, adquiridos pelos vídeos acima, no problema
Desfile dos Patos
(em nossa segunda lista de presença). - Lista pública no CD-MOJ
Para ganhar credenciais de acesso à lista, envie uma mensagem para @mojinhobot, no telegram AQUI, com o conteúdo:
participar bcr-EDA2-2021_1-hash
- Se você já conta para a outra lista (disponibilizada na Aula 1), pode utilizar as mesmas credenciais.
- Imagine que você tenha um bug em sua implementação de tabela hash utilizando hash-dupla (double-hashing) de tal forma que a primeira ou a segunda função de hash retornam sempre o mesmo valor (porém diferente de \(0\)). Descreva o que ocorre (exemplo: os custos de inserção e busca permanecem o esperado?) quando:
- a primeira hash está errada;
- a segunda hash está errada;
- ambas funções hash estão erradas.
- Resolva o exerício HASHIT da lista de HASH no CD-MOJ
Veja a discussão deste exercício com o Monitor Felipe Borges
- Resolva o exercício Desfile dos Patos com o seguinte algoritmo
1.12. Aula 12 25_ago
Aula dedicada à resolução dos exercícios de HASH disponibilizados no MOJ.
1.13. Aula 13 30_ago
1.14. Aula 14 01_set árvore
A aula de hoje terá caráter assíncrono. Os alunos devem relembrar os conceitos de árvores binárias.
Já deixo separado e recomendado que vocês iniciem a leitura de:
1.14.1. Vídeos de apoio
1.14.2. Exercícios
- Lista pública no CD-MOJ
Para ganhar credenciais de acesso à lista, envie uma mensagem para @mojinhobot, no telegram AQUI, com o conteúdo:
participar bcr-EDA2-2021_1-arvorebinaria
- Se você já conta para a outra lista (disponibilizada na Aula 2), pode utilizar as mesmas credenciais.
- Tente resolver o exercício https://br.spoj.com/problems/PREEMPOS/
- Suponha que as chaves
50 30 70 20 40 60 80 15 25 35 45 36
são inseridas, nesta ordem, numa árvore de busca inicialmente vazia. Desenhe a árvore que resulta. prof_Feofiloff - Considere árvores binárias de busca cujos nós têm a estrutura indicada abaixo. prof_Feofiloff
Escreva uma função que receba a raiz de uma tal árvore e o endereço de um nó
x
e devolva o endereço do pai dex
.typedef struct reg { int chave; int conteudo; struct reg *esq, *dir; } noh;
[NÚMERO DE NÓS.]
Escreva uma função que calcule o número de nós de uma árvore binária. prof_Feofiloff[FOLHAS.]
Escreva uma função que imprima, em ordem in-order, os conteúdos das folhas de uma árvore binária. prof_Feofiloff- Dada uma árvore binária, encontrar um nó da árvore cujo conteúdo tenha um dado valor val. prof_Feofiloff
[VARREDURA r-e-d.]
Escreva uma função que faça a varredura r-e-d (varredura prefixa) de uma árvore binária. prof_Feofiloff[VARREDURA e-d-r.]
Escreva uma função que faça varredura e-d-r (varredura posfixa) de uma árvore binária. prof_Feofiloff- Escreva uma função para calcular a altura de uma árvore binária
- Escreva uma função que determine a profundidade de um nó dado. prof_Feofiloff
- Escreva uma função que decida se uma dada árvore binária é quase completa. prof_Feofiloff
1.15. Aula 15 06_set exercício
1.16. Aula 16 08_set exercícios
A aula de hoje é dedicada à resolução de exercícios relativos a árvores binárias e HASH.
1.17. Aula 17 13_set
1.17.1. Material de apoio
1.17.2. Exercícios
- Resolva os exercícios de PQ prof_Feofiloff
- (SW 9.1) Suponha que a sequência
P R I O * R * * I * T * Y * * * Q U E * * * U * E
é aplicada a uma PQ de máximo inicialmente vazia. Uma letra significa inserção e um asterisco significa remoção do máximo. Dê a sequência de letras produzida pelas remoções. Sedgewick - (SW 9.17) Um vetor em ordem decrescente é um heap decrescente? Um vetor em ordem crescente é um heap crescente? Sedgewick
- Insira os itens
E A S Y Q U E S T I O N
, nessa ordem, em um heap decrescente inicialmente vazio. Mostre o heap que resulta. Sedgewick - Escreva um método
isMaxHeap()
para verificar se o vetorpq[]
é um heap decrescente. O seu algoritmo deve consumir tempo linear. Repita para heap crescente. Sedgewick - Fila priorizada min/max. Projete um tipo-de-dados que dê suporte às seguinte operações: inserção, remoção do mínimo, remoção do máximo, encontrar o mínimo (sem remover), e encontrar o máximo (sem remover). As três primeiras operações devem consumir tempo logarítmico e as duas últimas devem consumir tempo constante. Dica: Use dois heaps. Sedgewick
- Escreva a API completa de Filas de Prioridade de maneira que ela suporte mais de um Fila de prioridades no seu programa
- Como você pode implementar um algoritmo de Ordenação utilizando o conceito de filas de prioridade?
- Rode o conjunto de benchmark de ordenação e idenfique o comportamento dos algoritmos HeapSort e PQsortsimple quando se comparado com o melhor quicksort e o mergesort
- O HeapSort é estável?
- Você é capaz de ressolver esta ISSUE?
- Qual implementação (em vetor ordenado ou não ordenado, com lista encadeada ordenada ou não ordenada, árvore binária em vetor) para encontrar os \(100\) menores elementos de um conjundo de \(10^6\) números aleatórios? Sedgewick
- Implemente e faça testes de desempenho
- Resolva o problema Classificados de Sementes utilizando os conceitos de fila de prioridades
- Você pode ler o Enunciado aqui
- O exercício pode ser resolvido na lista de exercícios de Quicksort
- É possível resolver o problema kk-página utilizando os conceitos de fila de prioridades?
- Você pode ler o Enunciado aqui
- O exercício pode ser resolvido na lista de exercícios de Quicksort
- Resolva o problema Eu posso advinhar a estrutura de dados! urionlinejudge
- Implemente a ADT de fila de prioridades para fazer a troca baseada em índice (como vimos no fim da última aula)
- Suponha que um vetor está preenchido com as seguintes chaves
E A S Y Q U E S T I O N
. Imprima o conteúdo do vetorpq
eqp
após a inserção dos elementos da fila de prioridades implementada no exercício 1.17.2.16 - Adicione a operação remover na sua implementação do problema 1.17.2.16
- esta função serve para quando se remover um elemento qualquer do vetor original
- Resolva o exercício Churrascarias da Avenida utilizando a implementação feita no exercício 1.17.2.16 spoj br
1.18. Aula 18 15_set
- Aula assíncona para assistir aos vídeos disponibilizados na aula 17 e resolução de exercícios
1.19. Aula 19 20_set
1.20. Aula 20 22_set
Veja no primeiro vídeo a explicação sobre a “fila de prioridades baseada em índice”, o vídeo possui os timestamps.
No segundo vídeo veja a explicação de alguns exercícios, mas veja depois de tentar resolver os problemas disponibilizados na Aula 17.
1.20.1. Exercícios
- Lista pública no CD-MOJ
Para ganhar credenciais de acesso à lista, envie uma mensagem para @mojinhobot, no telegram AQUI, com o conteúdo:
participar bcr-EDA2-2021_1-pq
- Se você já conta para a outra lista (disponibilizada na Aula 2), pode utilizar as mesmas credenciais.
1.21. Aula 21 27_set semana_academica
- Semana acadêmica, não haverá encontro.
1.22. Aula 22 29_set semana_academica
- Semana acadêmica, não haverá encontro.
1.23. Aula 23 06_out
1.23.1. Material de Apoio
1.23.2. TRABALHO 2 - EDAzinho da Dominação
1.24. Aula 24 04_out
1.25. Aula 25 11_out feriado
1.27. Aula 27 18_out
1.28. Aula 28 20_out
- aula assíncrona para os alunos desenvolverem o trabalho
1.28.1. Lista pública no CD-MOJ
Para ganhar credenciais de acesso à lista, envie uma mensagem para @mojinhobot, no telegram AQUI, com o conteúdo:
participar bcr-EDA2-2021_1-grafos
- Se você já conta para a outra lista (disponibilizada na Aula 2), pode utilizar as mesmas credenciais.
1.29. Aula 29 25_out
1.30. Aula 30 27_out
Exercícios de grafos. Dúvidas por e-mail.
1.31. Aula 31 01_nov feriado
1.32. Aula 32 03_nov
- Avaliação da disciplina com exercícios que podem abranger toda a
disciplina, no entanto será focado em grafos.
- Será no MOJ, com as duplas do T2 e acontecerá das 6:00 às 10:00.
2. Antes de Começar
Nesta disciplina é esperado que o aluno tenha conhecimento básico da
linguagem C
tais como:
- Ponteiros
- Strings
- Leitura da Entrada padrão
As subseções abaixo elencam alguns vídeos que recaptulam o conhecimento necessário.
2.1. Material no Youtube
Vídeos com material relacionado ao conteúdo esperado para uso na disciplina.
Tenho disponibilizado vários materiais em meu canal no YouTube, por favor, considere assinar o canal e deixar o joinha :)
2.1.1. Revisão de Ponteiros
Segue abaixo a playlist da revisão de ponteiros no Youtube. Por ora são 5 vídeos que exploram o que é necessário saber para a disciplina de EDA-2.
2.1.2. Strings em C
Aqui um apanhando geral em como se manipula strings na linguagem C. Em uma série que chamei de “Umas Palavras sobre String”
2.1.3. SCANF
O SCANF
é uma poderosa função capaz de ler dados da entrada padrão
(e de outros arquivos com suas aliases como fscanf(3)
.
Na série Detonando o SCANF temos, além do uso básico da função abordo algumas curiosidades sobre as funções.
3. Plano de Aulas
O plano de ensino e plano de aulas é um PLANO e pode sofrer modificações ao longo do semestre de acordo com o rendimento da turma.
Curso: | Engenharia de Software | Período Letivo | 2021/1 |
Disciplina: | Estrutura de Dados 2 | Código | |
Carga Horária: | 60 horas | Créditos | 04 |
3.1. Ementa
- Estruturas não-lineares. Árvores. Tabelas hash. Grafos
- Filas de prioridade. Heap
- Algoritmos de ordenação avançados \(\mathcal{O}(n\log{}n)\)
- Algoritmos de manupalição e análise de grafos
- Aplicações
3.2. Horários das aulas e atendimento
- Aulas:
- {segunda,quarta}-feira, das 8:00 às 9:50
- Atendimento:
- por e-mail nos dias e horário das aulas
- caso necessário será aberto uma CALL para sanar as dúvidas
- por e-mail nos dias e horário das aulas
- E-mail:
- bruno.ribas EM unb.br
- Página:
3.3. Método
Aula expositiva por meio de vídeos no Youtube (gravados ou em live stream), conversas periódicas em vídeo conferências com os alunos nos horários das aulas, quadro branco (representado pelo tablet), listas de exercícios.
3.4. Critérios de Avaliação
- A avaliação será feita por um conjunto de trabalhos com peso variável, ou seja, o primeiro trabalho tem peso 1, o segundo peso 2, e assim por diante.
- As notas serão compostas por um número inteiro no intervalo \([0,100]\);
- As avaliações serão compostas por questões, podendo ser, a
critério do professor, teóricas e/ou práticas
- O método de entrega será combina previamente com os alunos, podendo ser realizada por meio: do corretor automático MOJ; questionários no sistema SIGAA e/ou; submissão por e-mail para o professor;
- Qualquer tentativa de fraude nas provas implicará em média ZERO no semestre para todos os envolvidos.
3.4.1. Presença
A presença na disciplina se dará pela entrega das avaliações, listadas acima.
A entrega DENTRO do prazo é obrigatória para todos os alunos.
3.4.2. Menção Final
As notas serão calculadas conforme a equação abaixo:
\begin{align} M_F = \frac{ \sum_{i=1}^{N}{i \cdot A_i}}{\sum_{i=1}^{N}{i}} \end{align}3.4.3. Critérios de aprovação
Obterá aprovação no curso o aluno que cumprir todas as exigências listadas abaixo:
- \(M_F >= 50\); e
- Presença em \(75\%\) ou mais das aulas.
Por fim, a menção final do curso é dada de acordo com a tabela abaixo:
\(M_F\) | Menção | Descrição |
\(0\) | SR | Sem rendimento |
\([1,29]\) | II | Inferior |
\([30,49]\) | MI | Médio Inferior |
\([50,69]\) | MM | Médio |
\([70,89]\) | MS | Médio Superior |
\([90,100]\) | SS | Superior |
3.5. Cronograma
Data | Atividade |
Semanas {1,2,3} | Ordenação Elementar, QuickSort, MergeSort |
Semanas {4,5,6} | Hashing, Filas de Prioridades |
Semanas {7,8,9,10} | Heap, Árvores Balanceadas |
Semanas {11,12,13,14,15,16} | Grafos |
3.6. Bibliografia
- CORMEN, Thomas H.; LEISERSON, Charles E.; RIVEST, Ronald L.; STEIN, Cli or. Algoritmos: Teoria e Prática. 2a.edição, Campus.
- (eBrary) CORMEN, Thomas H.; LEISERSON, Charles E.; RIVEST, Ronald
- Introduction to Algorithms. MIT Press, 2014.
- (eBrary) MEHLHORN, K; SANDERS, P. Algorithms and Data Structures: The Basic ToolBox, 1st. ed. Springer, 2008.
- (open access) HALIM, Steve S; HALIM, Felix. Competitive Programming, 1st ed, Lulu, 2010.
- (eBrary) STEPHENS, Rod. Essential Algorithms: A Pratical Approach to Computer Algorithms. John Wiley Sons, 2013.
- (open access) AHO, A. V.; ULLMAN, J. D. Foundations of Computer
Science: C Edition (Principles of Computer Science Series), 1st ed.,
- H. Freeman, 1994.
4. Monitor
Em busca de um MONITOR.
5. Presença
- VAZIO
6. Notas
AVx
são as avaliaçõesPP
é a porcentagem de presença (consolidada nesta tabela no fim do semestre)- Na seção anterior você pode ver o acompanhamento das presenças
situação
é a situação final na disciplina, gerada após todas avaliações- As penalidades nas avaliações são relativas às chamadas ao
getlog
do MojinhoBot
matricula | PP | AV1 | AV2 | AV3 | MM | situacao | nome |
160000572 | 099= 099 | 100= 100 | 100= 100 | 99 | SS | ** | |
180011961 | 090= 090 | 100= 100 | 012= 012 | 54 | MM | ** | |
180030264 | 100= 100 | 100= 100 | 040= 040 | 70 | MS | ** | |
180098021 | 100= 100 | 000= 000 | 073= 073 | 53 | MM | ** | |
190024950 | 098= 098 | 000= 000 | 010= 010 | 21 | MI | ** | |
190025379 | 100= 100 | 100= 100 | 060= 060 | 80 | MS | ** | |
180074741 | 100= 100 | 100= 100 | 030= 030 | 65 | MM | ** | |
190056843 | 100= 100 | 100= 100 | 100= 100 | 100 | SS | ** | |
180118005 | 100= 100 | 100= 100 | 060= 060 | 80 | MS | ** | |
190011602 | 100= 100 | 100= 100 | 008= 008 | 54 | MM | ** | |
170139981 | 096= 096 | ** | 070= 070 | 51 | MM | ** | |
180015311 | 100= 100 | 100= 100 | 100= 100 | 100 | SS | ** | |
190042419 | 100= 100 | 000= 000 | 100= 100 | 66 | MM | ** | |
170161871 | 093= 093 | 100= 100 | 040= 040 | 68 | MM | ** | |
190012200 | 100= 100 | ** | 060= 060 | 46 | MI | ** | |
190012307 | 100= 100 | 100= 100 | 080= 080 | 90 | SS | ** | |
190027088 | 098= 098 | 000= 000 | 010= 010 | 21 | MI | ** | |
180119508 | 006= 006 | ** | ** | 1 | SR | ** | |
180016067 | 100= 100 | ** | 060= 060 | 46 | MI | ** | |
190027355 | 100= 100 | 100= 100 | 060= 060 | 80 | MS | ** | |
180113259 | 095= 095 | 100= 100 | 080= 080 | 89 | SS | ** | |
180063723 | 100= 100 | 000= 000 | 100= 100 | 66 | MM | ** | |
190106565 | 100= 100 | 100= 100 | 007= 007 | 53 | MM | ** | |
150125682 | ** | 100= 100 | ** | 33 | SR | ** | |
170103200 | 096= 096 | ** | 070= 070 | 51 | MM | ** | |
180100831 | 098= 098 | 100= 100 | 024= 024 | 61 | MM | ** | |
170011020 | 100= 100 | ** | ** | 16 | SR | ** | |
180017870 | 100= 100 | 100= 100 | 000= 000 | 50 | MM | ** | |
180101617 | 100= 100 | 000= 000 | 073= 073 | 53 | MM | ** | |
170034941 | 099= 099 | 100= 100 | 010= 010 | 54 | MM | ** | |
190014032 | 100= 100 | 100= 100 | 080= 080 | 90 | SS | ** | |
190046091 | 100= 100 | 100= 100 | 060= 060 | 80 | MS | ** | |
170034992 | 100= 100 | ** | ** | 16 | SR | ** | |
180018728 | 100= 100 | 100= 100 | 040= 040 | 70 | MS | ** | |
180102613 | 100= 100 | 100= 100 | 040= 040 | 70 | MS | ** | |
170069800 | 100= 100 | 000= 000 | 100= 100 | 66 | MM | ** | |
190030291 | 100= 100 | 070= 070 | 040= 040 | 60 | MM | ** | |
180102711 | 100= 100 | ** | 100= 100 | 66 | MM | ** | |
180123203 | 090= 090 | 100= 100 | 012= 012 | 54 | MM | ** | |
180103431 | 098= 098 | 100= 100 | 024= 024 | 61 | MM | ** | |
180103580 | 100= 100 | ** | 000= 000 | 16 | MI | ** | |
190046945 | ** | ** | ** | 0 | SR | ** | |
180022237 | 100= 100 | 100= 100 | 100= 100 | 100 | SS | ** | |
190032863 | 100= 100 | ** | 060= 060 | 46 | MI | ** | |
190033088 | 100= 100 | 100= 100 | 080= 080 | 90 | SS | ** | |
170016838 | 100= 100 | ** | 060= 060 | 46 | MI | ** | |
180105604 | 100= 100 | 100= 100 | 040= 040 | 70 | MS | ** | |
190113031 | 000= 000 | ** | ** | 0 | SR | ** | |
190134623 | ** | ** | ** | 0 | SR | ** | |
180145231 | 000= 000 | ** | ** | 0 | SR | ** | |
180127535 | 100= 100 | 100= 100 | 100= 100 | 100 | SS | ** | |
180024868 | 100= 100 | 100= 100 | 010= 010 | 55 | MM | ** | |
190055201 | 100= 100 | 100= 100 | 060= 060 | 80 | MS | ** | |
150141629 | 100= 100 | 100= 100 | 000= 000 | 50 | MM | ** | |
170111288 | 100= 100 | 100= 100 | 060= 060 | 80 | MS | ** | |
190129221 | 098= 098 | 100= 100 | 010= 010 | 54 | MM | ** | |
190058650 | 100= 100 | 000= 000 | 100= 100 | 66 | MM | ** | |
140156909 | 060= 060 | ** | ** | 10 | SR | ** | |
190047968 | 100= 100 | 100= 100 | 100= 100 | 100 | SS | ** | |
190036435 | 100= 100 | 070= 070 | 040= 040 | 60 | MM | ** | |
170153975 | 100= 100 | ** | 040= 040 | 36 | MI | ** | |
190098287 | 090= 090 | 100= 100 | 010= 010 | 53 | MM | ** | |
180011308 | 100= 100 | 100= 100 | 060= 060 | 80 | MS | ** | |
180108344 | 095= 095 | 100= 100 | 080= 080 | 89 | SS | ** | |
190019085 | 100= 100 | 100= 100 | 080= 080 | 90 | SS | ** | |
170021581 | 093= 093 | 100= 100 | 040= 040 | 68 | MM | ** | |
190048221 | 100= 100 | 000= 000 | 040= 040 | 36 | MI | ** | |
180037242 | 100= 100 | 100= 100 | 060= 060 | 80 | MS | ** | |
180130889 | 100= 100 | 100= 100 | 100= 100 | 100 | SS | ** | |
170045943 | ** | ** | ** | 0 | SR | ** | |
180028260 | 100= 100 | 100= 100 | 040= 040 | 70 | MS | ** | |
170114929 | 090= 090 | 070= 070 | 060= 060 | 68 | MM | ** | |
190020377 | 100= 100 | 100= 100 | 100= 100 | 100 | SS | ** | |
190055294 | 100= 100 | 100= 100 | 008= 008 | 54 | MM | ** | |
190038969 | 100= 100 | 000= 000 | 040= 040 | 36 | MI | ** | |
180149598 | 000= 000 | ** | ** | 0 | SR | ** | |
190044390 | 100= 100 | 100= 100 | 010= 010 | 55 | MM | ** | |
190044403 | 100= 100 | 100= 100 | 080= 080 | 90 | SS | ** | |
190020903 | 100= 100 | 100= 100 | 080= 080 | 90 | SS | ** | |
180029223 | 100= 100 | 100= 100 | 080= 080 | 90 | SS | ** | |
180029240 | 000= 000 | ** | ** | 0 | SR | ** | |
180145363 | 090= 090 | 100= 100 | 010= 010 | 53 | MM | ** | |
160149410 | 100= 100 | 100= 100 | 100= 100 | 100 | SS | ** | |
180078640 | 100= 100 | 100= 100 | 030= 030 | 65 | MM | ** | |
média | ** | 92 | 82 | 54 | ** | ** | Média da turma |