Escolar Documentos
Profissional Documentos
Cultura Documentos
E2 Coal
E2 Coal
ALGORITMOS
Ariel Da Silva Dias
Sumário
INTRODUÇÃO������������������������������������������������� 3
ALGORITMO CONSTANTE����������������������������� 5
ALGORITMO LINEAR�������������������������������������� 8
ALGORITMO LOGARÍTMICO������������������������ 12
ALGORITMO QUADRÁTICO�������������������������� 19
ALGORITMO EXPONENCIAL������������������������ 23
RECORRÊNCIAS������������������������������������������� 25
Função recursiva direta������������������������������������������������������ 28
Função recursiva indireta��������������������������������������������������� 30
CONSIDERAÇÕES FINAIS���������������������������� 32
2
INTRODUÇÃO
Ao nos depararmos com um problema computa-
cional, podemos projetar várias soluções, ou seja,
desenvolvemos diversos algoritmos e escolhemos
aquele que seja mais eficiente dentre os algoritmos
desenvolvidos.
3
da (n) e um número de operações realizadas (N)
em relação ao tempo. Essa relação é denotada
como Ordem de crescimento na complexidade de
Tempo e dada a notação O[n], em que O é a ordem
de crescimento e n é o comprimento da entrada.
4
ALGORITMO CONSTANTE
Diz-se que um algoritmo tem tempo constante com
ordem O(1) quando não depende do tamanho da
entrada n, ou seja, independentemente do tamanho
de entrada n, o tempo de execução será sempre o
mesmo. Observe um exemplo na tabela 1.
5
Tabela 2: algoritmo para retornar o primeiro inteiro de um
vetor
1 int primeiroElemento(int vet[]){
2 return vet[0];
3 }
6
Figura 1: algoritmo de tempo constante
O(1)
4,5
4
Número de Operações
3,5
3
2,5
2
1,5
1
0,5
0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Tamanho dos dados de entrada
7
ALGORITMO LINEAR
Diz-se que um algoritmo tem uma complexidade
de tempo linear quando o tempo de execução au-
menta linearmente com o comprimento da entrada.
Quando a função envolve a verificação de todos
os valores nos dados de entrada, tal função tem
complexidade de tempo com ordem O(n) . Observe
um código de exemplo na tabela 3.
8
soma que recebe ela própria e adiciona o valor do
vetor na posição i.
9
Tabela 4: pesquisa sequencial de um valor k no vetor
1 int pesquisaSequencial(int arr[], int k) {
2 for(int i=0; i<n; i++)
3 if(arr[i] == k)
4 return 1;
5 return 0;
6 }
10
Figura 2: algoritmo de tempo linear
O(n)
250
Número de Operações
200
150
100
50
0
10 20 30 40 50 60 70 80 90 100 110120130140150160170180 190200
Tamanho dos dados de entrada
11
ALGORITMO LOGARÍTMICO
Para falarmos dos algoritmos logarítmicos, pri-
meiramente vamos abordar um dos tipos mais
clássicos de algoritmo: a busca binária. Isso será
feito pois, em qualquer sistema computacional, a
busca é uma das funcionalidades mais críticas a
serem desenvolvidas. As técnicas de pesquisa são
usadas em recuperações de arquivos, indexação
e muitas outras aplicações. Existem muitas técni-
cas de pesquisa disponíveis e a técnica de busca
binária é uma das mais utilizadas.
12
y Se o valor desejado for igual ao valor do índice
central, o índice será retornado como resposta;
y Se o valor de destino for menor que o índice
central da lista, o lado direito da lista será ignorado;
y Se o valor desejado for maior que o valor do
índice central, a metade esquerda é descartada;
13
da direita. Teremos então um novo subvetor for-
mado pelos valores 23 e 27.
3 6 7 8 14 15 23 27
início meio fim
14 15 23 27
início/meio fim
23 27
27
14
Observe pela figura 3 que, para um vetor com n=8
foram necessárias três instruções de divisão desse
vetor até encontrarmos o valor 27. Logo, o tempo
de complexidade é de 3 UT (unidades de tempo).
Observe agora a figura 4, que demonstra o mesmo
algoritmo para encontrar o valor 27, porém agora
em um vetor com n=4 e outro vetor com n=2.
3 7 14 27 3 27
início/meio fim
(a) 14 27 (b) 27
27
15
4 2 4
8 3 8
Log ou O (log n)
2
16
Por outro lado, em uma busca sequencial, o número
de iterações (passos) dentro do vetor será sempre
relacionado a n e, por esse motivo, uma busca
sequencial é categorizada como O(n).
FIQUE
SAIBAATENTO
FIQUE ATENTO
REFLITA
MAIS
17
Figura 5: algoritmo de tempo logarítmico
O(log n)
9
8
Número de Operações
7
6
5
4
3
2
1
0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
18
ALGORITMO QUADRÁTICO
Um dado algoritmo tem uma complexidade de
tempo não linear (ou quadrática) quando o tempo
de execução aumenta não linearmente, ou seja,
(n2), com o comprimento da entrada. Geralmente,
os loops aninhados estão nessa ordem de comple-
xidade de tempo, em que um loop leva O(n) e se a
função envolve um loop dentro de um loop, então
ela vai para O(n) * O(n) = O(n2) iterações.
19
Observe na tabela 7 que na linha 3 temos uma
estrutura de repetição for que percorrerá o vetor de
0 até n, ou seja, até o tamanho máximo do vetor.
Dentro desse laço de repetição, na linha 4, temos
outro laço for que inicia em 0 e percorrerá o vetor
até o final do vetor arr.
20
No algoritmo da tabela 8, temos um for na linha 3
que itera n vezes a linha 4. Por outro lado, temos
um for na linha 2 que itera por n vezes o for da
linha 3. Por fim, temos um for na linha 1 que itera
por n vezes o for da linha 2. Observe que um for
é dependente direto de outro for. Deste modo, a
função de complexidade é O(n3).
21
Figura 6: algoritmo de tempo quadrático
O(n 2 )
45000
40000
35000
30000
25000
25000
15000
10000
5000
0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
22
ALGORITMO
EXPONENCIAL
Em algoritmos de tempo exponencial, a taxa de
crescimento dobra a cada adição à entrada (n),
geralmente iterando por todos os subconjuntos dos
elementos de entrada. Sempre que uma unidade
de entrada aumenta em 1, o número de operações
executadas será dobrado. Note então que a com-
plexidade exponencial não pode ser considerada
eficiente porque vários recursos são necessários
para aumentar o tamanho da entrada.
FIQUE
SAIBAATENTO
FIQUE ATENTO
REFLITA
MAIS
23
Desse modo, assim como na complexidade de
tempo quadrático, você deve evitar algoritmos com
tempos de execução exponenciais, pois eles não
são bem dimensionados.
24
RECORRÊNCIAS
A recursão é uma abordagem para resolver proble-
mas em que a solução depende das soluções de
instâncias menores ou subproblemas do mesmo
problema. Assim, em programação, uma função
que chama a si mesma repetidamente (pode ser
uma chamada única) é chamada de função Recur-
siva. Resumidamente, uma relação de recorrência
ou recursividade é uma equação que define uma
sequência em que qualquer termo é definido em
termos de seus termos anteriores.
25
y Não sei quanto é 4!, mas sei que é o mesmo
que 4x3!;
y Não sei quanto é 3!, mas sei que é o mesmo
que 3x2!;
y Não sei quanto é 2!, mas sei que é o mesmo
que 2x1!.
26
Figura 7: cálculo recursivo
Fatorial (6)
retorna 720
Fatorial (5)
retorna 120
Fatorial (4)
retorna 24
Fatorial (3)
retorna 6
Fatorial (2)
retorna 2
Fatorial (1)
retorna 1
caso base
retorna 1
27
era retornado para cada uma das chamadas an-
teriores até se obter o resultado de 6!.
28
y Recursão sem cauda: uma função recursiva é
considerada sem cauda se a chamada recursiva
para a mesma função não for a última instrução ou
a última etapa processada pela função, isso quer
dizer que depois de retornar da pilha de chamadas,
resta algum código para avaliar. No caso de uma
função, a chamada recursiva é a primeira instrução
a ser processada pela função – tal tipo de recursão
é denominado como recursão de cabeça, pois é
a primeira chamada e não há nenhuma chamada
recursiva antes dela;
y Recursão em árvore: recursão na qual a função
chama a si mesma por mais de uma vez dentro de
seu bloco. Se a chamada for feita apenas uma vez
dentro do bloco de função, ela será chamada de
Recursão Linear, se for chamada mais vezes, será
Recursão em Árvore. Um exemplo famoso desse
tipo de recursão está no problema do enésimo
número de Fibonacci, em que, dado um número,
temos que encontrar o enésimo valor do termo na
série de Fibonacci.
29
5 return funcao(num-1);
6 }
Fonte: elaborado pelo autor.
30
Tabela 11: exemplo de recursão indireta
1 int funcA(int num){
2 if(num == 0)
3 return 0;
4 Else
5 return funcB(num - 1);
6 }
7 int funcB(int num2){
8 return funcA(num2 - 1);
9 }
31
CONSIDERAÇÕES FINAIS
Neste e-book você pôde compreender os diferentes
tipos de notação de complexidade de tempo dos
algoritmos. Inicialmente você conheceu a notação
de tempo constante, em que o valor da entrada
não varia no decorrer do tempo. Tal notação é
representada por 0(1).
32
Por fim, pôde conhecer sobre recursividade, sua
aplicação e os diferentes tipos de recursão exis-
tentes no desenvolvimento de algoritmos.
33
Referências Bibliográficas
& Consultadas
BORIN, V. P. Estrutura de dados. Curitiba:
Contentus, 2020. [Biblioteca Virtual].