Você está na página 1de 31

Pesquisa de Dados

APRESENTAÇÃO

A pesquisa de dados é muito utilizada na computação e também nas atividades do nosso dia a
dia. Seu objetivo é localizar, através de uma chave de busca, dentro de um conjunto de
elementos, o resultado que atenda a essa chave específica de forma rápida e eficiente. Nesta
Unidade de Aprendizagem, estudaremos os métodos de pesquisa de dados sequencial e binária,
sua fundamentação, estrutura e diferenças, além da aplicação e do desenvolvimento dos métodos
de pesquisa em pseudocódigo, utilizando o VisuAlg para o seu desenvolvimento.

Bons estudos.

Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:

• Diferenciar o funcionamento dos métodos de pesquisa sequencial e binário.


• Analisar algoritmos utilizando os métodos de pesquisa binário e sequencial.
• Usar a pesquisa de dados na solução de problemas em pseudocódigo.

DESAFIO

“Nosso sistema está com a busca de dados muito lenta, precisamos melhorar o algoritmo para
utilizar uma busca mais eficiente.”

E agora? Coube a você analisar o algoritmo implementado e estudar uma nova técnica para
melhorar a pesquisa de dados do sistema.

Abra o arquivo implementado pela empresa no VisuAlg no link abaixo.

Conteúdo interativo disponível na plataforma de ensino!


O algoritmo desenvolvido pela empresa é a primeira versão utilizando modularização e pesquisa
sequencial.

Para essa atividade, deve ser desenvolvido um MENU no algoritmo da empresa com as
seguintes funcionalidades:

MENU

1 - Pesquisa sequencial (algoritmos da empresa atualmente)

2 - Pesquisa binária

3 - Fim

A opção 1 é o modelo que a empresa está utilizando. Será realizada a leitura do vetor e
pesquisado um valor que será informado pelo usuário, utilizando a Pesquisa Sequencial. Se for
encontrado, deverá exibir a frase “O Cliente foi encontrado na posição xx”; se não for
encontrado, deverá exibir a mensagem “O Cliente não foi encontrado”.

A opção 2 irá realizar a leitura do vetor e pesquisar um valor que será informado pelo usuário,
utilizando a Pesquisa Binária. Os dados devem ser ordenados antes de realizar a busca. Se for
encontrado, deverá exibir a frase “O Cliente foi encontrado na posição xx”; se não for
encontrado, deverá exibir a mensagem “O Cliente não foi encontrado”.

A opção 3 encerra o algoritmo. O algoritmo somente poderá encerrar quando for digitada a
opção 3 de Sair do MENU, dando oportunidade para testar todas as opções do menu sem sair do
programa.

OBS: O módulo de leitura do vetor deve ser reutilizado em todos os métodos de pesquisa,
ou seja, ser implementado uma única vez e chamado em todos os métodos de pesquisa.

Entregue o novo algoritmo desenvolvido com as duas propostas descritas acima em um arquivo
no formato.alg no Visualg.

Após analisar, implementar e testar o algoritmo, responda, no espaço abaixo, qual das
duas soluções implementadas é a mais eficiente na pesquisa tendo 1000 clientes. Justifique
a sua escolha.

INFOGRÁFICO
Nesta Unidade de Aprendizagem veremos a aplicação da pesquisa de dados sequencial,
pseudocódigo, etc.

CONTEÚDO DO LIVRO

A pesquisa de dados é utilizada em diversas situações e o objetivo de encontrar uma ou mais


ocorrências em registros com chaves iguais à chave da pesquisa. Existe uma variedade enorme
de derivações dos métodos de pesquisa. A escolha do método mais adequado a uma determinada
aplicação possui alguns fatores, como número de elementos envolvidos, ou se os dados serão
alterados com frequência, entre outros. Sempre devemos pensar em minimizar o tempo de
pesquisa.

Para melhor compreender uma aplicação dos métodos de pesquisa de dados sequencial e binária,
acompanhe um trecho da seguinte obra: Ciencia da computação: uma visão abrangente O livro
servirá como base para esta Unidade de Aprendizagem. Nos capítulo selecionados, será
apresentada O algoritmo de busca sequencial e O algoritmo de busca binária.

Boa leitura.
J. Glenn Brookshear é Ph.D. pela New Mexico State University e Professor
Emérito da Marquette University, onde lecionou Linguagem Formal,
Introdução à Ciência da Computação e Teoria da Computação.

B873c Brookshear, J. Glenn.


Ciência da computação [recurso eletrônico] : uma visão
abrangente / J. Glenn Brookshear ; contribuição: David T.
Smith, Dennis Brylow ; tradução: Eduardo Kessler Piveta. –
11. ed. – Dados eletrônicos. – Porto Alegre : Bookman, 2013.

Editado também como livro impresso em 2013.


ISBN 978-85-8260-031-3

1. Ciência da computação. I. Título.

CDU 004

Catalogação na publicação: Ana Paula M. Magnus – CRB10/2052


170 Ciência da Computação: Uma Visão Abrangente

Concluímos que a descoberta de algoritmos permanece uma arte de-


safiadora que deve ser desenvolvida ao longo de um período de tempo, ao
invés de ensinada como um assunto formado por metodologias bem defini-
das. De fato, treinar um solucionador de problemas para que ele siga certas
metodologias é anular as características criativas que deveriam, ao invés
disso, ser estimuladas.

Questões e exercícios
1. a. Encontre um algoritmo para solucionar o seguinte problema: dado um inteiro positivo n,
encontre a lista de inteiros positivos cujo produto seja o maior entre todas as listas de intei-
ros positivos cuja soma é n. Por exemplo, se n for 4, a lista desejada é 2, 2 porque 2 ⫻ 2 é
maior que 1 ⫻ 1 ⫻ 1 ⫻ 1, 2 ⫻ 1 ⫻ 1 e 3 ⫻ 1. Se n for 5, a lista desejada é 2 e 3.
b. Qual é a lista desejada se n ⫽ 2001?
c. Explique como você deu o primeiro passo.
2. a. Suponha que nos seja dado um tabuleiro de damas consistindo em 2n linhas e 2n colunas
de quadrados, para algum inteiro positivo n, e uma caixa de ladrilhos em forma de L, cada
um dos quais pode cobrir exatamente três quadrados do tabuleiro. Se qualquer quadrado for
cortado do tabuleiro, podemos cobrir o tabuleiro restante com ladrilhos de forma que eles
não se sobreponham ou caiam fora da borda do tabuleiro?
b. Explique como sua solução para o item (a) pode ser usada para mostrar que 22n – 1 é divi-
sível por 3 para todos os inteiros positivos n.
c. Como os itens (a) e (b) são relacionados às fases de Polya da resolução de problemas?
3. Decodifique a mensagem a seguir, escrita em inglês, e então explique como você deu o pri-
meiro passo. Pdeo eo pda yknnayp wjosan.
4. Você estaria seguindo uma metodologia descendente se tentasse resolver um quebra-cabeça
simplesmente colocando as peças sobre a mesa e tentando agrupá-las? Sua resposta mudaria
se você olhasse na caixa do quebra-cabeça para ver como é a imagem montada?

5.4 Estruturas iterativas


Nosso objetivo, agora, é estudar algumas das estruturas de repetição usadas
para descrever processos algorítmicos. Nesta seção, discutiremos as estru-
turas iterativas, nas quais uma coleção de instruções é repetida na for-
ma de um laço. Na seção seguinte, introduziremos a técnica de recursão.
Como consequência, introduziremos alguns algoritmos populares – a busca
sequencial, a busca binária e a ordenação por inserção. Iniciamos introdu-
zindo o algoritmo de busca sequencial.

O algoritmo de busca sequencial


Considere o problema de buscar, dentro de uma lista de ocorrências, um va-
lor específico. Queremos desenvolver um algoritmo que determine se o va-
lor está na lista. Se o valor estiver na lista, consideramos a busca um suces-
so; caso contrário, a consideramos uma falha. Assumimos que a lista esteja
ordenada de acordo com alguma regra de ordenação de suas entradas. Por
exemplo, se for uma lista de nomes, assumimos que os nomes aparecem em
Capítulo 5 Algoritmos 171

ordem alfabética; se a lista for formada por valores numéricos, assumimos


que suas entradas aparecem em ordem crescente de magnitude.
Para dar o primeiro passo, imaginamos como poderíamos buscar, em
uma lista de convidados com, digamos, 20 entradas, um nome em particu-
lar. Nesta configuração, poderíamos varrer a lista desde o início, comparando
cada entrada com o nome buscado. Se achássemos o nome, a busca termina-
ria como um sucesso. Entretanto, se chegássemos ao final da lista sem encon-
trar o valor visado, nossa busca terminaria como uma falha. Na verdade, se
alcançarmos um nome maior que (alfabeticamente) o nome alvo sem encon-
trar o alvo, nossa busca já termina como uma falha. (Lembre-se, a lista está
organizada em ordem alfabética, então chegar a um nome maior que o nome
alvo indica que o alvo não está na lista.) Em resumo, nossa ideia rudimentar é
continuar buscando na lista enquanto existirem mais nomes a serem investi-
gados e o nome do alvo ser maior que o nome atualmente sendo considerado.
Em nosso pseudocódigo, esse processo poderia ser representado como
Selecione a primeira entrada na lista como EntradaDeTeste.
enquanto (ValorAlvo > EntradaDeTeste e
existirem entradas remanescentes a serem consideradas)
faça (Selecione a próxima entrada da lista como EntradaDeTeste)
Ao terminar essa estrutura enquanto, uma de duas condições será verdadei-
ra; ou o valor buscado foi encontrado ou não está na lista. Em cada um dos
casos, podemos detectar uma busca bem-sucedida comparando a entrada
de teste com o valor visado. Se eles forem iguais, a busca foi bem sucedida.
Logo, adicionamos a seguinte sentença
se (ValorAlvo = EntradaDeTeste)
então (Declare a busca um sucesso.)
senão (Declare a busca uma falha.)
para terminar nossa rotina em pseudocódigo.
Por fim, observamos que a primeira sentença em nossa rotina, a qual
seleciona a primeira entrada na lista como a entrada de testes, é baseada na
premissa de que a lista em questão contém ao menos uma entrada. Pode-
mos argumentar que essa é uma suposição segura, mas apenas para termos
certeza, podemos posicionar nossa rotina como a opção senão da sentença
se (Lista vazia)
então (Declare a busca uma falha.)
senão (...)
Isso produz o procedimento mostrado na Figura 5.6. Note que esse proce-
dimento pode ser usado de dentro de outros procedimentos por meio de
sentenças como
Aplique o procedimento Buscar à lista de passageiros
usando Darrel Baker como o valor a ser localizado.
para verificar se Darrel Baker é um passageiro e
Aplique o procedimento Buscar à lista de ingredientes
usando noz-moscada como o valor a ser localizado.
172 Ciência da Computação: Uma Visão Abrangente

procedimento Buscar(Lista, ValorAlvo)


se (Lista vazia)
então
(Declare a busca uma falha.)
senão
(Selecione a primeira entrada na lista como sendo EntradaDeTeste;
enquanto (ValorAlvo > EntradaDeTeste e
existirem entradas remanescentes a serem consideradas)
faça (Selecione a próxima entrada da lista como EntradaDeTeste.);
se (ValorAlvo = EntradaDeTeste)
então (Declare a busca um sucesso.)
senão (Declare a busca uma falha.)
) fim se

Figura 5.6 Algoritmo de busca sequencial em pseudocódigo.

para encontrar se noz-moscada aparece na lista de ingredientes.


Em resumo, o algoritmo apresentado pela Figura 5.6 considera as en-
tradas na ordem sequencial pela qual elas ocorrem na lista. Por essa razão,
o algoritmo é chamado de algoritmo de busca sequencial. Por sua simpli-
cidade, ele é frequentemente usado para pequenas listas ou quando outras
preocupações ditam seu uso. Entretanto, no caso de listas longas, as buscas
sequenciais não são tão eficientes quanto outras técnicas (que veremos em
breve).

Controle de laços
O uso repetitivo de uma instrução ou de uma sequência de instruções é
um conceito algorítmico importante. Um método de implementar tal repe-
tição é a estrutura iterativa conhecida como laço, na qual uma coleção de
instruções, chamada de corpo do laço, é executada de maneira repetida sob
a direção de algum processo de controle. Um exemplo típico é encontrado
no algoritmo de busca sequencial representado na Figura 5.6. Neste caso,
usamos uma sentença enquanto para controlar a repetição da sentença úni-
ca Selecione a próxima entrada da lista como EntradaDeTeste. Na
verdade, a sentença enquanto
enquanto (condição) faça (corpo)
exemplifica o conceito de uma estrutura de laço, já que sua execução mostra
o padrão cíclico
verificar a condição.
executar o corpo.
verificar a condição.
executar o corpo.
.
.
.
verificar a condição.
até que a condição falhe.
Capítulo 5 Algoritmos 181

5.5 Estruturas recursivas


Estruturas recursivas fornecem ao paradigma de laços uma alternativa para
implementar a repetição de atividades. Enquanto um laço implica repetir
um conjunto de instruções de maneira que o conjunto seja completado e en-
tão repetido, a recursão envolve repetir o conjunto de instruções como uma
tarefa em si mesma. Como uma analogia, considere o processo de conduzir
conversas telefônicas com o recurso de espera de chamada. Uma conversa
telefônica incompleta é posta de lado enquanto outra chamada é processa-
da. O resultado é que duas conversas estarão ocorrendo. Entretanto, elas
não são realizadas uma após a outra, como em uma estrutura de laço, mas,
em vez disso, uma é realizada dentro da outra.

O algoritmo de busca binária


Como uma maneira de introduzir recursão, vamos mais uma vez tratar
do problema da busca por uma entrada específica em uma lista ordenada,
mas, desta vez, damos o primeiro passo considerando o procedimento que
seguimos quando buscamos em um dicionário. Neste caso, não realizamos
um procedimento entrada por entrada ou página por página. Ao invés dis-
so, começamos abrindo o dicionário em uma página que esteja em uma
área na qual acreditamos que a entrada buscada esteja localizada. Se ti-
vermos sorte, encontraremos o valor visado lá; caso contrário, devemos
continuar a busca. Ainda assim, neste ponto, já reduzimos nossa busca
consideravelmente.
Obviamente, quando fazemos uma busca em um dicionário, temos um
conhecimento prévio de palavras que provavelmente serão encontradas.
Se você estiver procurando pela palavra sonambulismo, iniciaria abrindo a
porção mais ao fim do dicionário. No caso de listas genéricas, entretanto,
não temos essa vantagem, então vamos estabelecer um consenso de sempre

Primeira Segunda
Lista original
sublista sublista

Alice
Bob
Carol
David
Elaine
Fred
George
Harry
Irene Irene Irene
John John John
Kelly Kelly Kelly
Larry Larry
Mary Mary
Nancy Nancy
Oliver Oliver

Figura 5.12 Aplicação da nossa estratégia para buscar a entrada John em uma lista.
182 Ciência da Computação: Uma Visão Abrangente

iniciar nossa busca pela entrada localizada no “meio” da lista. Aqui, escre-
vemos a palavra meio entre aspas porque a lista pode ter um número par
de entradas e, logo, nenhuma entrada do meio existirá de fato. Neste caso,
vamos convencionar que a entrada do “meio” se refere à primeira entrada
da segunda metade da lista.
Se a entrada no meio da lista for o valor buscado, podemos declarar a
busca um sucesso. Caso contrário, podemos ao menos restringir o processo
de busca para a primeira ou para a segunda metade da lista, dependendo de
o valor buscado ser menor ou maior que a entrada que estamos consideran-
do. (Lembre-se de que a lista é ordenada.)
Para buscar na porção remanescente da lista, poderíamos aplicar a
busca sequencial, mas ao invés disso vamos aplicar a mesma abordagem
para essa porção da lista que usamos para a lista inteira. Ou seja, selecio-
namos a entrada do meio na porção remanescente da lista como a próxima
entrada a ser considerada. Como antes, se esta entrada for o valor visado,
terminamos. Caso contrário, podemos restringir nossa busca para uma por-
ção ainda menor da lista.
Essa abordagem para o processo de busca é resumida na Figura 5.12,
na qual consideramos a tarefa de fazer uma busca na lista mais à esquerda
na figura, pela entrada John. Primeiro, consideramos a entrada do meio,
Harry. Como nosso alvo está após esta entrada, a busca continua, conside-
rando a metade inferior da lista original. O meio da sublista agora é calcu-
lado como Larry. Como nosso alvo deve preceder Larry, movemos nossa
atenção para a primeira metade da sublista atual. Quando interrogamos o
meio desta sublista secundária, encontramos nosso alvo, John, e declara-
mos a busca um sucesso. Em resumo, nossa estratégia é dividir sucessiva-
mente a lista em segmentos menores, até que o alvo seja encontrado ou a
busca esteja restrita a um segmento vazio.
Precisamos enfatizar esse último ponto. Se o valor buscado não estiver
na lista original, nossa abordagem para a busca na lista será conduzida ao di-

se (Lista vazia)
então
(Relate que a busca falhou.)
senão
[Selecione a entrada do “meio” da Lista como sendo a EntradaDeTeste;
Execute o bloco de instruções abaixo que
está associado com o caso apropriado.
caso 1: ValorAlvo = EntradaDeTeste
(Relate que a busca foi bem-sucedida.)
caso 2: ValorAlvo < EntradaDeTeste
(Busque a porção da lista anterior a EntradaDeTeste pelo
ValorAlvo e relate o resultado dessa busca.)
caso 3: ValorAlvo > EntradaDeTeste
(Busque a porção da lista após EntradaDeTeste pelo
ValorAlvo, e relate o resultado dessa busca.)
] fim se

Figura 5.13 Primeiro rascunho da técnica de busca binária.


Capítulo 5 Algoritmos 183

Busca e ordenação
Os algoritmos de busca sequencial e de busca binária são apenas dois dos muitos algoritmos
para realizar o processo de busca. De maneira similar, a ordenação por inserção é apenas um de
muitos algoritmos de ordenação. Outros algoritmos clássicos para ordenação incluem a ordena-
ção por mesclagem (merge sort), discutida no Capítulo 12, a ordenação por seleção (Questão/
Exercício 6 da Seção 5.4), a ordenação por bolha (Questão/Exercício 7 da Seção 5.4), a ordena-
ção rápida (quick sort), que aplica uma abordagem dividir para conquistar sobre o processo de
ordenação) e a ordenação por monte (heap sort), que usa uma técnica bastante inteligente para
encontrar as entradas que devem ser movidas para frente na lista. Você encontrará discussões
sobre esses algoritmos nos livros listados na Leitura Adicional, ao final deste capítulo.

vidirmos a lista em segmentos menores até que o segmento que está sendo
considerado esteja vazio. Nesse momento, nosso algoritmo deve reconhecer
que a busca falhou.
A Figura 5.13 é um primeiro rascunho de nossos pensamentos usando
nosso pseudocódigo. Ele nos conduz a começar uma busca tentando ver
se a lista está vazia. Se estiver, ele nos diz para relatar que a busca é uma
falha. Caso contrário, o rascunho nos diz para considerar a entrada do meio
da lista. Se a entrada não for o valor buscado, ele nos diz para buscar na
primeira metade ou na segunda metade da lista. Ambas as possibilidades
requerem uma busca secundária. Seria bom realizar essas buscas por meio
de chamadas aos serviços de uma ferramenta abstrata. Em particular, nossa
abordagem é aplicar um procedimento chamado Buscar para conduzir essas
buscas secundárias. Para completar nosso programa, logo, devemos forne-
cer tal procedimento.
No entanto, esse procedimento deve realizar a mesma tarefa expressa
pelo pseudocódigo que já escrevemos. Ele primeiro deve verificar se a lista

procedimento Buscar (Lista, ValorAlvo)


se (Lista vazia)
então
(Relate que a busca falhou.)
senão
[Selecione a entrada do “meio” da Lista como sendo a EntradaDeTeste;
Execute o bloco de instruções abaixo que
está associado com o caso apropriado.
caso 1: ValorAlvo = EntradaDeTeste
(Relate que a busca foi bem sucedida.)
caso 2: ValorAlvo < EntradaDeTeste
(Aplique o procedimento Buscar para ver se ValorAlvo
está na porção da lista anterior a EntradaDeTeste,
e relate o resultado dessa busca.)
caso 3: ValorAlvo > EntradaDeTeste
(Aplique o procedimento Buscar para ver se ValorAlvo
está na porção da lista posterior a EntradaDeTeste,
e relate o resultado dessa busca.)
] fim se

Figura 5.14 Algoritmo de busca binária em pseudocódigo.


184 Ciência da Computação: Uma Visão Abrangente

que ele recebeu está vazia e, se não estiver, ele deve continuar considerando
a entrada do meio dessa lista. Logo, podemos fornecer o procedimento que
precisamos simplesmente identificando a rotina atual como o procedimento
chamado Buscar e inserindo referências para esse procedimento, no qual as
buscas secundárias são requeridas. O resultado é mostrado na Figura 5.14.
Note que esse procedimento contém uma referência para si mesmo. Se
o estivéssemos seguindo e chegássemos na instrução
Aplique o procedimento Buscar...
aplicaríamos na lista menor o mesmo procedimento que estávamos aplican-
do na lista original. Se essa busca fosse bem sucedida, retornaríamos para
declarar que nossa busca original havia sido bem sucedida; se essa busca
secundária falhasse, declararíamos que nossa busca original falhou.
Para ver como o procedimento na Figura 5.14 realiza sua tarefa, vamos
segui-lo enquanto ele faz uma busca na lista Alice, Bill, Carol, David, Evelyn,
Fred e George, pelo valor Bill. Nossa busca começa selecionando David (a
entrada do meio) como a entrada de teste a ser considerada. Como o valor
buscado (Bill) é menor que essa entrada de teste, o algoritmo nos instrui
para aplicar o procedimento Buscar na lista de entradas que precede David
– ou seja, a lista Alice, Bill e Carol. Ao fazer isso, criamos uma segunda cópia
do procedimento de busca e atribuímos a ela essa tarefa secundária.
Agora, temos duas cópias de nosso procedimento de busca sendo exe-
cutadas, como resumido na Figura 5.15. O progresso na cópia original é tem-
porariamente suspenso na instrução

Estamos aqui.

procedimento Buscar (Lista, ValorAlvo) procedimento Buscar (Lista, ValorAlvo)

se (Lista vazia) se (Lista vazia)


então (Relate que a busca falhou.) então (Relate que a busca falhou.)
senão senão
[Selecione a entrada do “meio” da Lista como sendo a EntradaDeTeste; [Selecione a entrada do “meio” da Lista como sendo a EntradaDeTeste;
Execute o bloco de instruções abaixo que Execute o bloco de instruções abaixo que
está associado com o caso apropriado. está associado com o caso apropriado.
caso 1: ValorAlvo = EntradaDeTeste caso 1: ValorAlvo = EntradaDeTeste
(Relate que a busca foi bem sucedida.) (Relate que a busca foi bem sucedida.)
caso 2: ValorAlvo < EntradaDeTeste caso 2: ValorAlvo < EntradaDeTeste
(Aplique o procedimento Buscar para ver se ValorAlvo (Aplique o procedimento Buscar para ver se ValorAlvo
está na porção da lista anterior a EntradaDeTeste, está na porção da lista anterior a EntradaDeTeste,
e relate o resultado dessa busca.) e relate o resultado dessa busca.)
caso 3: ValorAlvo > EntradaDeTeste caso 3: ValorAlvo > EntradaDeTeste
(Aplique o procedimento Buscar para ver se ValorAlvo (Aplique o procedimento Buscar para ver se ValorAlvo
está na porção da lista posterior a EntradaDeTeste, está na porção da lista posterior a EntradaDeTeste,
e relate o resultado dessa busca.) e relate o resultado dessa busca.)
] fim se ] fim se

Lista Lista
Alice
Bill
Carol
David (EntradaDe
Evelyn Teste)
Fred David
David
George Evelyn
Evelyn
Fred
Fred
George
George

Figura 5.15
Capítulo 5 Algoritmos 185

Aplique o procedimento Buscar para ver se ValorAlvo


está na porção da lista anterior a EntradaDeTeste,
enquanto aplicamos a segunda cópia à tarefa de buscar na lista Alice, Bill
e Carol. Quando completarmos essa busca secundária, descartaremos a se-
gunda cópia do procedimento, relataremos suas descobertas para a cópia
original e continuamos o progresso na original. Dessa maneira, a segun-
da cópia do procedimento funciona como uma sub-rotina da original, reali-
zando a tarefa solicitada pelo módulo original e, então, desaparecendo.
A busca secundária seleciona Bill como sua entrada de teste, pois ela é
a entrada do meio na lista Alice, Bill e Carol. Como ela é igual ao valor bus-
cado, ela declara sua busca um sucesso e termina.
Neste ponto, completamos a busca secundária, como solicitado pela
cópia original do procedimento, e somos capazes de continuar a execução
dessa cópia original. Aqui, o algoritmo nos diz que o resultado da busca se-
cundária deve ser relatado como sendo o resultado da busca original. Logo,
relatamos que a busca original foi bem-sucedida. Nosso processo determi-
nou corretamente que Bill é um membro da lista Alice, Bill, Carol, David,
Evelyn, Fred e George.
Vamos agora considerar o que acontece se pedirmos ao procedimento
na Figura 5.14 para buscar, na lista Alice, Carol, Evelyn, Fred e George, pela
entrada David. Desta vez, a cópia original do procedimento seleciona Eve-
lyn como sua entrada de teste e conclui que o valor buscado deve residir na
seção anterior da lista. Ele, então, requer outra cópia do procedimento para
buscar a lista de entradas que aparecem na frente de Evelyn – ou seja, a lista
de duas entradas que consiste em Alice e Carol. Neste estágio, nossa situa-
ção está conforme representado na Figura 5.16.
A segunda cópia do procedimento seleciona Carol como sua entrada
atual e conclui que o valor buscado deve residir na porção posterior de sua
lista. Ela, então, requer uma terceira cópia do procedimento para buscar a
lista de nomes que seguem Carol na lista Alice e Carol. Essa sub-lista é vazia,
então a terceira cópia do procedimento tem a tarefa de buscar na lista vazia
pelo valor David. Nossa situação neste ponto é representada pela Figura
5.17. A cópia original do procedimento recebe a tarefa de buscar na lista
Alice, Carol, Evelyn, Fred e George, com a entrada de teste sendo Evelyn; a
segunda cópia recebe a tarefa de buscar na lista Alice e Carol, com sua en-
trada de teste sendo Carol; e a terceira cópia trata de começar a buscar em
uma lista vazia.
Obviamente, a terceira cópia do procedimento rapidamente declara que
sua busca foi uma falha e termina. O término da tarefa da terceira cópia permi-
te que a segunda cópia continue sua tarefa. Ela nota que a busca que ela requi-
sitou não foi bem sucedida, declara que sua própria tarefa foi uma falha e ter-
mina. Esse relato é o que a cópia original do procedimento estava esperando,
então ela pode prosseguir. Como a busca que ela requisitou falhou, ela declara
que sua própria busca falhou e termina. Nossa rotina concluiu corretamente
que David não está na lista Alice, Carol, Evelyn, Fred e George.
Em resumo, se voltássemos a olhar os exemplos anteriores, podería-
mos ver que o processo empregado pelo algoritmo representado na Figura
5.14 é dividir a lista em questão repetidamente em duas porções menores,
de maneira que a busca remanescente pudesse estar restrita a apenas uma
186 Ciência da Computação: Uma Visão Abrangente

Estamos aqui.

procedimento Buscar (Lista, ValorAlvo) procedimento Buscar (Lista, ValorAlvo)

se (Lista vazia) se (Lista vazia)


então (Relate que a busca falhou.) então (Relate que a busca falhou.)
senão senão
[Selecione a entrada do “meio” da Lista como sendo a EntradaDeTeste; [Selecione a entrada do “meio” da Lista como sendo a EntradaDeTeste;
Execute o bloco de instruções abaixo que Execute o bloco de instruções abaixo que
está associado com o caso apropriado. está associado com o caso apropriado.
caso 1: ValorAlvo = EntradaDeTeste caso 1: ValorAlvo = EntradaDeTeste
(Relate que a busca foi bem sucedida.) (Relate que a busca foi bem sucedida.)
caso 2: ValorAlvo < EntradaDeTeste caso 2: ValorAlvo < EntradaDeTeste
(Aplique o procedimento Buscar para ver se ValorAlvo (Aplique o procedimento Buscar para ver se ValorAlvo
está na porção da lista anterior a EntradaDeTeste, está na porção da lista anterior a EntradaDeTeste,
e relate o resultado dessa busca.) e relate o resultado dessa busca.)
caso 3: ValorAlvo > EntradaDeTeste caso 3: ValorAlvo > EntradaDeTeste
(Aplique o procedimento Buscar para ver se ValorAlvo (Aplique o procedimento Buscar para ver se ValorAlvo
está na porção da lista posterior a EntradaDeTeste, está na porção da lista posterior a EntradaDeTeste,
e relate o resultado dessa busca.) e relate o resultado dessa busca.)
] fim se ] fim se

Lista Lista
Alice
Carol

Evelyn (EntradaDe
Fred Teste)
George David
David
Evelyn
Evelyn
Fred
Fred
George
George

Figura 5.16

dessas duas peças. Essa abordagem de divisão por dois é a razão pela qual o
algoritmo é conhecido como a busca binária.

Controle recursivo
O algoritmo de busca binária é similar à busca sequencial no sentido de que
cada algoritmo requer a execução de um processo repetitivo. Entretanto, a
implementação dessa repetição é significativamente diferente. Enquanto a
busca sequencial envolve uma forma circular de repetição, a busca binária
executa cada estágio da repetição como uma subtarefa do estágio anterior.
Essa técnica é conhecida como recursão.
Como vimos, a ilusão criada pela execução de um procedimento recur-
sivo é a da existência de múltiplas cópias do procedimento, cada uma das
quais é chamada de uma ativação do procedimento. Essas ativações são cria-
das dinamicamente em uma maneira telescópica e, por fim, desaparecem à
medida que o algoritmo avança. Das ativações existentes em dado momen-
to, apenas uma está ativamente progredindo. As outras estão efetivamente
no limbo, cada uma delas esperando pelo término de outra ativação antes
de poder continuar.
Sendo um processo repetitivo, os sistemas recursivos são tão depen-
dentes de controles apropriados quanto são as estruturas de laço. Assim
como no controle de laço, os sistemas recursivos são dependentes de testes
em relação a uma condição de término e de um projeto que garanta que
essa condição seja alcançada. Na verdade, um controle recursivo apropriado
Encerra aqui o trecho do livro disponibilizado para
esta Unidade de Aprendizagem. Na Biblioteca Virtual
da Instituição, você encontra a obra na íntegra.
DICA DO PROFESSOR

Devemos sempre nos preocupar em utilizar algoritmos de pesquisa de dados eficientes,


pois é esse algoritmo que vai determinar o custo da pesquisa. Métodos ineficientes
geralmente são mais fáceis de implementar, por isso, devemos estudar os métodos mais a
fundo se queremos ter um sistema com uma pesquisa eficiente e rápida.

Assista ao vídeo para conhecer um pouco mais sobre os métodos de pesquisa sequencial e
binária, sua funcionalidade, variações e propostas de implementação.

Conteúdo interativo disponível na plataforma de ensino!

EXERCÍCIOS

1) Um método utilizado para a pesquisa de dados em vetores utiliza a inserção do valor


pesquisado (chave) em sua última posição, restringindo a quantidade de buscas que serão
realizadas para encontrar a chave dentro do vetor. Com isso, o método o objetivo de
reduzir o número de comparações no momento da pesquisa, tornando mais rápida a
pesquisa de dados no algoritmo. Como exemplo, podemos descrever a situação de uma
empresa que deseja pesquisar os ramais de todos os seus telefones internos. Para isso,
utiliza uma estrutura de vetor para armazenar os ramais, conforme é mostrado abaixo.

Ramais:

Todos os ramais estão armazenados no vetor e desejamos pesquisar um determinado


ramal, como o 65.

O método em questão colocaria a chave 65 na última posição (ou também poderia ser na
primeira posição) do vetor, como demonstrado abaixo.
A pesquisa termina quando encontra o ramal desejado. Caso ele não exista, chegará ao
final do vetor e encontrará no último elemento a chave 65; assim, saberá que está na última
posição e não encontrou o elemento procurado.

Selecione a alternativa que representa o método descrito acima.

A) Pesquisa binária.

B) Pesquisa sequencial (linear).

C) Pesquisa sequencial com sentinela .

D) Pesquisa por interpolação.

E) Nenhuma das alternativas.

2) Considerando os métodos de pesquisa de dados sequencial e binária, analise as


afirmativas abaixo e determine se são verdadeiras (V) ou falsas (F).

I - O método de pesquisa binário é menos eficiente que o método de pesquisa


sequencial.
II - O método de pesquisa sequencial com sentinela é mais eficiente que o método de
pesquisa sequencial linear.
III - O método de pesquisa sequencial procura registro a registro pela chave.
IV - O método de pesquisa binário, para ser eficiente, não deve ter seus dados
ordenados antes da busca.

A) V, V, V, V.

B) F, F, F, F.

C) F, V, F, F.
D) F, V, V, V.

E) F, V, V, F.

3) Uma universidade realizou vestibular para os cursos superiores e armazenou em um vetor


o código dos alunos inscritos que tiveram aprovação. Essa pesquisa foi inserida no site da
instituição e os candidatos poderão realizar a pesquisa pelo site para verificar se obtiveram
a aprovação para o curso desejado. Para a realização da pesquisa, é necessário digitar o
código de inscrição do aluno. Como retorno, a mensagem para os candidatos que tiveram
aprovação será “Candidato aprovado no vestibular”; para os que não obtiveram aprovação,
a mensagem será “Candidato não aprovado no vestibular”.

Como exemplo para demonstrar a situação:,

Dados os códigos dos candidatos aprovados no vestibular armazenados no vetor


candidato[12], que utilizaremos para demonstração e para simplificar a atividade, somente
de 12 posições:

candidato = {6,5,3,23,12,34,56,43,31,20,86,29}

Observe:

i: representa o índice que controla a posição do vetor candidato.

X: representa a chave/valor que deseja procurar no vetor A, ou seja, o candidato


procurado.

candidato: representa o vetor onde será procurada a chave X (local onde será procurado o
candidato do vestibular).

Realize um teste de mesa para a pesquisa do candidato 86 no vetor candidato. Para a


pesquisa, utilize o trecho do algoritmo abaixo identificado pelos valores das suas linhas de 1
a 9.
Quantas serão as execuções realizadas da linha 3, para que o algoritmo encontre o valor 86
através da pesquisa sequencial?

A) 11.

B) 22.

C) 9.

D) 10.

E) Nenhuma alternativa.

4) São dados os seguintes trechos de algoritmos de pesquisa de dados para a pesquisa de


um elemento em um vetor H de 8 posições.
Observe:

i: representa o índice que controla a posição do vetor H.


ini: representa a posição inicial de pesquisa do vetor H.
fim: representa a posição final de pesquisa do vetor H.
meio: representa a posição central de pesquisa do vetor H a ser pesquisada a chave.
valor: representa a chave/elemento que deseja procurar no vetor H.
H: representa o vetor onde será procurada a chave valor.

O módulo de leitura dos elementos do vetor e da leitura do valor da chave (valor a ser
procurado) não estão implementados, somente o método de pesquisa. Os algoritmos
de pesquisa apresentados abaixo retornam para a função chamadora o valor lógico
Verdadeiro, se encontrar a chave procurada, ou Falso, se não encontrar.

ordena
ini <- 1
fim <- 8
procurado <- falso
enquanto (ini <= fim) e não procurado faca
meio <- (ini+fim) div 2
se H[meio]= valor entao
procurado <-verdadeiro
fimse
se H[meio] > valor entao
fim <- meio – 1
senao
ini <- meio +1
fimse
fimenquanto
se (procurado = verdadeiro) entao
retorne(verdadeiro)
senao
retorne (falso)
fimse

II

i <-1
enquanto (i < 8) e (valor < > H[i]) faca
i <- i+1
fimenquanto
se (valor = H[i]) entao
retorne(verdadeiro)
senao
retorne (falso)
fimse

III

i <- 1
H[8] <- valor
enquanto (valor < > H[i] ) faca
i <- i+1
fimenquanto
se (i < 8) entao
retorne(verdadeiro)
senao
retorne(falso)
fimse

Analise cada um dos métodos descritos nas alternativas acima e identifique qual o
método representado nas alternativas I, II e III, respectivamente.

A) Pesquisa binária, sequencial e sequencial com sentinela.

B) Pesquisa binária, sequencial com sentinela e sequencial.

C) Pesquisa sequencial com sentinela, sequencial e binária.

D) Pesquisa sequencial com sentinela, binária e sequencial.

E) Pesquisa sequencial, binária e sequencial com sentinela.


5) Considere o seguinte algoritmo em pseudocódigo: ,algoritmo
"Pesquisa_altera_Dados"
var
f: vetor[1..10] de inteiro
c, i: inteiro

procedimento lerCliente
inicio
para i de 1 ate 10 passo 1 faca
escreva("Valor(",i,"): ")
leia(f[i])
fimpara
fimprocedimento

procedimento pesquisa (var conta:inteiro)


inicio
para i de 1 ate 10 passo 1 faca
se (f[i]<0) entao
f[i]<- 1
conta <- conta+1
fimse
fimpara
fimprocedimento

procedimento imprimir
inicio
escreval()
escreval("Relatório do Vetor : ")
para i de 1 ate 10 passo 1 faca
escreval("Valor (" , i,"): ",f[i])
fimpara
fimprocedimento
// Corpo principal do algoritmo
inicio
lercliente
imprimir
pesquisa(c)
escreval(" Total = ", c)
imprimir
fimalgoritmo

Analise as alternativas a seguir e, com base no algoritmo apresentado acima,


selecione a alternativa INCORRETA.

A) O algoritmo altera todos os valores negativos armazenados no vetor para 1.

B) No procedimento denominado pesquisa, a variável conta utiliza a passagem por referência


e tem por função contar quantos valores do vetor serão alterados para 1.

C) O método de pesquisa de dados sequencial com sentinela seria mais eficiente na solução
do problema apresentado.

D) O módulo denominado pesquisa poderia ser implementado com um laço de repetição


iniciando em 10 e decrementando, e, ainda assim, manteria a mesma funcionalidade.

E) O procedimento denominado pesquisa poderia ser desenvolvido como uma função,


retornando a variável conta para a função chamadora, e ainda assim manteria a mesma
funcionalidade do algoritmo.

NA PRÁTICA

Pesquisa no Google – Estudo de Caso

Os algoritmos de busca são amplamente utilizados no nosso dia a dia, assim como na
computação, para o desenvolvimento de sistemas nas mais variadas áreas.

Vamos analisar um caso muito prático que utilizamos sempre que precisamos de ajuda para
encontrar algo na internet. Um dos buscadores mais conhecidos é o Google. Encontrar uma
informação na imensidão de dados da internet não é tarefa fácil, e o tempo que o buscador leva
para nos dar o resultado depende diretamente do algoritmo de busca utilizado, pois são milhares
de sites ativos existentes.

Como você realiza uma pesquisa no Google?

Você insere um texto no Google, ele conduz a busca em páginas que contenham os termos de
busca que você digitou e retorna uma relação de links encontrados sobre o tema que você está
procurando. Assim, quanto mais eficiente for o algoritmo de busca, mais rápido e eficiente será
o resultado da pesquisa.

Precisamos cuidar com o que digitamos nos sites de busca!

A forma como os dados são organizados e como são pesquisados pode determinar a eficiência
do algoritmo desenvolvido. Se o volume de dados for muito grande, o método para efetuar a
busca deverá ser eficiente, caso contrário, a busca poderá ser muito demorada e inviabilizar as
operações que serão realizadas com os dados, como inserção, exclusão, alteração, entre outras.

A pesquisa sequencial poderá ser ineficiente quando o volume de dados for muito grande. Se os
elementos estiverem ordenados, pode-se aplicar um algoritmo mais eficiente para realizar a
busca.

Vamos analisar uma situação prática?

Precisamos cuidar com o que digitamos nos sites de busca!

Uma empresa possui um cadastro de produtos utilizando uma estrutura em forma de matriz, no
qual constam os seguintes dados:
Para realizar a consulta ou qualquer operação com os produtos armazenados, é necessário,
primeiro, pesquisar o produto cadastrado e, depois, realizar a operação desejada.

A matriz poderia ter muitas outras colunas, mas, para simplificar o problema, utilizaremos
somente duas colunas de dados, sendo a primeira para o código do produto e a segunda para
armazenar o valor do custo do produto.

Após encontrar a chave da pesquisa, que é representada pelo código do produto, várias
operações podem ser realizadas, como:

Inserir novos produtos (mas, antes, verifica se o produto já não está cadastrado);

Excluir um produto (mas, antes, necessita encontrar o produto);

Alterar o valor do produto (mas, antes, necessita encontrar o produto);

Contar quantos produtos estão em uma faixa de preço.

Para qualquer operação, é preciso realizar uma pesquisa de dados.

Você percebeu como é importante conhecer os algoritmos de pesquisa/busca?

Como encontrar o preço de determinado produto?

Vamos desenvolver uma solução utilizando a pesquisa de dados sequencial e com a estrutura
de dados matriz?
Para a representação de uma das soluções possível para o problema, utilizaremos uma estrutura
de dados em forma de matriz. A solução foi desenvolvida e possui os seguintes módulos:

Módulo para realizar o cadastro dos produtos na estrutura.

Módulo para realizar a impressão dos produtos cadastrados na estrutura.

Módulo para pesquisa para exibir o valor de custo, caso o produto seja encontrado, ou informar
que o produto não foi encontrado na estrutura.

Acompanhe abaixo!

Arquivo do algoritmo Implementado


Conteúdo interativo disponível na plataforma de ensino!

Realize testes de suas funcionalidades no Visualg.

Encontram-se abaixo os módulos desenvolvidos do algoritmo.

algoritmo "Pesquisa_Produto_Matriz"

var
prod: vetor[1..5,1..2] de real
codpro,v: real
i,j: inteiro

//Módulo para realizar o cadastro dos produtos na matriz

procedimento cadastro_prod

inicio
escreval("CADASTRO DE PRODUTOS: ")
para i de 1 ate 5 passo 1 faca
escreva("Digite o codigo do produto (",i,"): ")
leia(prod[i,1])
escreva("Digite o valor do custo do produto : ")
leia(prod[i,2])
fimpara
fimprocedimento

//Módulo para realizar a impressão dos produtos que estão na matriz

procedimento relatorio_prod
inicio
escreval("RELATÓRIO DOS PRODUTOS CADASTRADOS NA MATRIZ")
escreval("Codigo Valor")
para i de 1 ate 5 passo 1 faca

escreva(" ",prod[i,1]:2)
escreval(" ",prod[i,2]:4:2)
fimpara
fimprocedimento

//Módulo que realiza a pesquisa do preço de um determinado produto na matriz.

funcao pesquisapreco(valor:real):real
inicio
i <-1
enquanto (i<5) e (valor < > prod[i,1]) faca
i <- i+1
fimenquanto se (valor = prod[i,1]) entao
retorne(prod[i,2])
senao
retorne (-1)
fimse
fimfuncao
inicio //corpo principal do algoritmo
cadastro_prod //chama o módulo
relatorio_prod //chama o módulo
escreva("Digite o código do produto que deseja pesquisar o preço: ")
leia(codpro)
v <- pesquisapreco(codpro) //chama o módulo e retorna um valor da pesquisa
se (v = -1)entao
escreval("O Produto não foi encontrado ")
senao
escreva("O Produto foi encontrado e o Preço = ", v:4:2)
fimse
fimalgoritmo

SAIBA MAIS

Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:

Ciência da Computação

Otimização para sites de busca

Conteúdo interativo disponível na plataforma de ensino!

Lógica de Programação - Pesquisa Sequencial em Vetores (Arrays)

Conteúdo interativo disponível na plataforma de ensino!

Lógica de Programação - Pesquisa Binária em Vetores (Arrays)

Conteúdo interativo disponível na plataforma de ensino!

Pesquisa Binária

Conteúdo interativo disponível na plataforma de ensino!


Download VisuAlg

Conteúdo interativo disponível na plataforma de ensino!

Você também pode gostar