Você está na página 1de 12

Capacitação em Lógica de Programação

ALGORITMOS DE PESQUISA

Aprenderemos como realizar pesquisas utilizando algoritmos. Estes podem ser


definidos como soluções computacionais utilizadas para resolução de problemas na
computação (PUGA; RISSETI, 2009). O uso de diferentes métodos de pesquisa torna
uma série de atividades da área da informática mais eficientes. Podemos citar como
exemplo a procura de dados específicos em um banco ou a busca pela melhor rota
de uma rede. Lembre-se que as estruturas de tipos de dados são divididas em três
categorias:
1) Simples: A variável armazena somente um valor, por exemplo,
na expressão ‘int x = 10’, nota-se que o valor do inteiro 10 é atribuído à variável
inteiro x.
2) Estruturada: Cada variável armazena em memória uma coleção
de tipos de dados, por exemplo, pode-se declarar uma variável do tipo array
(armazena um conjunto de nomes) representada pelo script ‘String[] nomes =
{ ‘ana’, ‘joao’, ‘pedro’}.
3) Ponteiros: Faz referência a um outro valor em memória por
intermédio do seu endereço. Pode-se, por exemplo, representar um ponteiro
com ‘int *ponteiro, teste; ponteiro = &teste;’. Na linguagem C, JAVA e algumas
outras, essa representação é feita por referência por meio da criação de
objetos. Desta forma, temos ‘Object o = new Object();’.
Estruturas complexas como array, pilha e filas precisam de métodos de
pesquisa eficientes que realizem a tarefa com o menor custo (tempo) de retorno
possível.
Esses tipos de estrutura estão presentes em todos os segmentos de
programação com recursos mais avançados. Um dos seus usos mais frequentes é em
plataformas de pesquisa, afinal, toda e qualquer pessoa procura ou já procurou por
informações na internet por meio de sites de busca como o Google.
Em programação, os tipos de busca são determinados por técnicas que podem
ser definidas como algoritmos utilizados para resolver problemas na engenharia de
desenvolvimento de sistemas.

Algoritmo de busca linear

Uma busca sequencial procura pelo item desejado começando da primeira


posição até a última, comparando todos os elementos. Esse método é usado em
consulta de tabelas de registro de dados (DEITEL; DEITEL, 2010).

Sequencial
Imagine uma estrutura de dados do tipo array composta por seis elementos
internos (nomes de pessoas). Essa estrutura é composta por um nome e seis
elementos internos. Lembre-se que todo array começa na posição zero e tem como
referência um par de chaves compostos pelo nome do array e sua posição, por
exemplo, nomeArray(posição]. Desta forma, pode-se referenciar cada elemento
dentro do array seguindo o mesmo critério, por exemplo, o elemento na posição um
seria nomeArray[0], o elemento na posição dois seria nomeArray[1] e assim
sucessivamente.

Figura– Estrutura de um array


No exemplo da figura, pode-se verificar que cada elemento possui uma posição
e um valor, ou seja, o array é composto por um par de chaves na combinação {posição,
elemento} e a referência é dada pelo nome do array e sua posição.
A busca sequencial faz a comparação de cada elemento e sua posição até
encontrar o valor buscado (DEITEL; DEITEL, 2010). Esse processo pode ser
exemplificado usando como referência o array da figura. Supondo que precisamos
buscar o nome ‘Carlos’, o método sequencial funcionará da seguinte maneira:
Primeiramente, será feita uma comparação com o elemento na posição um, ou
seja, nomes[0]. Caso este não seja o elemento buscado, o algoritmo passará para a
posição seguinte e fará uma nova comparação. Ele continuará agindo desta maneira
até localizar o nome desejado.
Para uma melhor compreensão desse processo, observe a imagem a seguir:

Figura– Busca sequencial

Essa operação será feita com cada elemento dentro do array até o final. Caso,
o elemento buscado seja encontrado antes desse momento, o método é finalizado na
posição que a condição foi satisfeita, ou seja, quando o valor do elemento do array for
igual a ‘40’.
Complexidade

Em termos de complexidade, caso o elemento buscado esteja na posição um,


ele será encontrado na primeira tentativa. No pior dos casos, o elemento buscado
estará na última posição e serão realizadas n tentativas, sendo n o número de vezes
que o algoritmo fez a comparação com os elementos do array. Ou seja, se o array
contém 100 posições e o elemento buscado está na última, serão computadas uma
centena de comparações.
Em uma complexidade média, o elemento buscado será encontrado na
realização (n+1)/2 comparações, ou seja, se o elemento buscado estiver na posição
quatro do array da figura, serão realizadas (6+1)/2 comparações. No caso de uma
pesquisa sem sucesso, a representação será O (n) = n + 1. O tempo necessário será
O(n), sendo n o número de comparações ou realizações para buscar o elemento
desejado.

Análise do algoritmo
O exemplo ilustrado na figura representa, em script de código de programação
Java, a estrutura de busca de um elemento dentro do array ‘nomes’ representado
anteriormente na figura.

Figura– Algoritmo de busca linear


Nota-se no exemplo da figura 1.4 que a linha sete representa a declaração do
array com seis elementos do tipo de dados de string. A linha nove abre o comando de
rotinas de repetição que começa na posição zero e repete até a posição final do array,
sempre passando para o próximo elemento.
Para que a comparação dos elementos seja possível, é necessário fazer o uso
de um comando de controle de curso. No caso da figura, na linha onze, é feito o
emprego do comando if.
Neste tipo de comparação, cada elemento do array é igualado ao valor ‘Carlos’.
Se essa comparação for verdadeira, a informação será exibida no console (linha 12)
e o fluxo será parado. Entretanto, se a comparação não for verdadeira, ela seguirá
para a próxima linha e repetirá o processo até encontrar o elemento desejado.
Esse algoritmo pode não ser apropriado para estruturas com uma grande
quantidade de elementos, pois o tempo de busca pode se tornar um grande empecilho
para a sua aplicação.

Algoritmo de busca linear com recursividade

Recursividade, em ciência da computação, é um tipo de função capaz de ser


definida em si mesma. Em outras palavras, ela pode executar a si mesma (DEITEL;
DEITEL, 2010).
Um bom exemplo de recursividade é o número fatorial. Trata-se do
desmembramento do número da seguinte maneira:

3! = 3*(3-1)*(3-2) = 6
Figura – Recursividade

A busca linear está quase sempre associada à recursividade, afinal, as versões


não recursivas desse algoritmo costumam ser mais complexas e menos elegantes na
codificação. No caso da pesquisa linear, a recursividade representa a redução de um
problema, transformando-o em uma instância menor dele mesmo.
Na programação, a recursividade é a técnica de fazer com que uma função
chame a si própria. Para exemplificar, vamos fazer uma análise fatorial do número
três. Esse exemplo clássico ilustra corretamente o uso da recursividade. Tem-se,
portanto:
• 0! = 1;
• 1! = 1;
• 2!= 2*1= 2
• 3!= 3*2*1= 6

Nota-se que a instancia maior (3) foi dividida em instancia menores até o
resultado final (6). Na programação, o conceito de recursividade segue os mesmos
princípios da matemática. Em uma busca linear recursiva, dado um número x, a
pesquisa e retorna o valor da chave que contém o valor x, mas caso esse elemento
não seja encontrado, o valor retornado é -1.
Análise do algoritmo

O mesmo exemplo da figura pode ser reescrito na forma recursiva como ilustra
a figura a seguir:

Figura– Busca Linear Recursiva

Nesse script o resultado será a posição do elemento encontrado dentro do array


nomes.
Nota-se que, no código da figura a linha 18 indica a criação do array com seis
elementos. A linha 19 demonstra uma variável de tipo de dados string que foi criada
para armazenar o valor ‘Carlos’. Nas linhas 21 até 25, foi inserido um comando de
controle de fluxo para analisar a resposta do método iniciado na linha cinco do código.
Esse controle determina se o elemento foi encontrado ou não.
Na linha 20, são passados três parâmetros, o array nomes, o número de
tamanho do array e o valor a ser consultado. Primeiramente, o método verifica se o
índice passado é maior que zero e verifica se a posição n é igual ao valor passado.
Caso verdadeiro, retorna à posição do index (n) do array. Caso falso, retorna -1.
Se o valor consultado é maior que zero, entretanto ainda não foi encontrado,
recursivamente, assim como consta na linha 12, o método é chamado novamente,
fazendo essa rotina até encontrar o valor buscado.

Algoritmo de busca binária

O algoritmo de busca binária tem por finalidade encontrar um elemento dentro


de um array ordenado. Trata-se de um conceito muito usado com computação que
pode, por exemplo, ser usado em um jogo de adivinhação (PUGA; RISSETI, 2009).

1 2 3 4 5 6 7 9

Figura – Array ordenado

O algoritmo de busca binária consiste em dividir pela metade a parte da


estrutura de dados que teoricamente contém a informação a ser buscada. Em outras
palavras, ‘dividir e conquistar’. A figura ilustra a busca de um número 2 dentro de um
vetor de números usando o algoritmo de busca binária.
Figura– Busca binária

No exemplo ilustrado pela figura, o array é dividido pela metade a partir do item
cinco, posteriormente uma nova divisão foi realizada, desta vez com o item três. Em
seguida, a parte restante foi dividida no item dois e, finalmente, restou somente o
elemento de busca, nesse caso, o item um.
A outra metade é restringida, pois o elemento buscado é menor que o elemento
de divisão, neste exemplo, o número cinco. Caso, ele fosse maior que o elemento do
meio da tabela, a busca percorreria o lado direito da árvore.

Complexidade

Em termo de complexidade, o algoritmo de busca binária é da ordem de O(log


n). Isso faz com que esse algoritmo seja mais eficiente que os de busca linear que
são menos produtivos em grandes arrays.
Os algoritmos lineares procuram, em média, por metade da lista. Os de busca
binária, por outro lado, tem seu pior cenário quando o elemento não está no vetor,
sendo necessárias diversas buscas para comprovar a inexistência do elemento
buscado. O seu melhor cenário é quando o elemento buscado está no meio do vetor,
sendo necessário somente uma única busca, O(1).
Análise do algoritmo

O exemplo ilustrado na figura representa a estrutura de uma busca binária de


um elemento dentro do array de números representados anteriormente na figura em
script de código de programação Java.

Figura– Algoritmo de busca binário


Nesse script, o resultado será a posição do elemento encontrado dentro do
array ‘números’.

Figura– Posição do Array

Você pode observar, o método com dois parâmetros que faz busca binária na
estrutura do array ordenado. Nas linhas seis e sete são declaradas as variáveis de
controle início e fim que são usadas para determinar o ponto médio do array (linha
nove).
O loop para buscar o número dentro do array tem início na linha oito. Verifica-
se, a princípio, se a chave é menor que o fim. Se sim, o valor do meio é calculado
(linha nove) e um comando de controle para conferir se a chave passada equivale ao
conteúdo do elemento do meio é aplicado. Se sim, o elemento do meio é retornado.
Se não, é verificado se a chave é maior que o número do meio.
Neste momento, se a chave for maior (linha 12), adiciona-se 1 ao valor
correspondente à variável meio e o resultado desempenha a função de início na
próxima busca (linha 14). Por outro lado, se a chave for menor, subtrai-se 1 ao valor
correspondente à variável meio e o resultado desempenha a função de fim na próxima
busca. Quando todas as possibilidades forem esgotadas e o valor da chave não for
encontrado, será retornado -1.
Nota-se que a chamada do método é realizada dentro do método principal
(linha 27) por meio do comando de saída e os parâmetros passados são declarados
nas linhas 25 e 26 respectivamente.

Você também pode gostar