Página anterior Voltar ao início do trabalhoPágina seguinte 

 

1.2. Novo custo

Claro que continua uma função linear, não houve nenhuma grande mudança. Os dois continuam com a mesma ordem de crescimento e tal... comparado com é uma diferença pequena, mas essa solução ficou bem mais elegante. Poxa, diminuímos o custo do algoritmo em ! Hehehe...

Agora, antes de continuar, só vamos definir a notação assintótica desse nosso novo custo!

A fórmula do é:

Substituindo pela nossa função, temos: . É trivial, que podemos escolher para as duas constantes e para . Com isso pretendi mostrar-lhes uma conclusão óbvia que no outro artigo não tinha mostrado para não complicar muito: uma função reta (linear) pertence sempre a notação e uma função quadrática pertence sempre a notação (ora, façam um gráfico das funções e vejam se isso não é óbvio!). Mas vamos aprendendo mais sobre análise de algoritmos com o tempo...

Bom... Continuando com a recursão... Nossa função cria um loop consigo mesma, ao invés de usar um para (for) ou enquanto (while). Ela se repete diminuindo um de a cada iteração, até que chegue ao valor mínimo aonde a resposta é trivial: .

O que é necessário para criarmos uma recursão? Apenas um ponto de parada! Temos que tomar cuidado para não criarmos loops infinitos cuidando sempre com cada entrada que o usuário pode colocar. Nesse caso, eu determinei que o domínio da função é . Se o cara colocasse , minha função iria diminuindo infinitamente... e nunca iria retornar nada!

Para fazer a recursão portanto, precisamos analisar o domínio de nossa função e mais: precisamos conhecer um valor (que vai ser o limite; no caso do fatorial, o valor que sabíamos é que ).

Acredito que vocês tenham achado tudo simples e que não tenham problema com isso. Funções recursivas vão ser extremamente úteis para nós nos próximos artigos. Vou finalizar mostrando-lhes alguns casos básicos de algoritmos em que podemos usar a recursão:

1.3. Números de Fibonacci

1. função fibonacci (n)

2. se , então

3. retorna

4. senão

5. retorna

6. fim-se

7. fim-função

Domínio de fibonacci(n):

Depois descobriremos como calcular os números de Fibonacci mais rápido, mas por enquanto nosso objetivo é a recursão!

1.4. Substituir um loop

Vamos supor que você quer imprimir os números de n a 1 e esqueceu a sintaxe do para...

1. função imprime_ate (n)

2. imprima

3. se , então

4. imprime_ate(n-1)

5. fim-se

6. fim-função

Domínio de imprime_ate(n):

Todo loop pode ser uma recursão e tem alguns que ficam bem mais fáceis se forem! Nesse caso, é claro que seria mais simples usarmos um para!

1.5. Outros exemplos

  • Ordenação por Intercalação (Merge Sort)
  • Busca em Profundidade (Depth-First Search) em Grafos
  • Função liveSearchS() em JavaScript do site em que você está agora... Veja você mesmo!
  • ... entre vários outros casos!

Vamos trabalhando com eles com o tempo...

2. Ordenação

Este mini-artigo é o sexto da Série Algoritmos. Se você ainda não leu os artigos anteriores, sugiro que leia antes de continuar:

  • Parte 1: O que é um algoritmo?
  • Parte 2: Como representar um algoritmo?
  • Parte 3: Qual a utilidade do algoritmo?
  • Parte 4: Análise de Algoritmos
  • Parte 5: Recursão

Neste artigo, iremos começar a estudar a ordenação de vetores. Aí vocês poderiam me perguntar: Por que a ordenação é importante? ou Por que começar com a ordenação? Por isso, resolvi antes de iniciar nos algoritmos de ordenação criar um artigo light para explicar no que consiste um vetor, o que é a ordenação e pra quê ela serve. Se isso tudo é óbvio pra você, espere... O próximo artigo chegará em breve!

2.1. O que é um vetor?

Vetor é uma estrutura de dados que serve para substituir várias variáveis. Para um problema pequeno onde desejo armazenar dois inteiros e tirar o MMC deles eu posso usar duas variáveis: n1 e n2. Mas existem casos em que seria um número muito grande de variáveis (e em alguns deles nem sabemos ao certo, porque faremos uma alocação a partir de um número que o usuário pedir), por isso vetores são extremamente úteis.

2.2. No que consiste a ordenação?

Os algoritmos de ordenação tem como objetivo permutar uma seqüência de forma que . A ordenação não precisa ser exatamente de um vetor, mas vetor é geralmente a estrutura que usamos para guardar uma lista de números para podermos ordená-los.

2.3. Por que ordenar?

Nessa parte, vou plagiar o Cormen...

  • Às vezes, a necessidade de ordenar informações é inerente a uma aplicação. Por exemplo, para preparar os extratos de clientes, os bancos precisam ordenar os cheques pelo número do cheque.
  • Os algoritmos freqüentemente usam a ordenação como uma sub-rotina chave. Por exemplo, um programa que apresenta objetos gráficos dispostos em camadas uns sobre os outros talvez tenha de ordenar os objetos de acordo com uma relação "acima", de forma a poder desenhar esses objetos de baixo para cima.
  • Existe uma ampla variedade de algoritmos de ordenação, e eles empregam um rico conjunto de técnicas. De fato, muitas técnicas importantes usadas ao longo do projeto de algoritmos são representadas no corpo de algoritmos de ordenação que foram desenvolvidos ao longo dos anos. Desse modo, a ordenação também é um problema de interesse histórico.

2.4. Algoritmos que iremos estudar

Eu planejo passar três algoritmos nos próximos artigos. São eles:

  • Ordenação por Inserção (Insertion Sort)
  • Ordenação por Seleção (Selection Sort)
  • Ordenação por Intercalação (Merge Sort)

Acho que é mais interessante não entrarmos no Heap Sort, no Quick Sort e outros algoritmos até mais rápidos, porque suas implementações são um pouco complexas demais para o objetivo dessa série. Mas quem sabe depois de tudo estar pronto, eu mude de idéia. Ou se vocês acharem realmente importante, dêem um toque!

3. Ordenação por Inserção

Este artigo é o sétimo da Série Algoritmos. Se você ainda não leu os artigos anteriores, sugiro que leia antes de continuar:

  • Parte 1: O que é um algoritmo?
  • Parte 2: Como representar um algoritmo?
  • Parte 3: Qual a utilidade do algoritmo?
  • Parte 4: Análise de Algoritmos
  • Parte 5: Recursão
  • Parte 6: Ordenação

Também conhecida como Insertion Sort, a Ordenação por Inserção consiste em inserir um elemento num vetor já ordenado de elementos. Neste artigo, apresento-lhes este simples algoritmo para ordenação de vetores.

O pseudocódigo da ordenação por inserção é o seguinte:

1. para j 2 até comprimento do vetor, faça

2. elemento vetor[j]

3. i j - 1

4. enquanto i > 0 e vetor[i] > elemento, faça

5. vetor[i + 1] vetor[i]

6. i i - 1

7. fim-enquanto

8. vetor[i + 1] elemento

9. fim-para

Para explicar eu vou fazer uma coisa que sempre faço para corrigir meus algoritmos, fingir que sou o programa, executando cada passo manualmente (claro que geralmente faço mais rápido, porque não preciso escrever tudo que faço). Vamos iniciar com o seguinte vetor v.

v[1]

v[2]

v[3]

v[4]

v[5]

v[6]

5

3

7

8

2

5

Aí o código me manda começar com e iterar até o comprimento do vetor (6). A primeira ordem que ele me dá é para armazenar o elemento () na variável elemento. Para facilitar toda a explicação eu vou sempre pintar de cinza o onde eu estou (no caso, o segundo elemento do vetor, 3) e de preto o vetor ainda não ordenado (elementos ).

v[1]

v[2]

v[3]

v[4]

v[5]

v[6]

5

3

7

8

2

5

Então ele me diz que . Portanto, . E agora ele me faz um enquanto (que poderia ser substituído por para) onde meu i deverá ir diminuindo. Vamos entrar no loop...

Bom, meu é maior que 0. é maior que o ? Sim, então vamos entrar no corpo do enquanto... Aqui ele me manda fazer um , que nesse caso é fazer um .

v[1]

v[2]

v[3]

v[4]

v[5]

v[6]

5

5

7

8

2

5

E agora subtrae de i um valor. Portanto, . Ele retorna ao enquanto, mas agora não satisfazemos a condição , por isso saímos do enquanto. Então ele pede para (). Portanto, o vetor fica assim:

v[1]

v[2]

v[3]

v[4]

v[5]

v[6]

3

5

7

8

2

5

E incrementamos o j, agora .

v[1]

v[2]

v[3]

v[4]

v[5]

v[6]

3

5

7

8

2

5

... E ? Não! Portanto, não entramos no enquanto.

(nenhuma mudança)

E lá vamos para e continuando até que vamos ter o vetor ordenado:

v[1]

v[2]

v[3]

v[4]

v[5]

v[6]

2

3

5

5

7

8

 

3.1 Qual a lógica?

Como eu já disse na introdução, mas lá sem grandes explicações, a Ordenação por Inserção divide o vetor em dois. O primeiro (de elementos ) contém todos seus valores ordenados e o segundo (de elementos ) contém os valores que devem ser inseridos no primeiro vetor já ordenado (por isso ele se chama Algoritmo de Inserção).

A chave do algoritmo é o enquanto que acontece para ir deslocando todos os elementos para seu índice enquanto o elemento for menor que eles (para depois o elemento ser colocado onde parou).

A variável elemento só serve para não perdermos o valor de (porque depois fazemos quando )

Acredito que não tenham restado dúvidas. Dê mais uma olhada no algoritmo e tente implementar. Se tiver dificulade, coloque mensagens de debug estratégicas para entender o algoritmo. (ex.: no início do para coloque para imprimir o valor de j e no início de cada enquanto coloque para imprimir os valores elemento, i e v[i])

3.2 Custo

Você deve ter percebido que este algoritmo não tem um custo fixo. Se todo o vetor estiver ordenado, ele nunca precisará iterar o e portanto será executado bem mais rápido do que se o vetor estiver inteiro em ordem decrescente (quando ele sempre precisará iterar até o fim - 0). Então, neste artigo, gostaria-lhes de apresentar a análise de algoritmos baseada em casos. Para este programa, dizemos que:

Melhor caso é quando todos os elementos já estão ordenados. Custo:

Pior caso é quando os elementos estão em ordem decrescente. Custo:

Em alguns programas o caso médio é importante também, mas não é o caso da ordenação por inserção. Vemos que há uma diferença bem grande entre o custo dos dois casos. Por isso, precisamos conhecer onde que nosso algoritmo será implementado e quais as chances de ele ser o melhor ou pior caso. Em geral, o pior caso é o mais comum... Por isso, diremos que o custo deste algoritmo é .

Tiago Madeira. - tmadeira[arroba]gmail.com



 Página anterior Voltar ao início do trabalhoPágina seguinte 



As opiniões expressas em todos os documentos publicados aqui neste site são de responsabilidade exclusiva dos autores e não de Monografias.com. O objetivo de Monografias.com é disponibilizar o conhecimento para toda a sua comunidade. É de responsabilidade de cada leitor o eventual uso que venha a fazer desta informação. Em qualquer caso é obrigatória a citação bibliográfica completa, incluindo o autor e o site Monografias.com.