Buscar

Apostila Estruturas de Dados

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 57 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 57 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 57 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

ESTRUTURAS 
 
 
DE 
 
 
DADOS 
 
 
 
 
 
 
 
 
 
 
 
 
 
ROGÉRIO FERREIRA SGOTI 
 
 
 
FACULDADE DE TECNOLOGIA DE BOTUCATU 
 
SUMÁRIO 
 
 
Apresentação da disciplina .................................................................................................. ..... 3 
1 Introdução ao estudo das estruturas de dados ..................................................................... 4 
2 Revisão de tópicos ........................................................................................................ ........ 4 
3 Registros ............................................................................................................................... 6 
4 Algoritmos de Ordenação ................................................................................................... ... 9 
5 Algoritmos de Pesquisa ......................................................................................................... 13 
6 Comparativo entre os algoritmos de pesquisa ...................................................................... 16 
7 Listas ............................................................................................................................. ........ 18 
8 Alocação Estática de Memória ...................................................................................... ........ 18 
 8.1 Lista Estática Sequencial ............................................................................................... . 18 
 8.2 Lista Estática Encadeada ............................................................................. ................... 22 
9 Alocação Dinâmica de Memória ............................................................................................ 28 
 9.1 Ponteiros ......................................................................................................................... 28 
 9.2 Listas Dinâmicas ........................................................................................................ ..... 29 
10 Pilhas ................................................................................................................................... 38 
 10.1 Operações sobre Pilhas ................................................................................................ 38 
 10.2 Aplicações de Pilhas ..................................................................................................... 39 
 10.3 Implementação de Pilhas .............................................................................................. 39 
 10.4 Alocação Sequencial de Pilhas ..................................................................................... 39 
 10.5 Alocação Dinâmica de Pilhas ........................................................................................ 42 
11 Filas ..................................................................................................................................... 44 
 11.1 Operações sobre Filas .................................................................................................. 44 
 11.2 Aplicações de Filas ........................................................................................................ 44 
 11.3 Implementação de Filas ................................................................................................ 44 
 11.4 Alocação Sequencial de Filas ....................................................................................... 45 
 11.5 Fila Circular .......................................................................................................... ......... 48 
 11.6 Alocação Dinâmica de Filas .......................................................................................... 50 
12 Espalhamento (Hashing) .............................................................................................. ....... 52 
 12.1 Fundamentos ............................................................................................................ ..... 52 
 12.2 Funções de Espalhamento ............................................................................................ 53 
 12.3 Tabelas de Espalhamento ............................................................................................. 55 
13 Recursividade ...................................................................................... ................................ 57 
 13.1 Implementação de Recursão ......................................................................................... 57 
 13.2 Recursão Degenerada .................................................................................................. 60 
 13.3 Eliminação de Recursão ................................................................................................ 62 
14 Árvores ................................................................................................................................ 64 
 14.1 Fundamentos ............................................................................................................ ..... 64 
 14.2 Árvores Binárias ............................................................................................................ 65 
 14.3 Percursos em Árvores Binárias ..................................................................................... 66 
 14.4 Algoritmos dos Percursos .............................................................................................. 68 
 14.5 Árvores de Busca Binária .............................................................................................. 70 
 14.6 Implementação de Árvores de Busca Binária ............................................................... 71 
Bibliografia ................................................................................................................ ................ 74 
ESTRUTURAS DE DADOS 
 
 
Instituição: Faculdade de Tecnologia de Botucatu 
Curso: Análise e Desenvolvimento de Sistemas 
Carga Horária: 04 h/a semanais – Total: 80 horas 
Professor Responsável: Rogério Ferreira Sgoti 
 
 
 
 
CONTEÚDO PROGRAMÁTICO 
 
Semana Tópicos 
1ª 
Apresentação da Disciplina: Objetivos, Ementa, Conteúdo 
Programático, Critério de Avaliação, Bibliografia. Revisão de Algoritmos: 
procedimentos, funções e passagens de parâmetros. 
2ª Registros. Aplicações, Sintaxes e Exemplos. Exercícios. 
3ª Manipulação de registros. Exercícios práticos. 
4ª 
Ordenação ou Classificação de dados. Conceitos. Algoritmos clássicos 
de ordenação. Simulação desses algoritmos. 
5ª 
Pesquisa ou Busca de dados. Conceitos. Algoritmos de Pesquisa 
Sequencial e Pesquisa Binária. 
6ª 
Cálculos de desempenho para algoritmos de pesquisa. Exemplos. 
Lista de Exercícios. Correção dos Exercícios. 
7ª 
Introdução às estruturas do tipo Lista. Conceitos e Aplicações. Tipos de 
Listas. Lista Estática Sequencial. Operações e Algoritmos. Simulação. 
8ª Lista Estática Encadeada. Operações e Algoritmos. Simulação. 
9ª Listas de Exercícios: listas estáticas – sequencial e encadeada. 
10ª Atendimento às dúvidas. 1ª Avaliação de Estruturas de Dados. 
11ª 
Alocação Estática X Alocação Dinâmica de Memória. Listas Dinâmicas. 
Conceitos e Aplicações. Exemplos. 
12ª 
Ponteiros. Conceitos. Notações. Exemplos. Operações e Algoritmos. 
Simulação. 
13ª 
Pilhas. Conceitos e Aplicações. Operações sobre Pilhas. Exemplos. 
Algoritmos. Simulação. 
14ª 
Filas. Conceitos e Aplicações. Operações sobre Filas. Exemplos. 
Algoritmos. Simulação. 
15ª 
Espalhamento (ou hashing). Conceitos e Aplicações. Exemplos. 
Tabelas de Espalhamento. 
16ª 
Recursividade. Conceitos e Aplicações. Vantagens e desvantagens do 
uso de recursividade. Exemplos. 
17ª 
Árvores. Conceitos e Aplicações. Operações sobre Árvores. Algoritmos. 
Exercícios. Simulação dos exercícios. 
18ª Atendimento às dúvidas. 2ª Avaliação de Estruturas de Dados. 
19ª Entrega de notase atendimento às dúvidas dos alunos. 
20ª Avaliação P3 de Estruturas de Dados e encerramento da disciplina. 
1 – INTRODUÇÃO AO ESTUDO DAS ESTRUTURAS DE DADOS 
 
 
Um programa de computador consiste em basicamente duas coisas: instruções e locais 
para se armazenarem dados e informações. Desse modo, as linguagens de programação são 
“equipadas” com mecanismos para poder controlar as instruções e os dados. Esses mecanismos 
são denominados “estruturas” e todas as linguagens de programação contemporâneas contam 
com dois tipos de estruturas: as estruturas de controle de fluxo de execução (para instruções) e 
as estruturas de dados (para os dados e informações). 
 
 
 Estruturas de Controle de Fluxo de Execução 
 
 Estrutura Sequencial; 
 Estruturas Condicionais; 
 Estruturas Iterativas; 
 Estruturas de Chamada/Retorno a/de Rotinas. 
 
 
 Estruturas de Dados 
 
 Estruturas Primitivas (Tipos de dados: inteiro, real, lógico e caracter); 
 
 Estruturas Compostas 
 
 Homogêneas (Vetores e Matrizes); 
 
 Heterogêneas (Registros e Arquivos). 
 
 Estruturas Complexas 
 
 Estáticas: Listas Estáticas (Sequenciais e Encadeadas), Pilhas, Filas, Árvores; 
 
 Dinâmicas: Listas Dinâmicas (Ponteiros), Pilhas, Filas, Árvores. 
 
 
 
2 – REVISÃO DE TÓPICOS 
 
 - Modularização; 
 
 - Variáveis Locais e Globais; 
 
 - Passagens de Parâmetros. 
 
 
Exemplos: 
 
 Algoritmos para cálculo do fatorial de um número n. 
 
 
 
Exercícios 
 
1) Escreva três algoritmos que recebam um número inteiro e exibam se esse número é primo ou 
não. Cada algoritmo com uma técnica diferente: procedimento com passagem de parâmetros por 
valor, procedimento com passagem de parâmetros por referência e por meio de função. 
 
2) Escreva um algoritmo que receba 100 números quaisquer e armazene-os em um vetor. 
Calcular e exibir o maior número e o menor número. 
 
 
 
3 – REGISTROS 
 
As estruturas de dados compostas, utilizadas até o momento (vetores e matrizes), 
permitem o armazenamento de vários valores na mesma estrutura, porém, cada estrutura só pode 
ser definida para um único tipo de dados. 
 Quando foi preciso utilizar dados de diferentes tipos para a solução de problemas, foi 
necessário o uso de diferentes estruturas. 
 Agora, é apresentada uma estrutura de dados em que é possível armazenar, na mesma 
estrutura, diversos valores de diferentes tipos de dados. Essa estrutura é chamada de Registro e, 
por sua característica, classificada como uma estrutura de dados heterogênea. 
 
Um exemplo de registro: 
 
 
 
 
 
 
 
 
 
 
 
 
Sintaxe: 
 TIPO 
 identificador_registro = REGISTRO 
 campo1: tipo de dado; 
 campo2: tipo de dado; 
 . 
 . 
 . 
 campoN: tipo de dado; 
 FIM; 
 VAR 
 identificador_variavel: identificador_registro; 
 
 
 
Exemplo: 
 BOLETIM ESCOLAR 
 
Aluno.......: Fulano de Tal 
 
1ª Nota....: 8,5 
2ª Nota....: 9,0 
3ª Nota....: 7,5 
 
Média......: 7,5 
 
 
 TIPO 
 cad_aluno = REGISTRO 
 nome: caracter; 
 nota1: real; 
 nota2: real; 
 nota3: real; 
 media: real; 
 FIM; 
 VAR 
 aluno: cad_aluno; 
 
 
Referência: 
 
identificador_variavel.campo 
 
 aluno.nome  “João”; 
 
 leia (aluno.nota1); 
 
 exiba (aluno.media); 
 
 
Exercício 
 
Escreva um algoritmo que receba o nome e as 4 notas de aluno, calcule e exiba a média das 
notas e a situação (aprovado ou reprovado) baseado na média maior ou igual a 6,0. 
 
Outro exemplo de registro: 
 
 
 
 
 
 
 
 
 
 
Exemplo: 
 
 TIPO 
 bimestre = VETOR [1..4] de real; 
 
 cad_aluno = REGISTRO 
 nome: caracter; 
 nota: bimestre; 
 media: real; 
 FIM; 
 VAR 
 aluno: cad_aluno; 
 i: inteiro; 
 
 
 BOLETIM ESCOLAR 
 
Aluno.......: Fulano de Tal 
 
Notas 
1 2 3 4 
 
 
Média......: 7,5 
 
Referência: 
 
identificador_variavel.campo[ i ] 
 
 leia (aluno.nota[ i ]); 
 
 exiba (aluno.nota[ i ]); 
 
Exercícios 
 
1) Escreva um algoritmo para manipular a ocorrência de um único aluno e suas 4 notas 
bimestrais. Receba os dados do usuário e exiba o boletim conforme o último layout apresentado. 
 
2) Idem ao anterior, porém manipular os dados para uma sala com 40 alunos. (E agora, como fica 
a estrutura de dados?). 
 
TIPO 
 bimestre = VETOR [1..4] de real; 
 
 cad_aluno = REGISTRO 
 nome: caracter; 
 nota: bimestre; 
 media: real; 
 FIM; 
 
 aluno_vet = VETOR [1..40] de cad_aluno; 
 
VAR 
 aluno: aluno_vet; 
 i, j: inteiro; 
 
 
Referências: 
 
 
 
 
leia (aluno[ i ].nome); 
 leia (aluno[ i ].nota [ j ]); 
 exiba (aluno[ i ].media); 
 
 
Exercícios 
 
1) Considerando o cadastro de uma agenda pessoal de nomes, telefones e cidades, defina a estrutura de 
registros apropriada e construa um algoritmo para armazenar 50 contatos nessa agenda. Após o 
armazenamento, exibir um relatório com os dados de todos os contatos que residem em Botucatu. 
 
 
2) Considerando o cadastro de uma agenda de prestadores de serviços contendo nome, código de área, 
telefone e cidade, defina a estrutura de registros apropriada e construa um algoritmo para armazenar 80 
contatos nessa agenda. Após o armazenamento, exibir um relatório com os dados de todos os prestadores 
de serviço de uma determinada área de telefone. Essa informação deve ser solicitada para o usuário. Obs: 
o código de área deve ser um campo separado do número do telefone (para possibilitar a consulta prevista 
no algoritmo). 
 
identificador_variavel[ i ].campo[ j ] identificador_variavel[ i ].campo 
4 – ALGORITMOS DE ORDENAÇÃO OU CLASSIFICAÇÃO 
 
 
4.1 Algoritmo Bubble Sort (ou método da bolha) 
 
Por ser simples e de fácil implementação o algoritmo Bubble Sort ou método da bolha está 
entre os mais conhecidos e difundidos métodos de ordenação de arranjos de dados. Mas não se 
trata do algoritmo mais eficiente. É estudado para desenvolvimento do raciocínio lógico e como 
introdução ao assunto de ordenação ou classificação de dados. 
O princípio da dinâmica de funcionamento desse algoritmo é o teste e a troca de valores 
entre as posições consecutivas do arranjo, fazendo com que os valores mais altos (ou mais 
baixos) “borbulhem” para o final do arranjo (ou começo). Este algoritmo realiza (n-1) iterações. 
 
Exemplo: 
 
 Situação inicial: 
1 2 3 4 5 
7 9 8 5 3 
 
 
1ª Iteração 
1 2 3 4 5 
7 8 5 3 9 
 
 
 2ª Iteração 
1 2 3 4 5 
7 5 3 8 9 
 
 
 3ª Iteração 
1 2 3 4 5 
5 3 7 8 9 
 
 
4ª Iteração 
 
1 2 3 4 5 
3 5 7 8 9 
 
 
 
 
Exercício 
 
Escreva um algoritmo que armazene 100 valores num vetor e exiba-os em ordem crescente, 
implementando o método bubblesort. 
 
 
 
4.2 Algoritmo Selection Sort 
 
O algoritmo do método de ordenação Selection Sort seleciona o maior elemento do arranjo 
e troca-o com o elemento da última posição. A cada iteração desconsidera a “última” posição do 
vetor fazendo com que o arranjo fique “menor”. Esse algoritmo também realiza (n-1) iterações 
para garantir que os elementos estejam ordenados. 
 
Dinâmica de funcionamento: 
 
- Na primeira iteração o algoritmo encontra o maior elemento do vetor e troca este 
elemento com o elemento que está na n-ésima posição; 
 
 - Na segunda iteração despreza-se o n-ésimo elemento e encontra-se novamente o maior 
elemento (exceto o maior elemento já identificado na primeira iteração, este segundo maior é o 
maior entre os demais) e troca-se com o elemento que está na (n-1)-ésima posição; 
 
 - Este processo se repete até que se tenha ordenado todos os elementos do arranjo. 
 
 
Exemplo: 
1 2 3 4 5 
7 9 8 5 3 
 
 
 - Percorre-se o vetor na busca do maior elemento. Neste caso, o maior elemento é o 9, que 
está na posição 2. Troca-se então esse elemento com o elemento que está na última posição. 
 
 
 Situação inicial: 
1 2 3 4 5 
7 9 8 5 3 
 
 
 
 
1ª Iteração 
1 2 3 4 5 
7 3 8 5 9 
 
 
 - Finalizada a primeira iteração inicia-se o processo novamente, selecionando o maior 
elementoe trocando-o com a penúltima posição. E assim sucessivamente... 
 
 
Exercício 
 
Escreva um algoritmo que armazene 100 valores num vetor e exiba-os em ordem crescente, 
implementando o método selection sort. 
 
 
 
 
4.3 Algoritmo Insertion Sort 
 
O algoritmo do método de ordenação Insertion Sort utiliza a técnica de indução algorítmica 
para resolver o problema de ordenação. Assim, sabendo-se resolver um problema menor, 
resolve-se um problema maior. 
Dinâmica de funcionamento: 
 
 Considere o vetor V assim definido: V = { V1, V2, V3, . . . ., Vn-1, Vn }. 
 
 Considere o vetor V´ assim definido e já ordenado: V´ = { V1}. 
i-maior 
 
 A dinâmica consiste em comparar do segundo elemento em diante do vetor V com o 
elemento (sempre já ordenado) do vetor V´ e inseri-los na posição correta do vetor V´. 
 
 Exemplo: 
1 2 3 4 5 
9 8 7 5 3 
 
 
 
Tem-se: V´ = 9 
 
 V = 8 7 5 3 
 
 Inserir o elemento 8 no vetor já ordenado V´. 
 
1 2 3 4 5 
9 8 7 5 3 
 
 
 Para inserir o elemento 8 na posição correta do vetor V´, desloca-se o elemento 9 
para uma posição a direita. 
 
1 2 3 4 5 
8 9 7 5 3 
 
 
 
 Assim, o processo se repete até que o vetor esteja ordenado. 
 
 
1 2 3 4 5 
8 9 7 5 3 
 
 
 
1 2 3 4 5 
7 8 9 5 3 
 
 
 
 
1 2 3 4 5 
5 7 8 9 3 
 
 
 
 
1 2 3 4 5 
3 5 7 8 9 
 
 
Exercício 
 
Escreva um algoritmo que armazene 100 valores num vetor e exiba-os em ordem crescente, 
implementando o método insertion sort. 
V´ V 
V´ V 
V´ V 
V´ V 
5 – ALGORITMOS DE PESQUISA (OU BUSCA) 
 
 
 São dois os métodos de pesquisa ou busca por uma ocorrência de algum elemento dentro 
de um arranjo de dados que são mais comumente usados. Geralmente é o usuário da aplicação 
quem fornece o valor do elemento que está sendo procurando e que tem interesse na pesquisa. 
Esses dois métodos são: a pesquisa sequencial e a pesquisa binária. 
 Sobre qual desses tipos de pesquisa apresenta o melhor resultado, depende-se 
exclusivamente da quantidade de operações realizadas para encontrar determinado elemento no 
arranjo. E isso é determinado por dois fatores: a quantidade de elementos do arranjo e a 
quantidade de consultas que se faça no mesmo. 
 Após conhecer como funcionam os dois tipos de pesquisa, no próximo capítulo serão 
apresentados alguns cálculos sobre como calcular a quantidade de operações necessárias para 
encontrar (ou não) um elemento dentro do arranjo de dados. Assim, pode-se decidir de modo 
mais exato, qual dos dois métodos é o melhor aplicar em cada situação. 
 
 
5.1 Pesquisa Sequencial 
 
O método de pesquisa sequencial consiste em efetuar a busca da informação desejada a 
partir do primeiro elemento, percorrendo o vetor sequencialmente até o último elemento. 
Localizando a informação procurada em algum dos elementos, esta é apresentada ao usuário e 
encerra-se a busca. Este método de pesquisa é, na média, um tanto lento. Porém, eficiente nos 
casos em que o vetor contenha seus elementos de forma desordenada. 
 
 Exercício: Escreva um algoritmo que implemente o método de pesquisa sequencial. 
 
 
5.2 Pesquisa Binária 
 
O método da pesquisa binária apresenta um mecanismo que, na média, se mostra mais 
rápido em comparação ao método da pesquisa sequencial. Uma diferença é que, para aplicar a 
pesquisa binária, o arranjo de dados deve, obrigatoriamente, estar previamente ordenado. 
Depois de ordenado o vetor, este é dividido em duas partes e examinado se a informação a 
ser pesquisada se encontra na linha de divisão (meio) do vetor ou se está acima ou abaixo desta 
linha de divisão. Se estiver acima, toda a metade inferior é desprezada para verificação. Em 
seguida, se a informação não foi encontrada no meio (lembre-se de que o vetor já está 
ordenado!), dividimos novamente esta metade do vetor em duas partes e examinamos se a 
informação está no meio, acima ou abaixo da linha divisória. Assim, o processo de divisão e 
descarte continua até que a informação seja encontrada ou até se acabar os elementos do 
arranjo. 
 
 
 
 
 
Exercício: Escreva um algoritmo que implemente o método de pesquisa binária. 
 
 
 
Exercício 
 
Escreva um algoritmo que exiba um menu para o usuário com as opções: Tamanho do Vetor, 
Armazenar Valores, Ordenar Valores, Tipo de Pesquisa, Pesquisar e Sair; e implemente essas 
funcionalidades. 
 
 
 
 
 
 
 
 
6 – COMPARATIVO ENTRE OS ALGORITMOS DE PESQUISA 
 
 
 Cálculo do nº de Operações para Pesquisas Sequencial e Binária 
 
 
Considerações: 
 
 Para a Ordenação do arranjo: 
 
o tem-se (n – 1) iterações; 
o o vetor verificará (n – 1) elementos; 
o logo, (n – 1).(n – 1) = n2 – 2n + 1. 
o a qtde de operações 
é proporcional a n2 
 
 
 Para a Pesquisa no arranjo: 
 
o n = nº de iterações por pesquisa ou nº de elementos do arranjo; 
o m = qtde de pesquisas; 
o op = nº de operações realizadas. 
 
 
 
 Pesquisa Sequencial 
 
 
Op = n . m 
 
 
 
 Pesquisa Binária 
 
 
- Na ordenação: op´ = n2 
 
- Na pesquisa: 
1ª iteração  n/2 = n/21 
 
 
 log2 (n) = x  
2ª iteração  n/4 = n/22 
3ª iteração  n/8 = n/23 
. . 
. . 
xª iteração  n/2x = 
 
 
 - Se forem realizadas m pesquisas, tem-se: op´´ = m . log2 (n) 
 
 - Logo, o nº total de operações para a pesquisa binária é dado por op = op´ + op´´ 
 
 -  
 
 Op = n2 + m . log2 (n) 
 
 
desprezível 
2x = n 
 Exemplo: Arranjo com 8 elementos 
 
 n = 8 
 
 log2 (8) = 
 
2x = 8 
 
x = 3 
 
 São necessárias 3 iterações (operações) 
 
 
 
 
 Exercícios 
 
 
 1) Dado um vetor com 8 elementos, decidir e apontar qual o melhor tipo de pesquisa a ser 
aplicada no caso de necessidade de 1000 consultas nesse vetor. 
 
 
 2) Considere um arranjo com 8192 elementos. Qual o tipo de pesquisa é mais vantajoso 
para 1000 consultas? 
 
 
 3) Dado um vetor com 30 elementos, indicar qual o melhor método de pesquisa para uma 
necessidade de 250 consultas. 
 
 
 4) Determinado arranjo contém 3875 elementos e há necessidade de realizar 327 
consultas. Nesse caso, qual método de pesquisa aplicar? 
 
 
 5) Dado um vetor com 1480 elementos e necessidade de 15 consultas qual tipo de 
pesquisa você implementaria? 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7 – LISTAS 
 
 
 Uma Lista é uma estrutura de dados que armazena em memória um conjunto de 
elementos, sendo estes dispostos um após o outro, como em uma lista telefônica, um catálogo de 
peças, entre outros. Existem vários tipos de listas, e as diferenças que os determinam são: o 
modo e a política como são realizadas as operações sobre cada tipo de lista. As principais 
operações são, entre outras, inclusão de elementos na lista, acesso a um determinado elemento 
da lista, exclusão de um elemento, verificação de lista vazia, verificação de lista cheia e 
quantidade de elementos na lista. 
A partir de agora, praticamente todas as estruturas de dados que serão estudadas são 
derivadas de algum tipo de lista. As listas podem ser classificadas de várias formas, que 
dependem de alguns fatores, como: o modo como é implementada a alocação de memória; a 
natureza de manipulação dos elementos da lista e, ainda, como ficam dispostos os elementos em 
relação à linearidade ou à hierarquia da estrutura. 
 
 
Classificação e Tipos de Listas 
 
 Quanto à Linearidade ou Hierarquia da Estrutura 
 
 Listas Lineares (Listas Seqüenciais, Encadeadas, Pilhas e Filas); 
 Listas Não-Lineares (Árvores). 
 
 Quanto à Alocação de Memória 
 
 Estática; 
 Dinâmica. 
 
 Quanto à Natureza de Manipulação dos Elementos 
 
 Sequencial; 
 Encadeada. 
 
 
8 – ALOCAÇÃO ESTÁTICA DE MEMÓRIA 
 
 Com alocação estática de memória, as listas podem ser implementadas de forma 
sequencial ou encadeada. 
 
 
8.1 – Lista Estática Sequencial 
 
 A lista estática sequencial é uma lista linear implementada como um arranjo de registros 
onde estão estabelecidas regras de precedência entre os seus elementos e se configura como 
uma coleção ordenada de componentes do mesmo tipo.Exs: Lista de telefones e Lista de alunos. 
 
 Características 
 
- Os elementos na lista estão ordenados e armazenados fisicamente em posições 
consecutivas; 
- A inserção de um elemento na posição i causa o deslocamento a direita dos 
elementos de i até o último; 
- A eliminação do elemento i requer o deslocamento a esquerda dos elementos (i+1) 
até o último; 
- Uma lista estática seqüencial L, ou é vazia ou pode ser descrita como: 
 
L = 
índice (i) 1 2 3 ... ... n 
elemento a1 a2 a3 ... ... an 
 
 onde: 
 a1 é o primeiro elemento da lista; 
 ai precede ai+1; 
 an é o último elemento da lista. 
 Vantagens 
 
- Acesso direto indexado a qualquer elemento da lista; 
- Tempo constante para acessar o elemento da posição i. 
 
 Desvantagens 
 
- Movimentação de elementos nas operações de inserção e eliminação; 
- O tamanho máximo da lista deve ser pré-estimado. 
 
 Quando usar 
 
- Listas pequenas; 
- O tamanho máximo da lista for bem definido; 
- Manipulação de dados com características de inserção e eliminação no final da 
lista. 
 
 
 Implementação 
 
TAD (Tipo Abstrato de Dados) 
 
CONST 
 max = ----; 
 
TIPO 
 Lista = REGISTRO 
 elem: VETOR [1..max] de T; 
 num: 0..max; 
 FIM; 
VAR 
 L: Lista; 
 
 
Exemplos: 
 
a) Rotina para criar uma lista estática sequencial. 
 
Procedimento CRIA_LISTA (var L: Lista); 
Inicio 
 L.num  0; 
Fim; 
Tipo de Dado 
inteiro, real, 
lógico ou caracter 
b) Rotina para verificar se a lista está ou não vazia. 
 
Funcao VAZIA (L: Lista): logico; 
Inicio 
 se (L.num = 0) 
 entao VAZIA  verdadeiro 
 senao VAZIA  falso; 
 fim se; 
Fim; 
 
 
Operações sobre Listas Estáticas Sequenciais 
 
 
Exercícios – Escreva, com base no TAD apresentado, as rotinas para as respectivas operações: 
 
1) Inserir um elemento na lista, em sequência. 
2) Inserir um elemento na lista, em determinada posição. 
3) Retornar o primeiro elemento da lista. 
4) Retornar o último elemento da lista. 
5) Retornar a quantidade de elementos da lista. 
6) Eliminar um elemento da lista (não sendo o último). 
7) Eliminar o último elemento da lista. 
8) Verificar se os elementos da lista estão ordenados. 
 
 
 
8.2 – Lista Estática Encadeada 
 
 
 Os elementos de uma lista estática encadeada são registros com um dos componentes 
(campos) destinados a guardar o endereço do próximo registro, possibilitando assim o 
encadeamento dos elementos da lista. Cada registro tem o seguinte formato: 
 
 
Valor lig Ex: Alessandra 2 
 
 
 
 Uma lista hipotética L possui os seguintes elementos: Bruna, Daniel, Kátia, Mário e Rose. 
Então, pode-se representar a lista L da seguinte forma: 
 
 
 
L = Bruna Daniel Kátia Mário Rose 
 
 
 
 
 
 
1 2 3 4 5 
1º 
elemento 
último 
elemento fim da 
lista 
 Para gerenciar esse tipo de lista deve-se trabalhar com dois conjuntos de informação: os 
elementos da lista (armazenados) e as posições da lista que ainda estão disponíveis. Obs: 
Considera-se como “fim da lista” o último elemento do vetor que tenha valor armazenado, que 
pode não ser necessariamente o tamanho máximo do vetor. Convencionou-se a utilizar o valor 0 
(zero) para referenciar o fim da lista. Assim tem-se: 
 
 
 
 
L = Bruna Daniel Kátia Mário Rose 
 
 
 
 
 
 
 Como exemplo o elemento com o valor “Kátia” será eliminado da lista. Nesse caso, o 
registro desta posição ficará disponível e pronto para ser usado novamente. Assim, a referência 
desse registro deve passar a integrar a lista denominada por “Dispo” que contém os registros 
ainda livres (disponíveis) da lista. 
 
 
 
 
 
L = Bruna Daniel Kátia Mário Rose 
 
 
 
 
 
 Se numa próxima inserção houver a necessidade de inserir o valor “Silvia” na lista, esta 
deve ficar configurada da seguinte forma: 
 
 
 
L = Bruna Daniel Silvia Mário Rose 
 
 
 
 
 
 Deve ficar claro que o que importa é o encadeamento dos elementos e não a ordem 
seqüencial física do armazenamento. 
 
 
 Vantagens 
 
- Não requer a movimentação dos elementos nas operações de inserção e eliminação; 
- Apenas os campos de ligação são manipulados e alterados. 
 
 
 Desvantagens 
 
- Necessário prever espaço máximo da lista; - Aumento no tempo de execução; 
- Necessidade de gerenciar o campo Dispo; - Reserva de espaço para Dispo. 
1 2 3 4 5 
1º 
elemento 
(Prim) 
último 
elemento 
Dispo 
6 ... max 
1 2 3 4 5 
1º 
elemento 
(Prim) 
último 
elemento 
Dispo 
6 ... max 
1 2 3 4 5 
1º 
elemento 
(Prim) 
último 
elemento 
Dispo 
6 ... max 
- O acesso não é indexado; 
 
 
 Quando usar 
 
- Quando for possível fazer uma boa previsão do espaço utilizado; 
- Quando o ganho dos movimentos dos elementos sobre a perda de acesso direto a cada 
elemento for compensatório. 
 
 
 Implementação 
TAD (Tipo Abstrato de Dados) 
 
CONST 
 max = ----; 
 
TIPO 
 endereço = 0..max; 
 
 Reg = REGISTRO 
 info: T; 
 lig: endereco; 
 FIM; 
 
 Lista = REGISTRO 
 A: VETOR [1..max] de Reg; 
 prim, dispo: endereco; 
 FIM; 
VAR 
 L: Lista; 
 
 
 Operações sobre listas seqüenciais encadeadas 
 
 
- Inicialização da lista; - Acesso ao último elemento da lista; 
 
- Inserção com a lista vazia e não vazia; - Verificação de lista vazia ou cheia; 
 
- Inserção antes ou após o registro x; - Eliminação de elementos da lista; 
 
- Acesso ao primeiro elemento da lista; - Qtde de elementos da lista. 
 
 
 
Exercícios – Escreva, com base no TAD apresentado, as rotinas para as respectivas operações: 
 
 
1) Inicializar uma lista estática encadeada. 
 
2) Retornar se a lista está vazia. 
 
3) Retornar se a lista está cheia. 
 
4) Inserir um elemento em lista vazia. 
 
5) Obter um nó (posição) da lista. 
 
6) Inserir um elemento em lista não vazia. 
 
7) Retornar o primeiro elemento da lista. 
 
8) Retornar o último elemento da lista. 
 
9) Retornar a quantidade de elementos da lista. 
 
10) Inserir um elemento após o elemento x. 
 
11) Eliminar um elemento da lista. 
 
12) Devolver um nó (posição) disponível para a lista. 
 
 
 
Esboço do T.A.D 
 
L 
A 
 
 
 
Info lig 
 
 
 
Info lig 
 
 
Info lig 
 
 
Info lig 
 
 
Info lig 
 
 
 
prim 
 
dispo 
 
 
 
 
 
1 2 3 ... max N ... 
 
 
9 – ALOCAÇÃO DINÂMICA DE MEMÓRIA 
 
 
9.1 – Ponteiros 
 
 Na alocação estática de memória, conforme já abordamos, há a necessidade de o 
programador fazer uma estimativa prévia da quantidade de memória a ser ocupada pelos dados 
de sua aplicação. Isso se deve porque as estruturas de dados estáticas necessitam ser 
declaradas antes do início do código, sendo assim, chamadas de estruturas pré-referenciadas. A 
partir daí o programador não tem muita flexibilidade para mudar essa situação. 
Em contrapartida, na alocação dinâmica de memória o programador dispõe de estruturas 
de dados pós-referenciadas, criando novos registros sob demanda e necessidade da aplicação, 
ficando limitação apenas em relação à quantidade de memória física disponível no hardware. 
As linguagens de programação modernas tornaram possível explicitar não apenas os 
dados, mas também os endereços desses dados. Isso é possível com a utilização de ponteiros, 
que são variáveis de memória que “apontam” para endereços de memória. Esses endereços de 
memória apontados pelos ponteiros são conhecidos como variáveis dinâmicas. 
 
 Exemplo: 
 
 
 
 
 
 
 
 
 
 A notação introduzida por Wirth para a linguagem de programação Pascal é: 
 
Type 
tp = ^T; 
 
 
Essa declaração expressa que valores do tipo tp são ponteiros para dados do tipo T. 
Portanto, lê-se o símbolo “^” como “ponteiro para”. 
 Valores para ponteiros são gerados quando dados correspondentes a seus tipos são 
alocados/desalocados dinamicamente. Em pascal os procedimentos new() e dispose() existem 
com esse propósito. 
 
Em pseudolinguagem serão adotados os comandos: 
 
 
 ALOCA: cria um ponteiro que automaticamente aponta para um endereço de memória 
existente. Ex: 
 
 ALOCA (p); =DESALOCA: destrói um ponteiro juntamente com a variável dinâmica associada. Ex: 
 
 
 DESALOCA (p); = 
 
2BF57 conteúdo 
p 2BF57 
ponteiro 
endereço 
físico 
variável 
dinâmica 
p variável dinâmica 
p variável dinâmica 
 Exemplo: 
 
 
ALGORITMO EXEMPLO; 
 
TIPO 
 p = ^ caracter; 
VAR 
 nome: p; 
 
INICIO 
 ALOCA (nome); 
 leia (nome^); 
 exiba (nome^); 
 DESALOCA (nome); 
FIM. 
 
 
 
Exercício: Usando os conceitos de ponteiro e variáveis dinâmicas, escreva um algoritmo que 
armazene o nome de um aluno e suas duas notas de prova. Calcule a média das notas e exiba o 
nome e a média. 
 
 
 
9.2 – Listas Dinâmicas 
 
 
 A implementação de listas dinâmicas é feita com o uso de ponteiros e dessa forma o 
trabalho de alocação de memória fica facilitado. É possível então criar registros por meio de 
ponteiros e, conforme a necessidade e a demanda, acrescentando elementos ou eliminando 
posições no arranjo de dados ou lista dinâmica. 
 
 
 
 Operações sobre Listas Dinâmicas 
 
- Criar lista vazia; 
- Inserir o primeiro elemento na lista; 
- Inserir elemento no início da lista; 
- Acessar o primeiro elemento; 
- Acessar o último elemento; 
- Quantidade de elementos da lista; 
- Inserir valor (após determinado elemento ou na posição x); 
- Eliminar elemento (após determinado elemento ou da posição x). 
 
 
 
 Registros com ponteiros 
 
Uma variável do tipo p_rec (por exemplo), aponta para ou é um ponteiro para um registro 
do tipo de dados registro, conforme trecho de declaração da estrutura de dados abaixo: 
 
 
 
TAD (Tipo Abstrato de Dados) 
 
TIPO 
 p_rec = ^rec; 
 
 Lista = p_rec; 
 
 rec = REGISTRO 
 info: T; 
 lig: Lista; 
 Fim; 
VAR 
 L: Lista; 
 
 
Obs: O tipo de dados ponteiro é o único tipo que pré-referencia outro tipo em Pascal. 
 
 
Um ponteiro do tipo “Lista” (definido na estrutura acima) pode assumir o conjunto de 
valores que corresponde a endereços reais de memória para os campos “info” e “lig”. 
Exemplo: 
 
 
 
 
 
Onde o conteúdo de P corresponde ao endereço do objeto (conjunto de campos info e lig). 
Esses endereços são as ligações das listas encadeadas dinâmicas. 
 
 
 
 Referências – Sintaxe 
 
 
- O acesso ao registro depende do tipo de alocação adotada. Se utilizar alocação em vetor, 
referencia-se como: L.A[p]; e se a alocação for dinâmica, referencia-se como: p^. 
 
 
- Para referenciar ponteiro, objeto e campo, as sintaxes são: 
 
 - ponteiro: p 
 
 - objeto: p^ 
 
 - campos: p^.info 
 p^.lig 
 
 
- Para referenciar e controlar a informação sobre fim da lista ou lista vazia, também se deve 
utilizar o valor 0 (zero), também conhecido como endereço nulo ou terra para esse fim. 
 
Obs: A linguagem de programação Pascal possui uma constante pré-definida para denotar 
esse endereço nulo chamada “nil”. 
 
 
P 
objeto endereço 
Info lig 
( ) 
 Ponteiro X Objeto apontado 
 
 
Ex: 
 a) p  q; (ponteiros) 
 
 
 b) p^  q^; (conteúdo dos registros apontados pelos ponteiros) 
 
 
 
 
Ex: 
 Situação Inicial 
 
 
 
 
 
 
 
 
 
 
 a) p  q; 
 
 
 
 
 
 
 
 
 
 
 b) p^.lig  q^.lig; 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Kátia Mário Rose 
Bruna Daniel Silvia 
Bruna Daniel Silvia 
Kátia Mário Rose 
Bruna Daniel Silvia 
p 
q 
p q 
p 
q 
 Manipulação de Registros 
 
1) Criação de um registro 
 
 
ALOCA (p); 
 
 
Substitui o procedimento Obter_No (j), utilizado em listas estáticas encadeadas, dada uma 
variável do tipo ponteiro para tipo ^rec. 
 
 
- Efetivamente aloca uma variável do tipo rec; 
- Gera um ponteiro ^rec apontado para aquela variável; 
- Atribui o ponteiro à variável p. 
 
A partir daí: 
 
- O ponteiro pode ser referenciado como p; 
- A variável referenciada por p é denotada por p^. 
 
 
2) Liberação de um registro 
 
 
DESALOCA (p); 
 
 
Substitui o procedimento Devolver_No (j). 
 
- Esta operação libera o espaço apontado por p; 
- p passa a ter valor indefinido. 
 
 
 
Exercícios – Escreva, com base no TAD apresentado, as rotinas para as respectivas operações: 
 
1) Criar uma lista. 
 
2) Retornar se a lista está ou não vazia. 
 
3) Inserir o primeiro elemento na lista. 
 
4) Inserir um elemento no início da lista. 
 
5) Inserir um elemento no final da lista. 
 
6) Retornar o primeiro elemento da lista. 
 
7) Retornar o último elemento da lista. 
 
8) Retornar a quantidade de elementos da lista. 
 
9) Inserir um elemento após outro na lista. 
 
10) Inserir um elemento na posição “x” da lista. 
 
11) Eliminar o primeiro elemento da lista. 
 
12) Eliminar o último elemento da lista. 
 
13) Eliminar o elemento da posição “x” da lista. 
p 
Info lig 
p 
Info lig 
Exercícios 
 
 
1) Diferencie Alocação Estática de Memória de Alocação Dinâmica de Memória. 
 
 
2) Explique o que são ponteiros. 
 
 
3) O que são listas? Explique e dê exemplos. 
 
 
4) Defina, sintaticamente: 
 
a) ponteiro 
 
b) objeto 
 
c) campo 
 
 
5) Explique os seguintes comandos de atribuição: 
 
a) p^  q^; 
 
b) p  p^.lig; 
 
c) p  q; 
 
 
1 2 3 4 5 
1 2 3 4 5 
1 2 3 4 5 
1 2 3 4 5 
1 2 3 4 5 
10 – PILHAS 
 
 
 Pilhas são listas onde as inserções de novos elementos ou as eliminações de elementos já 
armazenados se dão em uma única extremidade da lista: no topo. 
 Pilhas também são conhecidas como Listas LIFO (Last In First Out – Último que Entra, 
Primeiro que Sai), ou seja, o último elemento inserido é o primeiro a ser acessado, lido, excluído, 
processado. 
 
 
 
Pilha Vazia 
 
 
 
 
Insere (A) A 
 
 
 
 
Insere (B) A B 
 
 
 
 
Remove (B) A B 
 
 
 
 
Insere (C) A C 
 
 
 
 
 
 
10.1 Operações sobre Pilhas 
 
 
- Criar (P): cria uma pilha vazia; 
- Inserir (x, P): insere x no topo da pilha P. Também conhecida como empilha (ou push); 
- Vazia (P): testa se a pilha está vazia; 
- Topo (P): acessa o elemento do topo da pilha; 
- Remove (P): elimina um elemento da pilha P. Conhecida como desempilha (ou pop). 
 
 
 
 
 
 
 
topo 
topo 
topo 
topo 
topo 
10.2 Aplicações de Pilhas 
 
Exemplo: Chamadas de Rotinas 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Quando a rotina R1 é executada ela efetua uma chamada a rotina R2, que deve carregar 
consigo o endereço de retorno e1. Ao término de R2 o processamento deve retornar a 
rotina R1 no devido endereço. Situação idêntica ocorre em R2 e R3. 
Assim, quando um procedimento termina, é o seu endereço de retorno que deve ser 
consultado. Portanto, há uma lista implícita de endereços (e0, e1, e2, e3) que deve ser 
manipulada como uma pilha pelo sistema operacional para controle na execução de 
programas. Obs: e0 é o endereço de retorno de R1. 
 
 
 
10.3 Implementação de Pilhas 
 
 
Como implementar uma pilha? Como lista sequencial ou encadeada? No caso geral de 
listas ordenadas, a maior vantagem da alocação encadeada sobre a sequencial (se a 
memória não for problema) é a eliminação dos deslocamentos necessários quando da 
inserção ou eliminação dos elementos. 
No caso de pilhas, essas operações de deslocamentos não ocorrem. Portanto, pode-se 
afirmar que a alocação sequencial é mais vantajosa na maioria das vezes. 
 
 
 
10.4 Alocação Sequencial de Pilhas 
 
 
TAD (Tipo Abstrato de Dados) 
CONST 
 max_pilha = ----; 
 
TIPO 
 indice = 0..max_pilha; 
 
 Pilha = VETOR [1..max_pilha] de T; 
 
VAR 
 P: Pilha; 
 topo: indice; 
rotina R1; 
 
 
 
 R2; 
e1 
 
 
fim; 
rotina R2; 
 
 
 
 R3; 
e2 
 
 
fim; 
rotina R3; 
 
 
 
 R4; 
e3 
 
 
fim; 
rotina R4; 
 
 
 
 
 
 
 
fim; 
Exercícios – Escreva, com base no TAD apresentado, as rotinas para as respectivas operações: 
 
 
1) Criar uma pilha. 
 
2) Retornar se a pilha está vazia. 
 
3) Retornar se a pilha está cheia. 
 
4) Inserir um elemento na pilha (empilhar). 
 
5) Acessar elemento da pilha. 
 
6) Eliminarelemento da pilha. 
 
7) Acessar elemento da pilha e eliminá-lo em seguida (desempilhar). 
 
 
 
 
 
 
 
 
 
 
 
 
10.5 Alocação Dinâmica de Pilhas 
 
 
TAD (Tipo Abstrato de Dados) 
TIPO 
 pont = ^reg_pilha; 
 
 Pilha = pont; 
 
 reg_pilha = REGISTRO 
 info: T; 
 lig: pont; 
 FIM; 
VAR 
 P: Pilha; 
 
 
 
Exercícios – Escreva, com base no TAD apresentado, as rotinas para as respectivas operações: 
 
 
1) Criar uma pilha. 
 
2) Retornar se a pilha está vazia. 
 
3) Empilhar um elemento. 
 
4) Acessar a pilha. 
 
5) Eliminar elemento da pilha. 
 
6) Desempilhar elemento. 
 
 
 
 
 
 
 
 
 
 
 
11 – FILAS 
 
 
 Filas são listas em que as inserções de novos elementos são feitas numa extremidade da 
lista e as eliminações na outra.Filas também são conhecidas como Listas FIFO (First In First Out 
– Primeiro que Entra, Primeiro que Sai), ou seja, o primeiro elemento inserido é o primeiro a ser 
acessado, lido, excluído, processado. 
 
 
( a1, a2, a3, ..., an -1, an ) 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11.1 Operações sobre Filas 
 
- Criar (F) – cria uma fila vazia; 
- Inserir (x, F) – insere x no final da fila; 
- Vazia (F) – testa se a fila esta vazia; 
- Primeiro (F) – acessa o elemento do inicio da fila; 
- Ultimo (F) – acessa o elemento do final da fila; 
- Elimina (F) – elimina o elemento do inicio da fila. 
 
 
 
11.2 Aplicações de Filas 
 
Exemplo: Escalonamento de jobs (fila de processos aguardando recursos do S.O.). 
 
 
 
 
11.3 Implementação de Filas 
 
Como implementar uma fila? Como lista sequencial ou encadeada? Estática ou Dinâmica? 
Só tem sentido falar em fila sequencial estática ou fila encadeada dinâmica, uma vez que 
não existe movimentação de elementos. As filas encadeadas são usadas quando não há 
previsão do tamanho máximo da fila. 
 
 
Fila 
Eliminações 
no Início 
Inserções 
no Final 
Começo Final 
11.4 Alocação Estática Sequencial de Filas 
 
 
TAD (Tipo Abstrato de Dados) 
CONST 
 max_fila = ----; 
 
TIPO 
 indice = 0..max_fila; 
 
 Fila = VETOR [1..max_fila] de T; 
 
VAR 
 F: Fila; 
 Comeco, {posição anterior ao primeiro elemento} 
Final: indice; {posição do último elemento} 
 
 
 
Exercícios – Escreva, com base no TAD apresentado, as rotinas para as respectivas operações: 
 
 
1) Criar uma fila. 
 
2) Retornar se a fila está vazia. 
 
3) Retornar se a fila está cheia. 
 
4) Inserir um elemento na fila. 
 
5) Acessar o primeiro elemento da fila. 
 
6) Acessar o último elemento da fila. 
 
7) Eliminar elemento da fila. 
 
 
 
 Problemas na Alocação Estática Sequencial de Filas 
 
 
O que aconteceria com a fila considerando a seguinte sequência de operações? I, E, I, E, I, 
E, I, E. Legenda: I – Inclusão; E – Exclusão. 
 
Resp.  A fila terá sempre um elemento (ou nenhum), e no entanto, num certo 
momento: 
 
 
 
 
 
 
 
 
 
Fila 
Começo 
Final 
 Ou seja, apenas um elemento (ou nenhum) na fila, ocupando a última posição do 
vetor. Na próxima inserção ocorrerá uma condição de overflow e na verdade a fila está 
vazia! 
 
 
Exercício: Implemente uma solução para resolver o problema. 
 
 
Solução: Na rotina de eliminação, após a atualização da variável Comeco, verificar se a fila 
ficou vazia, isto é, se Comeco = Final. Neste caso, reinicializar: Comeco e Final  0. 
 
 
Procedimento ELIMINA (var Comeco, Final: indice); 
Inicio 
 se (VAZIA = falso) 
 entao Comeco  Comeco + 1; 
 se (Comeco = Final) 
 entao Comeco  0; 
 Final  0; 
 fim se; 
 fim se; 
Fim; 
 
 
E o que aconteceria com a fila se a sequência de operações fosse: I, I, E, I, E, I, E, I, E, I? 
 
Resp.:  A fila estaria com no máximo dois elementos e ainda assim ocorreria 
overflow com a fila quase vazia. 
 
 
 
Alternativa: Forçar Final a usar o espaço liberado por Comeco, implementando o que se 
conhece por Fila Circular! 
 
 
 
11.5 Fila Circular 
 
Fila Circular implementada como um Anel. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Começo 
Final 
Condições: 
 
 
- Índices do vetor: 0..max_fila - 1; 
 
- Variáveis de controle: comeco e final; 
 
- Inicialmente: comeco = final = 0; 
 
- Quando Final = max_fila - 1, o próximo elemento será inserido na posição 0 (se essa 
posição estiver vazia!); 
 
- Condição de fila vazia: Comeco = Final. 
 
 
 
 
T.A.D. 
 
 TIPO 
indice = 0..max_fila - 1; 
 
Fila = VETOR [0..max_fila -1] de T; 
 
 VAR 
 F: Fila; 
 Comeco, Final: indice; 
 
 
 
 
Procedimento INSERE (var F: Fila; var Final: indice; Comeco: indice; valor: T); 
Inicio 
 se ( (Final + 1) MOD max_fila = Comeco) ) 
 entao exiba (“Fila Cheia!”) 
 senao 
 Final  (Final + 1) MOD max_fila; 
 F [Final]  valor; 
 fim se; 
Fim; 
 
 
 
Procedimento ELIMINA (var Comeco: indice); 
Inicio 
 Comeco  (Comeco + 1) MOD max_fila; 
Fim; 
 
 
 
 
 
 
11.6 Alocação Dinâmica de Filas 
 
 
TAD (Tipo Abstrato de Dados) 
 
 TIPO 
pont = ^reg_fila; 
 
Fila = pont; 
 
reg_fila = REGISTRO 
 info: T; 
 lig: pont; 
 FIM; 
 VAR 
 Comeco, Final: Fila; 
 
 
 
Exercícios – Escreva, com base no TAD apresentado, as rotinas para as respectivas operações: 
 
 
1) Criar uma fila. 
 
2) Retornar se a fila está vazia. 
 
3) Inserir o primeiro elemento na fila. 
 
4) Inserir um elemento na fila. 
 
5) Retornar o primeiro elemento da fila. 
 
6) Retornar o último elemento da fila. 
 
7) Eliminar elemento da fila. 
 
 
 
 
 
12 – ESPALHAMENTO (HASHING) 
 
 
• Técnica eficiente para armazenamento e recuperação de dados; 
 
• Vantagem: não requer ordenação dos dados. 
 
 
12.1 Fundamentos 
 
• Chama-se espalhamento (ou hashing) de um conjunto C a sua divisão em um número finito 
de partes: C1, C2,..., Cn, para n>1, tal que: 
 
• C1 ᴗ C2 ᴗ ... ᴗ Cn = C, ou seja, todo elemento de C ocorre em uma dessas partes; 
 
• Ci ∩ Cj = Ø, para 1 ≤ i < j ≤ n, isto é, nenhum elemento de C ocorre em mais de uma 
dessas partes; 
 
• Tais propriedades garantem que em um espalhamento de um conjunto C em n partes, 
nenhum elemento seja perdido ou duplicado; 
 
• A distribuição unívoca dos elementos de C em n partes, sugere a existência de uma função 
h: [1..n], denominada função de espalhamento, que mapeia cada elemento de C à sua 
respectiva parte Ci, isto é: x Є C x Є C h(x); 
 
• Caso um espalhamento efetuado por uma função h e o resultado da diferença absoluta 
entre os tamanhos de duas partes quaisquer seja no máximo 1, diz-se que essa função h é 
ótima; 
 
• Exemplo: 
 
Sejam o conjunto C = {a,b,c,d,e} e h uma função de espalhamento h: C [1..3] que 
resulte nos seguintes valores para os elementos de C: 
 
h(a) = 2 
h(b) = 1 
h(c) = 3 
h(d) = 3 
h(e) = 1 
 
Então, por h, os elementos de C serão distribuídos da seguinte forma: 
 
C1 = {b,e} 
C2 = {a} 
C3 = {c,d} 
 
 
• Como a diferença absoluta entre os tamanhos das partes de C geradas pela função h é de 
no máximo 1, pode-se dizer que essa função é ótima para esse espalhamento; 
 
• Como todas as partes de C possuem aproximadamente o mesmo tamanho, diz-se que o 
espalhamento é uniforme, ou seja, a menor parte possui (|C| div n) elementos e a maior 
parte possui (|C| div n) + 1 elementos; 
 
• Considerando o espalhamento de um conjunto C, por uma função ótima (h: C [1..|C|]), 
isto é, o número de partes é igual ao número de elementos do conjunto C, e que o 
espalhamento é uniforme (h é ótima!), cada parte terá exatamente um elemento do 
conjunto C, e aí se diz que o espalhamento é perfeito; 
 
• Na prática é muito difícil de se obter espalhamentos perfeitos. Geralmente, ao menos uma 
das partes é vazia ou possui mais de um elemento (colisão); 
 
• Aplicações de Espalhamento 
• Consultas; 
• Transformação de elementos alfanuméricos; 
• Tratamento de permutações. 
 
• Considere x Є C e o valor h (x) que possibilita acesso direto na parte de C que contém x. 
Assim, caso C seja um arranjo a ser consultado, um espalhamento permitirá um processo 
de busca muito eficiente, pois essa busca estará restritaa uma pequena parte do conjunto 
C; 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
• Espalhamento  técnica de redução do espaço de busca. Quando o tamanho das partes 
diminui, a eficiência da busca aumenta. Na situação extrema do espalhamento perfeito, o 
valor h (x) permite acesso direto à posição de x, tornando-se o mais eficiente método de 
busca existente. 
 
 
12.2 Funções de Espalhamento 
 
• Mapeia cada elemento de um conjunto em um endereço; 
 
• Situação ideal: n elementos distintos  n endereços distintos; 
 
• Existem n! modos de se fazer esse mapeamento ideal; 
 
• Existem nn maneiras de mapear n elementos a n endereços; 
 
• Probabilidade espalhamento perfeito: mínima! (n!/nn); 
 
• Contente-se com funções de mapeamentos razoáveis (distribuições de elementos 
medianamente uniformes em endereços); 
 
• Já foi dispendido muito esforço para se criar funções de espalhamentos eficientes. 
Paradoxalmente, um dos métodos mais simples (divisão) é o que vem apresentando os 
melhores resultados na prática. 
 
x = “João” 
Antônio 
 Pietra 
João 
 Carla 
Martin 
C 
Busca sem espalhamento 
C
3
 
x = “João” 
h(x) = 2 
Antônio 
 Pietra 
 
 João 
 Carla 
 
Martin 
C
2
 
C
1
 
Busca com espalhamento 
Antônio 
 
 Pietra 
 
 João 
 
 Carla 
 
Martin 
x = “João” 
h(x) = 3 
C
1
 
C
2
 
C
3
 
C
4
 
C
5
 
Espalhamento perfeito 
• Método da Divisão 
 
• Indicado para C como subconjunto de N; 
 
• Efetua-se uma divisão por n, considere o resto e soma-se 1; 
 
• Exemplo: 
 
Para n = 3 e C = {9, 12, 22, 35, 47, 51}, tem-se os seguintes valores para h: 
 
h (9) = ( 9 mod 3) + 1 = 1 
h (12) = (12 mod 3) + 1 = 1 
h (22) = (22 mod 3) + 1 = 2 
h (35) = (35 mod 3) + 1 = 3 
h (47) = (47 mod 3) + 1 = 3 
h (51) = (51 mod 3) + 1 = 1 
 
• Portanto: 
 
C1 = {9, 12, 51} 
C2 = {22} 
C3 = {35,47} 
 
 
• Transformação de Elementos Alfanuméricos 
 
• Com elementos alfanuméricos o método da divisão não pode ser usado direto; 
• Devem, antes, serem convertidos em valores numéricos; 
• Dica: somar o código ASCII de cada caracter do elemento; 
• Exemplo em Pascal: 
 
function h (x: string): integer; 
var i, s: integer; 
begin 
 s := 0; 
 for i := 1 to length (x) do 
 s := s + ord (x[i]); 
 h := (s mod n) + 1; 
end; 
 
 
• Considere: 
 
 n = 7 e C = {Bia, Décio, Edu, Lucy, Neusa, Rose, Sueli, Thais, Yara} 
 
• Tem-se: 
 
h (“Bia”) = 3 Portanto: 
h (“Décio”) = 2 
h (“Edu”) = 7 C1 = {Lucy} 
h (“Lucy”) = 1 C2 = {Décio, Thais} 
h (“Neusa”) = 5 C3 = {Bia} 
h (“Rose”) = 4 C4 = {Rose, Sueli} 
h (“Sueli”) = 4 C5 = {Neusa} 
h (“Thais”) = 2 C6 = {Yara} 
h (“Yara”) = 6 C7 = {Edu} 
 
12.3 Tabelas de Espalhamento 
 
 
• Estruturas de dados que permitem a implementação do espalhamento de um conjunto C 
em aplicações computacionais; 
 
 
• Representada por um vetor onde cada posição (encaixe), mantém uma parte de C; 
 
 
• Evidente: número de encaixes coincide com o número de partes criadas pela função de 
espalhamento; 
 
 
• Se admitir a existência de elementos sinônimos em C, espera-se a ocorrência de pelo 
menos uma colisão (necessidade de armazenar um elemento em uma posição já ocupada); 
 
 
• Solução: tratamento de colisão por espalhamento externo; 
 
 
• Princípio de que existirão muitas colisões na inserção dos elementos numa tabela; 
 
 
• Ao invés de armazenar só um elemento, cada encaixe T[i] guardará uma coleção de 
elementos sinônimos. Como a quantidade destes pode variar bastante, recomenda-se o 
uso de lista encadeada; 
 
 
• Assim, uma tabela de espalhamento externo será um vetor de listas encadeadas, cada 
uma delas uma parte de C; 
 
 
• O termo “externo” se dá em função dos elementos serem armazenados fora da tabela de 
espalhamento (área de memória alocada de modo dinâmico). 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1 
2 
3 
4 
5 
23 62 
8 14 
11 51 37 
34 83 59 
8 14 
• Tipo Abstrato de Dados (TAD) 
 
 Const 
 n = 5; 
 Tipo 
 Lista = ^rec; 
 rec = REGISTRO 
 info: T; 
 lig: Lista; 
 FIM; 
 Tab_Esp = VETOR [1..n] de Lista; 
 Var 
 TE: Tab_Esp; 
 
 
• Operações Básicas com Tabelas de Espalhamento 
 
Inicialização da Tabela 
 
Procedimento INICIALIZA_TABELA (var TE: Tab_Esp); 
 var 
 i: integer; 
 Inicio 
 para i  1 to n faca 
 CRIAR_LISTA (TE[i]); 
 fim para; 
 Fim; 
 
Inserção na Tabela 
 
Procedimento INSERE_TABELA (var TE: Tab_Esp; valor: T); 
Inicio 
 se (L = 0) 
 entao INSERE_PRIMEIRO_ELEMENTO (TE [ h(valor) ], valor: T ) 
 senao INSERE_INICIO_LISTA (TE [ h(valor) ], valor: T ); 
 fim se; 
Fim; 
 
Eliminação de elemento da Tabela 
 
Procedimento ELIMINA_ELEMENTO (var L: Lista; valor: T); {a lista deve estar ordenada} 
var n, p: Lista; 
Inicio 
 se (valor = L^.info) 
 entao n  L; 
 L  L^.lig; 
 DESALOCA (n); 
 senao p  L; 
 enquanto (p^.lig <> 0) E (valor > p^.lig^.info) faca 
 p  p^.lig; 
 fim enquanto; 
 n  p^.lig; 
 p^.lig  n^.lig; 
 DESALOCA (n); 
 fim se; 
Fim; 
 
Procedimento ELIMINA_ELEMENTO_TABELA (var TE: Tab_Esp; valor: T); 
Inicio 
 ELIMINA_ELEMENTO (TE [ h (valor) ], valor: T ); 
Fim; 
13 – RECURSIVIDADE 
 
 
• Método que possibilita a solução de um problema P a partir das soluções de subproblemas 
de P e que são semelhantes ao próprio P; 
 
• Decompõe-se P até a obtenção de subproblemas simples que possam ser resolvidos 
diretamente sem ser preciso novas decomposições (triviais); 
 
• Os resultados obtidos compõem a solução do problema original; 
 
• Considere P(i) um algoritmo que resolve o problema P com entrada i. Diz-se que P(i) é uma 
instância de P. Sendo P(i) e P(i’) duas instâncias de P, denota-se P(i’) < P(i) indicando 
que P(i’) é mais simples que P(i); 
 
• Podendo uma instância ser decomposta em outra mais simples, diz-se que ela é não 
trivial e pode ser reduzida. Quando uma instância não pode ser reduzida ela é 
denominada trivial; 
 
 
 
 
• Um algoritmo recursivo é composto de duas partes de destaque: 
 
• base de recursão (resolve instâncias triviais diretamente); 
 
• passo de recursão (resolve instâncias não triviais recursivamente); 
 
 
13.1 Implementação de Recursão 
 
• Exemplo: Cálculo de fatorial 
 
• Def.: 
 1 para n = 0 
 
 n...3.2.1 para n > 0 
 
 
 
• Tomando por exemplo: a instância 3! é mais simples que a instância 4!, pois 3! necessita 
de uma multiplicação a menos que 4!; 
 
• Como 0 é o menor número natural, a instância 0! não pode mais ser reduzida à outra 
instância mais simples (:. é trivial); 
n! = 
• Classificadas as instâncias do problema fatorial em triviais e não triviais, pode-se resolvê-
las aplicando as seguintes regras: 
 
• Base de recursão: para n=0, a instância n! é trivial e sua solução é 1; 
 
• Passo de recursão: para n>0, a instância n! é não trivial e sua solução é n.(n-1)!. 
 
 
 
 
 
Pseudocódigo 
 
Funcao fat (n: inteiro): inteiro; 
Inicio 
 se (n = 0) 
 entao fat  1 
 senao fat  n * fat (n – 1); 
Fim; 
 
 
Simulação da execução de fat(4) usando substituições sucessivas 
 
 
 
 
 
 
 
 
Outro modo de simular a dinâmica de uma função recursiva 
 
 
fat(4) = 4 * fat(3) = 4 * 3 * fat(2) = 4 * 3 * 2 * fat(1) = 4 * 3 * 2 * 1 * fat(0) = 4 * 3 * 2 * 1 *1 
Substituições sucessivas efetuadas para alcançar uma instância trivial Instância 
não trivial 
Solução 
obtida 
24 = 
 
 
• Para cada chamada recursiva, reduz-se uma instância não trivial em outra mais simples e a 
operação de multiplicação fica pendente, esperando a propagação da resolução da 
instância mais simples; 
 
• Considera-se que a função que chama fica congelada, esperando a finalização da 
chamada recursiva para a continuidade da execução; 
 
• Isso é possível porque há o empilhamento do endereço de retorno da função que faz a 
chamada,da qual a execução deve seguir na instrução que faz o cálculo da multiplicação; 
 
• Ao se obter a instância trivial, as chamadas “congeladas” são reativadas em uma ordem 
inversa daquela em que ocorreram; 
 
• Por essa razão a base de recursão de uma função recursiva é tão importante!; 
 
• Sem ela, o circuito cíclico das chamadas recursivas nunca será finalizado, gerando o que é 
conhecido como stack overflow, ou seja, um erro que causa o estouro da pilha que controla 
o fluxo de execução da função. 
 
Outros exemplos usando recursão 
 
Cálculo de Potência 
 
 As regras utilizadas para determinar as instâncias do problema da potenciação são: 
 
 Base de recursão: se n = 0, a instância xn é trivial e sua solução é 1; 
 Passo de recursão: se n > 0, a instância xn é não trivial e sua solução é x.xn-1. 
 
 
 
 
 
 
 
 
 
 
 
 
2
3
 
8 
4 
*2 
2
2
 
Caso geral 
*n 
x
n - 1
 x
n - 1
 
x.x
n - 1
 
x
n
 
Caso particular 
Pseudocódigo 
 
Funcao potencia (x: real; n: inteiro): real; 
Inicio 
 se (n = 0) 
 entao potencia  1 
 senao potencia  x * potencia (x, n-1); 
Fim; 
 
 
13.2 Recursão Degenerada 
 
• Os aspectos de simplicidade e legibilidade se apresentam como principais benefícios da 
técnica de recursão; 
 
• Entretanto, existem dois casos em que tais benefícios não são alcançados: 
 
 Recursão de Cauda; 
 Recursão Redundante. 
 
Recursão de Cauda 
 
• Ocorre quando existe uma única chamada recursiva no final de uma rotina. Assim, 
nenhuma instrução dessa rotina fica pendente de ser executada depois de terminar a 
execução dessa chamada recursiva; 
 
• Portanto, o único objetivo dessa recursão (cauda) é a criação de um looping, o qual 
pode ser mais eficientemente implementado por um comando iterativo. 
 
Funcao SOMA (n1, n2: inteiro): inteiro; 
Inicio 
 se (n1 = 0) 
 entao SOMA  n2 
 senao SOMA  SOMA (pred (n1), succ (n2) ); 
Fim; 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Execução da chamada recursiva SOMA (3,4) 
SOMA(3,4) 7 
SOMA(2,5) 
SOMA(1,6) 
SOMA(0,7) 
7 
7 
7 
• A utilização de recursão deixa essa execução mais custosa, pois cada chamada 
recursiva necessita da alocação de variáveis locais para armazenar os parâmetros n1 e 
n2, e também empilhar o endereço de retorno para a função que realiza a chamada; 
 
• Conclui-se que é mais eficiente substituir essa recursão por um laço iterativo. 
 
 
Funcao SOMA (n1, n2: inteiro): inteiro; 
Inicio 
 Enquanto (n1 > 0) faca 
 n1  pred (n1); 
 n2  succ (n2); 
 Fim Enquanto; 
 SOMA  n2; 
Fim; 
 
 
Recursão Redundante 
 
• Outro exemplo no qual uma solução iterativa é mais vantajosa que uma recursiva são 
os casos em que ao decompor o problema resultam inúmeros subproblemas iguais (por 
isso, recursão redundante!); 
 
• Exemplo: sequência de Fibonacci (1, 1, 2, 3, 5, 8, 13, ...). 
 
 
Funcao FIBO (n: inteiro): inteiro; 
Inicio 
 se (n < 3) 
 entao FIBO  1 
 senao FIBO  FIBO (n - 2) + FIBO (n - 1); 
Fim; 
 
 
 
 
 
 
Solução iterativa em substituição à função recursiva para cálculo de Fibonacci 
 
Funcao FIBO (n: inteiro): inteiro; 
var 
 i, a, b, c: inteiro; 
Inicio 
 a  1; 
 b  0; 
 para i  1 ate n faca 
 c  a + b; 
 a  b; 
 b  c; 
 fim para; 
 FIBO  c; 
Fim; 
 
 
13.3 Eliminação de Recursão 
 
• O controle do fluxo entre chamadas/retornos de rotinas é realizado por uma pilha 
administrada pelo SO que vai empilhando endereços de retorno e as variáveis locais; 
 
• Desse modo, usando instruções iterativas e pilhas, podemos converter qualquer rotina 
recursiva em uma rotina iterativa; 
 
• Em geral, rotinas iterativas são mais rápidas que rotinas recursivas; 
 
• No entanto, caso haja uma quantidade muito grande de instruções iterativas e muitas pilhas 
para converter recursão em iteração, talvez seja melhor ficar com a versão recursiva 
mesmo; 
 
• Um programa com código simples e claro é mais vantajoso que outro que execute apenas 
ligeiramente mais rápido; 
 
• Quando uma chamada recursiva é executada, o endereço de retorno e todas as variáveis 
locais precisam ser recriadas na pilha; 
 
• Exemplo: chamada recursiva de fat(4). 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
• Ao ser executada, a variável n é criada no topo da pilha com o valor passado no momento 
da chamada. Ao terminar, a última cópia de n criada é destruída. Desse modo, em 
qualquer instante da execução o valor de n será o que estiver no topo da pilha. 
 
 
Relação entre Recursão e a estrutura de Pilha 
 
• Para melhor compreensão da relação entre recursividade e manipulação de pilhas, observe 
o procedimento recursivo abaixo, o qual exibe os itens de uma lista ordenada em ordem 
inversa. 
Fat (4) 
4 
n 
Fat (3) 
3 
4 
n 
Fat (2) 
3 
2 
4 
n 
Fat (1) 
3 
2 
1 
4 
Fat (0) 
3 
2 
1 
0 
4 n 
n 
 
 
Procedimento Exibe_Itens (L: lst_ord); 
Inicio 
 se (nao VAZIA (L) ) 
 entao 
 Exibe_Itens (restante (L) ); 
 exiba (primeiro (L) ); 
 fim se; 
Fim; 
 
 
 
 
 
• Para a exibição dos itens de uma lista em ordem inversa o algoritmo deve exibir o resto 
dessa lista em ordem inversa e, por último, exibir o primeiro item; 
 
• Para cada chamada recursiva ( Exibe_Itens (L) ) uma cópia da variável L é criada para 
manter o endereço do próximo bloco dessa lista; 
 
• Durante as etapas de execução os endereços dos blocos vão sendo empilhados até a lista 
ficar vazia, momento em que se retorna o controle para a instrução exiba ( primeiro (L) ), a 
qual vai exibir os itens da lista, do último para o primeiro (ordem inversa); 
 
• Nota-se, nesse caso, que o único objetivo desse procedimento recursivo é o de simular 
uma pilha onde os endereços dos blocos da lista precisam esperar o momento para os 
itens serem exibidos; 
 
• Assim, com o uso de uma pilha, pode-se substituir o procedimento recursivo por uma 
versão iterativa equivalente, conforme o código a seguir. 
 
 
Procedimento Exibe_Itens (L: lst_ord); 
 
var 
 P: Pilha; 
 
Inicio 
 
 CRIA (P); 
 
 Enquanto (nao VAZIA (L) ) faca 
 EMPILHA (primeiro (L), P ); 
 L  resto (L); 
 Fim Enquanto; 
 
 Enquanto (nao VAZIA (P) ) faca 
 exiba (DESEMPILHA (P) ); 
 Fim Enquanto; 
 
Fim; 
 
 
 
Funcao restante (L: Lista): Lista; 
Inicio 
 restante  L^.lig; 
Fim; 
 
 
 
Funcao primeiro (L: Lista): T; 
Inicio 
 primeiro  L^.info; 
Fim; 
 
 
 
Etapa de reduções 
Etapa de propagação 
14 – ÁRVORES 
 
 
• Árvores são estruturas de dados que permitem organizar dados de modo hierárquico. 
 
 
14.1 Fundamentos 
 
• Uma árvore A é uma estrutura composta por n nós, para n ≥ 0; 
 
• Para n = 0, diz-se que a árvore A é vazia; Senão: 
 
 há um nó especial em A chamado de raiz; 
 
 os outros nós de A são organizados em A1, A2, ..., Ak estruturas de árvores 
disjuntas, denominadas de subárvores de A. 
 
• Por definição, árvores são estruturas recursivas, isto é, caso a raiz de uma árvore 
seja removida, tem-se uma coleção de árvores; 
 
• Cada nó de uma árvore é raiz de alguma subárvore; 
 
• Representação gráfica de uma árvore 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
• Nó pai e nó filho; 
 
• A raiz (principal) de uma árvore é o único nó que não tem pai; 
 
• A quantidade de filhos de um nó é denominada grau, assim como um nó que tenha 
grau 0 é denominado folha; 
 
• O grau de uma árvore é o máximo entre os graus de seus nós; 
 
• A altura de uma árvore é o máximo dos níveis de seus nós; 
 
• Por definição, uma árvore vazia possui altura 0; 
 
• Árvores são usadas para representar dados e informações com necessidade de 
organização de modo hierárquico. Exemplos: árvores genealógicas, árvores 
gramaticais, árvores taxonômicas, entre outros; 
A 
B C 
D F E 
G 
• Na área de sistemas operacionais são úteis na representação de arquivos e 
estruturas de diretórios e subdiretórios além de outras aplicações (adiante). 
 
 
14.2 Árvores Binárias 
 
 
 Uma árvore binária é um tipo particular de árvore que possui grau 2 e onde se distingueuma subárvore esquerda de uma subárvore direita; 
 
 Definição do tipo árvore binária 
 
 Tipo 
 arvb = ^bloco_no; 
 bloco_no = registro 
 esq: arvb; 
 info: T; 
 dir: arvb; 
 fim; 
 
 
Operações básicas com árvores binárias 
 
Criação de uma árvore 
 
Funcao NO (e: arvb; valor: T; d: arvb): arvb; 
var 
 A: arvb; 
Inicio 
 Aloca (A); 
 A^.esq  e; 
 A^.info  valor; 
 A^.dir  d; 
 NO  A; 
Fim; 
 
 
Verificação de árvore vazia 
 
Funcao VAZIA (A: arvb): logico; 
Inicio 
 VAZIA  (A = 0); 
Fim; 
 
 
Retorno do item da raiz da árvore 
 
Funcao RAIZ (A: arvb): T; 
Inicio 
 RAIZ  A^.info; 
Fim; 
 
 
 
 
Retorno da subárvore esquerda 
 
Funcao ESQUERDA (A: arvb): arvb; 
Inicio 
 ESQUERDA  A^.esq; 
Fim; 
 
 
Retorno da subárvore direita 
 
Funcao DIREITA (A: arvb): arvb; 
Inicio 
 DIREITA  A^.dir; 
Fim; 
 
 
14.3 Percursos em Árvores Binárias 
 
 Percurso é um modo sistemático de percorrer cada nó de uma árvore exatamente um 
por vez; 
 
 Tipos de percursos: 
 
 Percursos em profundidade; 
 Percursos em largura. 
 
 
• Percursos em Profundidade 
 
 Em-ordem; 
 Pré-ordem; 
 Pós-ordem. 
 
• Percurso em Largura 
 
 Em-nível. 
 
 
Percursos em Profundidade 
 
 Em-ordem: percorre recursivamente a subárvore esquerda, volta a raiz da árvore e, 
por último percorre recursivamente a subárvore direita; 
 
 Pré-ordem: percorre a raiz da árvore e depois percorre recursivamente as 
subárvores esquerda e direita, respectivamente; 
 
 Pós-ordem: percorre recursivamente as subárvoes esquerda e direita, 
respectivamente, e por último, volta a raiz da árvore. 
 
 
 
 
 
 
 
Podemos compreender melhor esses percursos quando comparamos o funcionamento 
destes com as formas infixa, prefixa e posfixa de expressões aritméticas. 
 
 
 
 
 
 
 
 
 
 
 
 
Forma infixa da expressão  Aplica-se o percurso em-ordem 
 
 Exibir a subárvore esquerda; (a) 
 Exibir a raiz; (+) 
 Exibir a subárvore direita; (b) 
 
 
Forma prefixa da expressão  Aplica-se o percurso pre-ordem 
 
 Exibir a raiz; (+) 
 Exibir a subárvore esquerda; (a) 
 Exibir a subárvore direita; (b) 
 
 
Forma posfixa da expressão  Aplica-se o percurso pos-ordem 
 
 Exibir a subárvore esquerda; (a) 
 Exibir a subárvore direita; (b) 
 Exibir a raiz; (+) 
 
 
Com o uso de recursão, podemos generalizar esse raciocínio e desenvolver a forma 
posfixa da expressão abaixo, percorrendo, em pós-ordem, a subárvore esquerda (ab*), depois a 
subárvore direita (cd/) e, finalmente, a raiz (+). 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Expressão aritmética a*b + c/d 
representada por uma árvore binária 
+ 
* 
a b 
/ 
c d 
+ 
a b 
Expressão aritmética a + b 
representada por uma árvore 
binária 
Ao final, teremos a expressão: 
 
a b * c d / + 
14.4 Algoritmos dos 3 tipos de percurso em profundidade 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Retorno da subárvore esquerda 
 
Funcao ESQUERDA (A: arvb): arvb; 
Inicio 
 ESQUERDA  A^.esq; 
Fim; 
 
 
Retorno da subárvore direita 
 
Funcao DIREITA (A: arvb): arvb; 
Inicio 
 DIREITA  A^.dir; 
Fim; 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Procedimento EM_ORDEM (A: arvb); 
Inicio 
 EM_ORDEM (ESQUERDA (A) ); 
 exiba (RAIZ (A) ); 
 EM_ORDEM (DIREITA (A) ); 
Fim; 
Procedimento PRE_ORDEM (A: arvb); 
Inicio 
 exiba (RAIZ (A) ); 
 PRE_ORDEM (ESQUERDA (A) ); 
 PRE_ORDEM (DIREITA (A) ); 
Fim; 
Procedimento POS_ORDEM (A: arvb); 
Inicio 
 POS_ORDEM (ESQUERDA (A) ); 
 POS_ORDEM (DIREITA (A) ); 
 exiba (RAIZ (A) ); 
Fim; 
Percurso em Largura 
 
 Conhecido por percurso em-nível; 
 
 Percorre-se os nós de uma árvore por nível: 
 
• de cima para baixo; 
 
• da esquerda para a direita. 
 
 Exemplo: na expressão a*b + c/d, teremos: 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Na implementação do percurso em largura (em-nível), inicia-se uma fila possuindo só o nó 
da raiz da árvore. Em seguida, enquanto essa fila não ficar vazia, elimina-se dessa um nó, exibe-
se o seu conteúdo e armazena-se seus filhos de volta na mesma. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
+ * / a b c d 
+ 
* 
a b 
/ 
c d 
Procedimento EM_NIVEL (A: arvb); 
var 
 F: Fila; 
Inicio 
 CRIA_FILA (F); 
 ENFILEIRA (A, F); 
 Enquanto (nao VAZIA (F) ) faca 
 A  ELIMINA (F); 
 exiba (RAIZ (A) ); 
 se nao VAZIA (ESQUERDA (A) ) 
 entao ENFILEIRA (ESQUERDA (A), F ); 
 se nao VAZIA (DIREITA (A) ) 
 entao ENFILEIRA (DIREITA (A), F); 
 Fim Enquanto; 
Fim; 
14.5 Árvores de Busca Binária 
 
Considere A como uma árvore binária na qual sua raiz contenha o item r. 
 
Essa árvore A será uma Árvore de Busca Binária (ordenada), se e somente se: 
 
 Todo elemento armazenado na subárvore esquerda de A seja menor ou igual a r; 
 Todo elemento armazenado na subárvore direita de A seja maior que r; 
 Toda subárvore de A seja também uma árvore de busca binária. 
 
Assim, os elementos de uma árvore de busca binária A estarão ordenados de acordo com 
a propriedade de uma busca binária, ou seja, para todo elemento x Є A, quando um elemento y 
está armazenado à esquerda de x, então y < x. Já quando y está armazenado à direita de x, 
então y > x. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Uma observação importante acerca da propriedade de busca binária faz com que 
cheguemos a conclusão de que ao projetar uma árvore de busca binária obteremos uma 
sequência ordenada de todos os seus elementos. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Ordenada 
c 
b 
a 
f 
e g 
d 
Não Ordenada 
d 
a 
b c 
f 
e g 
4 6 9 
8 
5 
0 1 2 3 4 5 6 7 8 9 
1 
0 2 
3 7 
14.6 Implementação de Árvores de Busca Binária 
 
 O TAD para implementar árvores de busca binária é idêntico ao de árvores binárias; 
 
 Tipo 
 arvbb = ^bloco_no; 
 bloco_no = registro 
 esq: arvbb; 
 info: T; 
 dir: arvbb; 
 fim; 
 
 Esse fato denota que as propriedades da busca binária não são exclusivas dessa estrutura. 
Portanto, suas características devem ser desenvolvidas por meio das operações que farão 
uso dela. 
 
 
Criação e teste de árvore vazia 
 
Procedimento CRIA (var A: arvbb); 
Inicio 
 A  0; 
Fim; 
 
Funcao VAZIA (A: arvbb): logico; 
Inicio 
 VAZIA  (A = 0); 
Fim; 
 
 
Acesso em árvore de busca binária 
 
Funcao RAIZ (A: arvbb): T; 
Inicio 
 se (A = 0) 
 entao exiba (“Árvore binária vazia!”); 
 fim se; 
 RAIZ  A^.info; 
Fim; 
 
Funcao ESQUERDA (A: arvbb): arvbb; 
Inicio 
 se (A = 0) 
 entao exiba (“Árvore binária vazia!”); 
 fim se; 
 ESQUERDA  A^.esq; 
Fim; 
 
Funcao DIREITA (A: arvbb): arvbb; 
Inicio 
 se (A = 0) 
 entao exiba (“Árvore binária vazia!”); 
 fim se; 
 ESQUERDA  A^.dir; 
Fim; 
Inserção em árvore de busca binária 
 
Funcao FOLHA (valor: T); 
var 
 A: arvbb; 
Inicio 
 ALOCA (A); 
 A^.esq  0; 
 A^.info  valor; 
 A^.dir  0; 
 FOLHA  A; 
Fim; 
 
 
Procedimento INSERE (valor: T; var A: arvbb); 
Inicio 
 se ( VAZIA (A) ) 
 entao A  FOLHA (valor) 
 senao se ( valor <= RAIZ (A) ) 
 entao INSERE (valor, A^.esq) 
 senao INSERE (valor, A^.dir); 
 fim se; 
 fim se; 
Fim; 
 
 
Remoção em árvore de busca binária 
 
Funcao SUBSTITUI (var valor: T; var A: arvbb): arvbb; 
Inicio 
 se (A^.dir = 0) 
 entao 
 SUBSTITUI  A; 
 valor  A^.info; 
 A  A^.esq; 
 senao 
 SUBSTITUI  SUBSTITUI (valor, A^.dir); 
 fim se; 
Fim; 
 
 
Procedimento REMOVE (valor: T; var A: arvbb); 
var 
 n: arvbb; 
Inicio 
 se ( VAZIA (A) ) 
 entao Sair; 
 se ( valor = RAIZ (A) ) 
 entao 
 n  A; 
 se ( ESQUERDA (A) = 0 ) 
 entao A  A^.dir 
 senao se ( DIREITA (A) = 0 ) 
 entao A  A^.esq 
 senao n  SUBSTITUI(A^.info, A^.esq); 
 fim se; 
 fim se; 
 DESALOCA (n); 
 senao 
 se ( valor <= RAIZ (A) 
 entao REMOVE (valor, A^.esq) 
 senao REMOVE (valor, A^.dir); 
 fim se; 
 fim se; 
Fim; 
 
 
Busca em árvore de busca binária 
 
Funcao BUSCA (valor: T; A: arvbb): logico; 
Inicio 
 se ( VAZIA (A) ) 
 entao BUSCA  falso 
 senao se ( valor = RAIZ (A) ) 
 entao BUSCA  verdadeiro 
 senao se ( valor < RAIZ (A) ) 
 entao BUSCA  BUSCA (valor, ESQUERDA (A) ) 
 senao BUSCA  BUSCA (valor, DIREITA (A) ); 
 fim se; 
 fim se; 
 fim se; 
Fim; 
 
 
Algumas aplicações de árvores 
 
 Consultas de dados; 
 Avaliação de expressões aritméticas; 
 Geração de índices remissivos; 
 Manipulação de arquivos indexados; 
 Implementação de filas de prioridades. 
 
 
 
 
 
 
 
 
 
 
 
 
 
BIBLIOGRAFIA* 
 
 
 
FORBELLONE, A. L.; EBERSPACHER, H. F. Lógica de programação: a construção de 
algoritmos e estruturas de dados. São Paulo: Prentice Hall, 2005. 
 
 
GUIMARAES, A. e LAGES, N. Algoritmos e estruturas de dados. Rio de Janeiro: LTC, 1994. 
 
 
MANZANO, J. A. Lógica estruturada para programação de computadores. São Paulo: Érica, 
2001. 
 
 
PEREIRA, Silvio do L. Estruturas de dados fundamentais: conceitos e aplicações. 12 ed. São 
Paulo: Érica, 2008. 
 
 
 
* Esta apostila foi elaborada com base nas obras relacionadas neste item.

Mais conteúdos dessa disciplina