Você está na página 1de 13

UNIVERSIDADE FEDERAL DO AMAPÁ

PROGRAMAÇÃO 2023.2

CLEBERTE DE LIMA PIMENTA


ELIANDRO DA SILVA DA CONCEIÇÃO
MIGUEL PEREIRA FERNANDES
WILLIAM ALFAIA DOS SANTOS

RELATÓRIO SOBRE ORDENAÇÃO

MACAPÁ
2023
CLEBERTE DE LIMA PIMENTA
ELIANDRO DA SILVA DA CONCEIÇÃO
MIGUEL PEREIRA FERNANDES
WILLIAM ALFAIA DOS SANTOS

RELATÓRIO SOBRE ORDENAÇÃO

Relatório apresentado ao professor Dr,


Julio Furtado, como requisito parcial da
disciplina de Programação 2, do curso
bacharelado em Ciência da Computação
da Universidade Federal do Amapá –
UNIFAP

MACAPÁ
2023
Questão 1. Implemente em uma linguagem de programação a sua escolha o
algoritmo de ordenação QuickSort com o pivôˆ sendo o elemento do meio.
Em seguida, trabalhe os itens abaixo:
a. Use uma sequência aleatória de números inteiros entre 1 e 100000 1
como entrada do algoritmo implementado e apresente a sequência ordenada
como saída.

b. Qual é a complexidade no tempo do algoritmo implementado? Explique.


Será respondido na letra d)
c. Compare o tempo de execução do algoritmo quando o mesmo recebe
como entrada sequências ordenadas (em ordem crescente e decrescente) e
desordenadas. Caso mais números fossem inseridos nas sequências, como o
desempenho do algoritmo seria afetado? Usando dados reais, ilustre
graficamente suas conclusões.
Será respondido na letra d)

d. Faça um estudo comparativo do algoritmo HeapSort implementado com


os algoritmos QuickSort, usados na Questão 1, nas situações apresentadas.
O presente estudo busca realizar uma análise comparativa entre duas
variantes do algoritmo de ordenação Quick sort, uma sendo o pivô o
elemento central do vetor e a outra com o pivô sendo um elemento
aleatório.
Quando o pivô é o elemento do meio, o algoritmo consegue dividir o vetor
em duas partes praticamente iguais em cada iteração, o que leva a um
equilíbrio na altura da árvore de recursão.
O motivo pelo qual isso resulta em uma complexidade de Θ(n log n) está
relacionado à natureza da árvore de recursão gerada pelo QuickSort. Cada
nível da árvore representa uma partição do vetor, e a altura da árvore é
determinada pelo número de partições necessárias para reduzir o vetor a
casos base individuais (vetores de tamanho um).
Ao escolher o pivô no meio, a cada iteração, o vetor é dividido em duas
partes, aproximadamente pela metade. Dessa forma, a altura da árvore de
recursão é limitada a log n, onde n é o tamanho do vetor. Em cada nível da
árvore, todas as n partições podem ser processadas, resultando em uma
complexidade total de Θ(n log n).
Essa escolha estratégica do pivô, ao garantir uma divisão balanceada do
vetor, contribui para um desempenho eficiente do QuickSort em diversos
cenários, tornando-o particularmente adequado para grandes conjuntos de
dados.
Quando o pivô é escolhido de forma aleatória, a complexidade do
QuickSort permanece predominantemente em Θ(n log n). A adoção dessa
abordagem tem como objetivo diminuir situações em que a escolha
determinística do pivô poderia resultar em casos extremos, como em
conjuntos de dados ordenados.
Ao escolher aleatoriamente o pivô em cada chamada recursiva, o algoritmo
reduz a probabilidade de encontrar conjuntos de dados específicos que
levariam ao pior desempenho. Mesmo que, ocasionalmente, um pivô
escolhido aleatoriamente possa coincidentemente pertencer ao pior caso, a
probabilidade disso ocorrer é baixa.
A independência na escolha do pivô em cada iteração é crucial. Essa
independência significa que o algoritmo não é suscetível a padrões
específicos nos dados, como seria o caso em uma escolha determinística do
pivô. Isso garante uma distribuição mais uniforme das partições ao longo
do processo de ordenação, contribuindo para o desempenho eficiente do
QuickSort.
Comparando os dois algoritmos nas situações apresentadas, pode-se notar
em questão de tempo de execução que o algoritmo tendo o pivô como
elemento aleatório teve um desempenho pior nos três casos (elementos em
ordem crescente, decrescente e desordenados) em relação ao com pivô
sendo o elemento central.
Em relação ao quesito estabilidade, os dois algoritmos são instáveis, ou
seja, quando dois elementos têm chaves iguais, a ordem original entre eles
não é preservada na saída ordenada.
Segue abaixo os gráficos usados para o estudo:
Questão 2. Implemente em uma linguagem de programac¸a˜o a sua escolha
o algoritmo de ordenação HeapSort. Em seguida, trabalhe os itens abaixo:
a. Use uma sequência aleatória de números inteiros entre 1 e 100000 como
entrada do algoritmo implementado e apresente a sequência ordenada como
saída.
b. Qual é a complexidade no tempo do algoritmo implementado? Explique.
Será respondido na letra d)
c. Compare o tempo de execução do algoritmo quando o mesmo recebe
como entrada sequências ordenadas (em ordem crescente e decrescente) e
desordenadas. Caso mais números fossem inseridos nas sequências, como o
desempenho do algoritmo seria afetado? Usando dados reais, ilustre
graficamente suas conclusões.
Será respondido na letra d)
d. Faça um estudo comparativo do algoritmo HeapSort implementado com
os algoritmos QuickSort, usados na Questão 1, nas situações apresentadas.
O presente estudo busca realizar uma análise comparativa entre duas
variantes do algoritmo Quick Sort (Pivô central e Pivô aleatório) e o
algoritmo Heap Sort.

O Heap Sort e o Quick Sort são algoritmos de ordenação com


complexidades distintas. O Heap Sort mantém uma complexidade
constante de O(n log n) em todos os cenários, enquanto o Quick Sort com
pivô central pode degradar para O(n^2) no pior caso, embora sua média
seja O(n log n). O Quick Sort com pivô aleatório reduz a probabilidade do
pior caso, mantendo a média em O(n log n). O Heap Sort é mais estável em
termos de desempenho, adequado quando a consistência é crucial, enquanto
o Quick Sort pode ser preferido em cenários onde um desempenho médio
superior é mais valorizado, apesar da sensibilidade à escolha do pivô.
Ambos não são estáveis, e a escolha entre eles dependerá das
características específicas do conjunto de dados e dos requisitos do
contexto de aplicação.
Comparando os algoritmos em termos de tempo de execução, pode-se
perceber que o Heap sort tem uma grande desvantagem, enquanto todos os
gráficos do Heap sort apresentam um tempo mínimo de execução de 300
milissegundos, o quick sort em suas duas variantes não ultrapassa 250
milissegundos. Entretanto, no quesito consistência o Heap sort leva uma
grande vantagem contra o quick sort, apresentando poucas flutuações
conforme a inserção de novos dados, apenas quando os dados são dispostos
de forma aleatória que a consistência dos três algoritmos se mantem
similares.

Em resumo, a decisão sobre qual algoritmo é mais adequado dependerá das


particularidades do problema, dos requisitos de desempenho e das
características dos dados a serem ordenados. Cada um dos três algoritmos
tem suas vantagens e desvantagens, sendo crucial uma análise cuidadosa
por parte do usuário, levando em consideração o contexto de aplicação.
Segue abaixo os gráficos usados como referência:
Questão 3. Implemente em uma linguagem de programação a sua escolha
os algoritmos de ordenação linear CountingSort e RadixSort. Em seguida,
trabalhe os itens abaixo:
a. Analise o comportamento do tempo de execução do algoritmo
CountingSort quando o número de elementos da sequência de entrada e´
aumentado gradativamente. Durante a análise, comente a relação que existe
entre o tamanho da sequência de entrada e o elemento de maior valor nessa
sequência. Usando dados reais, ilustre graficamente suas conclusões.

Analisando o gráfico abaixo, observa-se que a medida que o tamanho da


sequência é aumentado gradativamente o tempo de execução não é tão
afetado, isso porquê o Couting Sort é linear em termos de tempo (O(n +
k)), onde “n” é o número de elementos da sequência e “k” é a diferença
entre o valor máximo e mínimo. Portanto, mesmo que a sequência de
entrada seja pequena e o valor máximo seja um elemento muito grande, o
algoritmo ainda pode ter um desempenho eficiente, desde que a diferença
entre o menor e o maior valor seja relativamente pequena.
No gráfico pode-se observar que mesmo que os valores máximos entre 1,
10, 1000 e 5000 sejam distantes um entre o outro, os seus tempos de
execução ainda permaneceram semelhantes, inclusive o tempo dos valores
de 1, 100 e 1000 tiveram tempos de execução iguais.
b. Faça um estudo comparativo do tempo de execução do algoritmo
CountingSort com as implementações do QuickSort, feitas na Questão 1,
em situações reais (praticas) de uso. Explique qual algoritmo e´ mais
eficiente e por que.
O presente estudo busca realizar uma análise comparativa entre duas
variantes do algoritmo Quick Sort (Pivô central e Pivô aleatório) e o
algoritmo Couting Sort.

O Counting Sort e o Quick Sort são algoritmos de ordenação com


características distintas. O Counting Sort mantém uma complexidade linear
de O(n + k), onde "n" é o número de elementos a serem ordenados e "k" é o
intervalo de valores possíveis. Em contraste, o Quick Sort, com pivô
central, pode degradar para O(n^2) no pior caso, embora sua média seja
O(n log n). O Quick Sort com pivô aleatório reduz a probabilidade do pior
caso, mantendo a média em O(n log n).
O Counting Sort é particularmente eficiente quando lidamos com conjuntos
de dados pequenos e com intervalos de valores limitados, proporcionando
um desempenho constante. Por outro lado, o Quick Sort é vantajoso em
cenários onde se valoriza um desempenho médio superior, apesar de sua
sensibilidade à escolha do pivô.
Ambos os algoritmos não são estáveis em termos de ordenação. A escolha
entre Counting Sort e Quick Sort dependerá das características específicas
do conjunto de dados e dos requisitos do contexto de aplicação. O Counting
Sort é uma escolha sólida para conjuntos de dados com valores restritos,
enquanto o Quick Sort pode ser preferido em situações que exigem um
desempenho médio superior em um contexto mais amplo.
Um exemplo de situação real onde o Couting Sort seria mais vantajoso,
seria no caso de ordenação de notas, como pode-se observar no gráfico
abaixo:
c. Usando o algoritmo RadixSort, ordene os CEPS de Belém. Especifique o
algoritmo de ordenação estável utilizado na implementação. Durante a
tarefa, analise o comportamento do tempo de execução a medida que a
quantidade de CEPS e´ aumentada na sequência de entrada. Usando dados
reais, ilustre graficamente suas conclusões.
A eficácia do algoritmo Radix Sort utilizado neste exemplo é garantida pela
sua característica de estabilidade, empregando o algoritmo de ordenação
estável Counting Sort. A estabilidade assegura que, em situações de
empate, a ordem relativa entre os elementos seja mantida.
Durante a expansão do conjunto de dados com a inclusão de novos CEPs,
observamos um aumento gradual no tempo de execução do algoritmo. Este
comportamento evidencia a necessidade de considerar a performance dos
algoritmos de ordenação em conjuntos de dados específicos. Adaptações na
escolha do algoritmo são essenciais para otimizar o desempenho em
conformidade com as características particulares de cada problema.
Com base nos resultados obtidos, concluímos que o algoritmo Radix Sort,
ao empregar o Counting
Sort como algoritmo de
ordenação estável,
demonstra um
desempenho satisfatório
na ordenação dos CEPs
de Belém. No entanto, é
importante ressaltar que
o tempo de execução apresenta um crescimento gradual à medida que a
quantidade de CEPs na entrada é incrementada. Esta análise ressalta a
importância da escolha cuidadosa do algoritmo de ordenação, considerando
o cenário específico de aplicação.
Segue abaixo o gráfico usado como referência:

Você também pode gostar