Conceitos_tecnicos_ED

Propaganda
Estrutura de Dados
Sumário
1.
Consideraçöes Gerais ............................................................................................................................................... 3
2.
Tipos de Dados .......................................................................................................................................................... 3
2.1
3.
Primitivos, Estáticos e Dinâmicos ...................................................................................................................... 3
Variáveis.................................................................................................................................................................... 4
3.1
Variáveis Compostas Homogêneas .................................................................................................................... 4
3.2
Variáveis Compostas Heterogêneas ................................................................................................................... 4
3.2.1
Registros ..................................................................................................................................................... 4
4.
Tipo Apontador (Ponteiro) ...................................................................................................................................... 5
4.1
Características Gerais........................................................................................................................................ 5
4.2
Ponteiros no Pascal............................................................................................................................................ 5
4.3
Rotinas para Alocação de Memória: ................................................................................................................. 6
4.4
Atribuição de Valores ......................................................................................................................................... 7
4.4.1
Exercícios: .................................................................................................................................................. 8
5.
Listas Encadeadas .................................................................................................................................................... 8
5.1
Conceito ............................................................................................................................................................. 8
5.2
Listas Simplesmente Encadeadas ....................................................................................................................... 9
5.2.1
Definiçäo .................................................................................................................................................... 9
5.2.2
Operaçöes Básicas (Inclusäo, Pesquisa, Alteraçäo e Exclusäo) ............................................................... 10
5.2.3
Criando Listas na Memória ...................................................................................................................... 11
5.2.4
Exercícios: ................................................................................................................................................ 14
5.3
Listas Duplamente Encadeadas ....................................................................................................................... 16
5.3.1
Aplicaçäo .................................................................................................................................................. 16
5.3.2
Rotinas ...................................................................................................................................................... 16
5.3.3
Exercícios: ................................................................................................................................................ 18
5.4
Filas.................................................................................................................................................................. 19
5.4.1
Definiçäo .................................................................................................................................................. 19
5.4.2
Aplicaçäo .................................................................................................................................................. 19
5.4.3
Operaçöes Básicas (Inclusäo e Exclusäo) ................................................................................................. 20
5.4.4
Exercícios .................................................................................................. Error! Bookmark not defined.
5.5
Pilhas................................................................................................................................................................ 20
5.5.1
Definiçäo .................................................................................................................................................. 20
5.5.2
Aplicaçäo .................................................................................................................................................. 20
5.5.3
Operaçöes Básicas (Inclusäo e Exclusäo) ................................................................................................. 20
5.5.4
Exercícios .................................................................................................. Error! Bookmark not defined.
6.
7.
Deck ......................................................................................................................................................................... 20
6.1
Definiçäo .......................................................................................................................................................... 20
6.2
Aplicaçäo .......................................................................................................................................................... 20
6.3
Operaçöes Básicas (Inclusäo e Exclusäo) ........................................................................................................ 20
6.4
Exercícios ............................................................................................................ Error! Bookmark not defined.
Hash ......................................................................................................................................................................... 20
1
8.
9.
7.1
Definiçäo .......................................................................................................................................................... 20
7.2
Aplicaçäo .......................................................................................................................................................... 21
7.3
Operaçöes Básicas (Criaçäo, Inclusäo, Pesquisa, Alteraçäo e Exclusäo) ....................................................... 21
7.4
Exercícios ............................................................................................................ Error! Bookmark not defined.
Ávores ...................................................................................................................................................................... 21
8.1
Definiçäo .......................................................................................................................................................... 21
8.2
Árvores Binárias............................................................................................................................................... 22
8.3
Aplicaçäo .......................................................................................................................................................... 22
8.4
Operaçöes Básicas (Inclusäo, Pesquisa, Alteraçäo, Exclusäo, transformaçäo e Caminhamentos) ................ 23
Classificaçäo de Dados ................................................................................................ Error! Bookmark not defined.
9.1
Definiçäo ............................................................................................................. Error! Bookmark not defined.
9.2
Ambiente de Classificaçäo .................................................................................. Error! Bookmark not defined.
9.3
Métodos de Classificaçäo .................................................................................... Error! Bookmark not defined.
9.3.1
Por Inserçäo ............................................................................................... Error! Bookmark not defined.
9.3.2
Por Troca ................................................................................................... Error! Bookmark not defined.
9.3.3
Por Seleçäo ................................................................................................ Error! Bookmark not defined.
9.3.4
Por Intercalaçäo ......................................................................................... Error! Bookmark not defined.
9.3.5
Por Distribuiçäo ......................................................................................... Error! Bookmark not defined.
2
1. Consideraçöes Gerais
A automatizaçäo de tarefas é um aspecto marcante da sociedade moderna e na ciência da
computaçäo houve um processo de desenvolvimento simultâneo e interativo de máquinas
(hardware) e dos elementos que gerenciam a execuçäo automática (software) de uma tarefa.
Nesta grande evoluçäo do mundo computacional, um fator de relevante importância é a forma
de armazenar as informaçöes, já que, informática é a ciência da informaçäo. Entäo de nada
adiantaria o grande desenvolvimento do hardware e do software, se a forma de armazenamento e
tratamento da informaçäo näo acompanhasse esse desenvolvimento. Por isso a importância das
estruturas de dados, que nada mais säo, que formas otimizadas de armazenamento e tratamento das
informaçöes eletronicamente.
As estruturas de dados, na sua maioria dos casos, foram espelhadas em formas naturais de
armazenamento do nosso dia a dia, ou seja, nada mais säo que a transformaçäo de uma forma de
armazenamento já conhecida e utilizada no nosso munda para o mundo computacional. Por isso,
cada tipo de estrutura de dados possue vantagens e desvantagens e cada uma delas tem sua área de
atuaçäo (massa de dados) ótima.
Este curso foi elaborado com o objetivo de introduzir o aluno, que já possua um conhecimento
da linguagen Pascal, no mundo das estruturas de dados, bem como mostrar a teoria (conceitos) e a
prática (implementaçäo) das estruturas de dados mais utilizadas no dia a dia do profissional de
informática.
O aluno até aqui, somente teve contato com estruturas de dados estáticas (vetores e matrizes),
e deve estar familizarizado com suas facilidades e dificuldades de uso. Agora novas estruturas de
dados seräo apresendas, sendo que, todas elas seräo estruturas de dados dinâmicas, ou seja, crescem
e diminuem de acordo com a necessidade, veremos que, para isso, seräo necessárias várias rotinas
que controlam esta dinamicidade das estruturas.
2. Tipos de Dados
A matemática classifica suas variáveis de acordo com as características, distinguindo
constantes, equações, conjuntos e funções. Em computação precisamos identificar os tipos de dados
que o computador, a linguagem de programação ou mesmo um algoritmo serão capazes de entender.
De uma forma geral diferenciamos os tipos de dados pelo conjunto de valores que podem
assumir e pelo conjunto de operações que podemos efetuar com eles.
Por exemplo, poderíamos definir que fruta é um tipo de dado que pode assumir apenas os
valores maçã, pêra, banana e abacaxi, sobre os quais podemos efetuar as operações de comparar,
comprar, comer e servir.
2.1 Primitivos, Estáticos e Dinâmicos
Podemos separar os tipos de dados em três grupos: primitivos, estáticos e dinâmicos. Os
tipos primitivos são aqueles a partir dos quais podemos definir os demais tipos, não importando
como são implementados e manipulados.
São considerados tipos primitivos números inteiros, números reais, caracteres, lógicos e
ponteiros. Esses tipos de dados são os mais frequentes nas linguagens de programação.
Cada um desses tipos primitivos tem um conjunto de valores e operações restrito:
 Inteiro - Representa uma quantidade contável de objetos. Operações: Soma, Subtração,
Multiplicação, Divisão, Resto. Exemplos: -45; 2; 1037
 Real - Representa um valor que pode ser fracionado. Operações: Soma, Subtração,
Multiplicação. Exemplos: -4,78; 1,25; 2,333...
3
 Lógico - Representa dois estados. Operações: E, NÃO, OU. Exemplos: [Verdadeiro,
Falso];[1,0]
 Caracter - Representa uma sequência de dígitos, letras e sinais. Operações: Igualdade,
Diferença, Concatenação. Exemplos: “A”, “X”, “1”, “+”
 Ponteiro - Representa o enderenço de um dado na memória. Operações: Igualdade,
Diferença, Soma, Subtração, Multiplicação, Divisão.
A definição do conceito de tipos estáticos e dinâmicos pode ser feita de forma física ou
lógica. Utilizaremos a forma lógica que corresponde ao modo como definimos todas as estruturas de
dados.
Definimos tipos estáticos de dados como aqueles que têm a estrutura completamente
definida antes de começarmos a efetuar operações. O exemplo que sobressai é o de que, definido
um tipo estático de dado, ele não poderá conter mais elementos do que o previsto inicialmente. Não
só a limitação de elementos torna um tipo de dados estático, como também seus sucessores e
antecessores não se modificam (observe que o conteúdo pode ser modificado, mas não as suas
posições na memória). Dessa forma a estrutura permanece estática. Um exemplo de estrutura
estática é o vetor ( “Array”), que é um agregado homogêneo de dados.
Em contrapartida, os tipos dinâmicos de dados são aqueles que sofrem alteração estrutural
quando estão sendo manipulados, à medida que ocorrem inserções e retiradas de elementos. Esse
tipo de dado não tem tamanho predefinido, só ficando limitado à memória do computador em que se
está trabalhando. Do ponto de vista lógico, um tipo dinâmico não tem limitações, porém, como os
algoritmos de manipulação dessas estruturas são implentados em computadores, neste texto
trataremos as suas limitações físicas.
3. Variáveis
3.1 Variáveis Compostas Homogêneas
Correspondem a posições de memória, indentificadas por
individualizadas por índices e cujo conteúdo é de mesmo tipo.
um
mesmo
nome,
O conjunto de 10 notas dos alunos de uma disciplina pode constituir uma variável
composta. A este conjunto associa-se o identificador Nota que passará a identificar não uma
única posição de memória, mas 10.
A referência ao conteúdo do n-ésimo elemento do conjunto será indicada pela notação
NOTA[n], onde n é um número inteiro ou uma variável numérica contendo um valor inteiro.
3.2 Variáveis Compostas Heterogêneas
3.2.1 Registros
São conjuntos de dados logicamente relacionados, mas de tipos diferentes (numérico,
literal, lógico).
4
4. Tipo Apontador (Ponteiro)
Um das características mais marcantes do pascal é permitir a criaçäo e destruiçäo de variáveis
durante a execuçäo do programa. O uso dessas variáveis possibilita a implementaçäo das estruturas
de dados dinâmicas. Essas variáveis criadas e destruídas durante a execuçäo do programa säo
chamadas variáveis dinâmicas. Uma variável dinâmica näo é declarada na parte de declaraçäo de
variáveis porque esta ainda näo existe antes do seu tempo de execuçäo, ela näo possui sequer um
nome, ficando a cargo dos ponteiros desempenhar esta funçäo de “nome”. Uma variável dinâmica é
sempre referenciada indiretamente por um apontador, ou seja, para cada variável dinâmica criada
deve existir um apontador, que literalmente aponta para ela, permitindo a sua manipulaçäo.
4.1 Características Gerais
Os apontadores säo declarados como as demais variáveis, seguindo a sintaxe da linguagem de
programaçäo utilizada. Eles säo variáveis que armazenam o endereço de memórias de outras
variáveis, funcionanddo assim, como meio de refrenciar uma variável dinâmica, permitindo o
acesso a essa variável. Outra característica dos apontadores é que na sua declaraçäo deve ser
indicada qual o tipo de variável este irá armazenar o endereço.
A principal funçäo dos ponteiros é permitir a criaçäo e a manipulaçäo das variáveis dinâmicas,
as quais iräo compôr as estruturas de dados dinâmicas.
4.2 Ponteiros no Pascal
 Declaraçäo : a sintaxe de declaraçäo de um tipo ponteiro é o seguinte.
type identificador = ^tipo; {onde o símbolo ^ indica que o identificador é um ponteiro}
,isso indica que teremos um ponteiro com o nome de identificacor com a capacidade de
armazenar o endereço de memória de uma variável desse tipo.
Como os ponteiros säo utilizados para implementar as estruturas de dados dinâmicas, o mais
comum é que seja criado um tipo do ponteiro desejado (type) e depois declaramos (var) as variáveis
ponteiros deste tipo.
Exemplo :
type
Nome : string[35];
PontNome : ^Nome;
var
nome1,nome2,nome3 : PontNome;
 Inicializaçäo : como os ponteiros armazenam endereços de memória, assim que eles säo
declarados o seu conteúdo é um valor desconhecido (como as demais variáveis), ou seja, näo
podemos prever para qual área de memória este esta apontando, por isso, a linguagem pascal
permite que um ponteiro seja inicializado, da seguinte forma :
identificador := nil; {nil é um valor constantee pode ser armazenado em uma variável do
tipo apontador para indicar que a variável näo contém endereço de memória de nenhuma variável
dinâmica }
 Criaçäo de uma variável dinâmica : para criaçäo de uma variável dinämica é necessário
que exista uma variável do tipo apontador para o tipo da variável que se desaja criar, e entäo utilizáse o procedimento new, cuja sintaxe é a seguinte :
new(identificador); {onde, identificador deve ser uma variável do tipo ponteiro para o tipo
de variável a ser criada}
5
Obs: quando uma variável dinâmica é criada através do procedimento NEW, um espaço de
memória do tamanho da variável criada é alocado na memória heap e este espaço ficará alocado até
ser liberado.
 Destruiçäo de uma variável dinâmica : para que o espaço de memória heap seja liberado é
necessário que a variável dinâmica seja destruida, isso pode ser feito através do procedimento
dispose, utilizando a seguinte sintaxe;
dispose(identificador);
 Referencia a uma variável dinâmica : quando uma variável dinâmica é criada através de
uma ponteiro, este pode ser utilizado para referenciá-la, permitindo a manipulaçäo (leitura,
atribuiçäo, escrita, etc) desta variável como outra variável qualquer, para isso devemos utilizar o
símbolo ^ após o nome da variável do tipo ponteiro:
identificador^
*
Marcação e liberação de uma área no heap - mark(ponteiro) e release(ponteiro)
Ex:
program ManipulacaoVariaveisDinamicas;
type
nome = string[30];
ponteiro = ^nome;
var
p1, p2 : ponteiro;
begin
new(p1);
new(p2);
readln(p1^);
p2^ := 'José Maria';
p1^:= p1^ + ' ' + p2^;
writeln(p1^);
end.
4.3 Rotinas para Alocação de Memória:
Rotina : NEW()
Função
: Aloca espaço na memória para uma informação, com o tamanho definido pelo tipo
da variável pointer.
Sintaxe
: NEW(Variável Pointer)
Exemplo:
PROGRAM ALOCA;
VAR
Ap_WORD : ^WORD;
BEGIN
NEW(Ap_WORD);
END.
6
Obs.: No Exemplo acima, após o comando NEW, será alocado na memória HEAP, dois BYTE’s
(uma WORD), sendo que poderemos representar a memória como é mostrado abaixo:
Ap_WORD
?
4000:3D07
Rotina : DISPOSE()
Função
: Libera espaço na memória, o número de BYTE’s liberados dependerá do tipo da
variável pointer utilizada. Uma vez liberada memória, o valor lá armazenado estará perdido.
Sintaxe
: DIPOSE(Variável Pointer)
Exemplo:
PROGRAM LIBERA;
VAR
Ap_WORD : ^WORD;
BEGIN
NEW(Ap_WORD);
DISPOSE (Ap_WORD);
END.
Obs.: No Exemplo anterior, após o comando DISPOSE, serão liberado dois (2) BYTE’s devido ao
fato de uma WORD ocupar este espaço de memória.
4.4 Atribuição de Valores
A Sintaxe para atribuição de valores é a mesma utilizada em variáveis simples, a única
diferença é que devemos colocar após o Nome da variável apontadora o símbolo “ ^ “
Exemplo:
PROGRAM ATRIBUI;
VAR
Ap_Número : ^INTEGER;
BEGIN
NEW(Ap_Número);
Ap_Número ^:= 10;
DISPOSE (Ap_Número);
END.
No Exemplo acima ocorre o seguinte:
a) Criamos uma variável que irá apontar ara dois (2) BYTE’s (um INTEGER) na memória.
b) Alocamos espaço suficiente para armazenar um valor do tipo INTEGER e fazemos com que a
variável “Ap_Número” aponte para a posição de memória alocada.
Ap_Numero
?
3000:004A
c) Colocamos na posição de memória apontada por “Ap_Número” o valor dez (10).
7
d) Liberamos os dois (2) BYTE’s apontados por “Ap_Número”. A informação não mais poderá ser
acessada.
4.4.1 Exercícios:
1. Crie um vetor com n elementos, sendo que cada posição do vetor corresponderá a um pointer para
um valor do tipo REAL. Faça a leitura de n valores e armazene-os na memória.
2. Crie uma variável pointer do tipo ARRAY[1..20] OF CHAR, faça a leitura de 20 caracteres e os
armazene na memória.
3. Percorra o ARRAY definido acima e escreva quantos caracteres “A”, “E”, “I”, “O” e “U” existem
no mesmo.
4. Defina um tipo (TYPE) de dado que represente um pointer para um RECORD com os seguintes
campos: Nome e Idade.
5. Usando a definição de tipo anterior, crie uma sub-Rotina para ler as informações de uma única
pessoa.
6. Defina uma variável como sendo um ARRAY com 10 posições, sendo que cada posição
corresponderá aos dados de uma pessoa, conforme definido no item 5.
7. Use a sub-Rotina definida no item 5, para ler o vetor definido no exercício acima.
8. Defina uma variável pointer do tipo matriz N x N, sendo que cada posição desta matriz também
será um pointer mas para um valor do tipo WORD.
9. Faça a leitura da matriz definida no item acima.
10. Percorra a matriz acima e escreva os valores existente na diagonal principal.
11. Faça as definições necessárias para obter a seguinte representação de pointer.
PAÍS
BR
ESTADO
CIDADE
CLIENTE
SC
FLO
CRI
ARA
PR
JAG
BNO
TUB
NOME ENDEREC IDADE
O
12. Preencha a estrutura acima com as informações de 12 pessoas.
13. Liste no vídeo o Nome e idade das pessoas que tem idade ímpar.
5. Listas Encadeadas
5.1 Conceito
Esta classe de estruturas de dados foi inspirada numa forma de armazenamento bastante
comum na nossa vida cotidiana, pois, desde eras bastantes remotas, o homem utiliza-se da idéia de
listar coisas com o objetivo de melhor organizá-las.
Baseado nesse conceito bastante simples (listagem) a estrutura de dados lista foi concebida,
onde, cada elemento da lista armazena uma informaçäo útil e uma, ou mais, referencia(s) para outro
elemento (limitaçäo do mundo computacional) e assim por diante, desta forma, com o auxílio dos
ponteiros, pode-se acrescentar ou retirar elementos conforme a necessidade.
Listas encadeadas geralmente säo utilizadas para criar vetores de extensäo de memória
desconhecida, pela sua característica dinâmica, permitindo que o vetor (lista) tenha sempre o
tamanho necessário.
8
5.2 Listas Simplesmente Encadeadas
5.2.1 Definiçäo
Este tipo de lista é o mais simples e segue as seguintes regras:
a. deve exstir um ponteiro que aponte para o primeiro elemento da lista (início da lista);
b. cada elemento, ou nó, da lista aponta para o próximo sucessivamente (daí o nome listas
encadeadas)
c. o último elemento deve apontar para NIL, indicando o final da lista.
Agora podemos definir a estrtura básica de um nó da lista
Representaçäo gráfica :
NÓ
Info
prox
Declaraçäo :
type
apontador
InfoType
= ^no;
= record
campos do registro;
end;
no
= record
info : InfoType;
prox : apontador;
end;
,onde, nó é um registro com dois campos : info e prox, info é um tipo registro do tipo infotype
contendo as informaçöes (variáveis) úteis e prox é um ponteiro capaz de armazenar o endereço de
memória de um registro do tipo nó (elemento da lista).
Graficamente a representação de uma lista simplesmente encadeada seria a seguinte :
INICIO
NÓ
NÓ
Info
prox
Info
prox
,onde, INICIO é um ponteiro que guarda o endereço de memória do primeiro elemento da
lista.
5.2.2 Aplicaçäo
As listas simplesmente encadeadas säo utilizadas quando há necessidade de criar vetores com
tamanho variável (dinâmico), sua limitaçäo, é somente permitir, o caminhamento unideirecional na
lista, pois, como as referências iniciam no primeiro elemento da lista e seguem unidirecionalmente
até o último elemento, näo é possível regressar no caminhamento através da lista.
9
Mesmo com esta limitaçäo, as listas simplesmente encadadas säo largamente utilizadas, pela
sua simplicidade de implementaçäo fornecendo um bom índice entre custo/benefício, na gerencia,
em memória, de conjuntos de dados näo muito extensos.
5.2.3 Operaçöes Básicas (Inclusäo, Pesquisa, Alteraçäo e Exclusäo)
Como toda estrutura de aramazenamento de dados, as listas simplesmente encadeadas deve
suportar as operaçöes de cadastro das informaçöes. Uma particularidade das listas é o fato de
apresentarem uma pequena variçäo no código de inclusäo e exclusäo, de acordo com o local onde o
novo elemento deverá ser inserido (no início, no meio ou no fim), e ainda assim, está variaçäo pode
ocorrer de acordo com os mecanismo de controle utilizados na gerncia da lista, tais como, utilizaçäo
de um único ponteiro apontando para o ínicio da lista, ou dois ponteiros, um para o início e outro
para o final.
As operaçöes de cadastro sobre listas devem tomar o cuidado especial de análisar se o valor
do ponteiro para o início é diferente de NIL, pois, se for igual a lista está vazia e certamente as
rotinas deveräo efetuar procedimentos especiais.
INCLUSÄO - Levando em consideraçäo o uso de um único ponteiro para o início
procedure InsereLista (var inicio : ponteiro ; info : InfoType);
No início
No fim
No meio
INCLUSÄO - Levando em consideraçäo o uso de dois ponteiros (início e fim).
procedure InsereLista (var inicio, fim : ponteiro; info : InfoType);
No início
No fim
No meio (ordenada)
PESQUISA - normalmente, usa-se uma funçäo que, se encontrar, retornará o endereço do nó,
caso contrário, retornará o valor NIL.
function PesquisaLista (inicio : ponteiro ; info : InfoType) : ponteiro;
ALTERAÇÄO - utilizando a funcäo de pesquisa, obtem-se o endereço do nó a ser alterado e
de posse deste endereço, altera-se os dados deste nó.
procedure AlteraLista (inicio : ponteiro ; info : InfoType);
EXCLUSÄO - usa-se um procedimento recebendo o início da lista e os dados do nó ser
excluído, entäo, através do campo identificado (chave) efetua-se uma pesquisa e localiza-se o nó
anterior ao nó a ser excluído, e entäo devemos liberar o espaço alocado para o nó excluído e fazer o
seu anterio apontar para o posterior.
procedure ExcluiLista (inicio : ponteiro ; info : InfoType);
No início
10
No meio
No fim
5.2.4 Criando Listas na Memória
Para criarmos uma lista, para colocarmos na memória uma seqüência de valores sendo que
os mesmos estejam ligados entre si por um endereço, ou pointer, vamos utilizar a estrutura
RECORD. Esta RECORD será usada basicamente para definir dois tipos de campos: O primeiro
tipo corresponde aos campos de informações, aquelas quereremos armazenar na memória, e o
segundo tipo corresponde ao campo apontador (pointer), cuja Função será armazenar o endereço da
próxima informação existente na memória.
Exemplo: Definir um tipo de dado que permita armazenar na memória as informações de um
cliente: Nome, Idade e Sexo.
PROGRAM TÁ_FALTANDO_ALGO;
TYPE
REGISTRO = RECORD
Nome : STRING;
Idade : BYTE;
Sexo : CHAR;
Ender : <tipo apontador>;
END;
BEGIN
<comandos>;
END.
O programa acima não está completo quanto a definição do RECORD, pois um campo chamado
“Ender” que não tem o seu tipo definido. Mas então, qual será este tipo? O campo “Ender” deverá
ser usado para armazenar o endereço de um a informação na memória que seja do tipo “Registro”,
pois é ela que contém a definição dos dados dos clientes. Desta forma, o campo “Ender” deverá ser
um tipo apontador de registros. Só que temos um pequeno problema de Sintaxe. Caso façamos a
seguinte definição do tipo “Registro”:
PROGRAM AINDA_TÁ_ERRADO;
TYPE
REGISTRO = RECORD
Nome : STRING;
Idade : BYTE;
Sexo : CHAR;
Ender : ^Registro;
END;
BEGIN
<comandos>;
END.
O PASCAL irá acusar um erro de compilação, pois ele precisa que um apontador de estruturas
complexas como RECORD’s, tenham que ter definidos um tipo (TYPE) específico para ele, por
isso eu necessito definir antes, um tipo que seja um apontador de “Registro. Abaixo é mostrado
como isto será feito:
11
PROGRAM OK;
TYPE
Ap_Registro = ^REGISTRO;
REGISTRO = RECORD
Nome : STRING;
Idade : BYTE;
Sexo : CHAR;
Ender : Ap_Registro;
END;
BEGIN
<comandos>;
END.
Pode parecer estranho, definir o tipo “Ap_Registro” como sendo um apontador de registro sendo
que o tipo “Registro” ainda não tinha sido definido. Não se assuste, é assim mesmo. Com o tempo
você se acostuma.
No futuro, quando já tivermos a lista definida criada, a mesma poderá ter a seguinte representação:
Nome
Idade
Sexo
Ender
Nome
Idade
Sexo
Ender
Início
Nome
Idade
Sexo
Ender
Obs.: Um apontador não pode ficar sem um valor, por isso o apontador do último elemento da lista
deverá receber um valor especial do PASCAL, que indica que aquele apontador não aponta para
ninguém. Este valor é uma variável pré-definida do PASCAL chamada NIL.
Desta forma, a estrutura acima com o uso da variável NIL, terá a seguinte representação:
Nome
Idade
Sexo
Ender
Nome
Idade
Sexo
Ender
Início
Nome
Idade
Sexo
Ender
Obs.: O termo lista simplesmente encadeada significa que a lista possui somente um apontador para
apontar as informações na memória.
Exemplo1: Faça um PROGRAMA que armazene o Nome, idade, e sexo de uma pessoa em uma
estrutura simplesmente encadeada na memória.
12
PROGRAM LISTA_ENCADEADA;
USES CRT;
TYPE
Ap_Nodo = ^Nodo
Nodo = RECORD
Nome : STRING;
Idade : BYTE;
Sexo : CHAR;
Prox : Ap_Nodo;
END;
VAR
Raiz : Ap_Nodo;
BEGIN
NEW(RAIZ)
WRITE (‘Digite o Nome : ‘);
READLN (RAIZ^.Nome);
WRITE (‘Digite o Idade : ‘);
READLN (RAIZ^.Idade);
WRITE (‘Digite o Sexo : ‘);
READLN (RAIZ^.Sexo);
RAIZ^.Prox := NIL;
END.
Exemplo 2: Aproveitando a lista criada no Exemplo anterior, crie uma sub-Rotina que recebendo
como parâmetro as informações de uma pessoa, acrescente esta pessoa no início da lista.
PROCEDURE Inclui_Inicio_da_Lista (Var Raiz : Ap_Nodo; Reg: Nodo);
VAR
Novo_Nodo : Ap_Nodo;
BEGIN
NEW ( Novo_Nodo);
Novo_Nodo^:= Reg;
Novo_Nodo^.Prox := Raiz;
Raiz := Novo_Nodo;
END.
Exemplo 3: Aproveitando a lista criada no Exemplo anterior, crie uma sub-Rotina que recebendo
como parâmetro as informações de uma pessoa, acrescente esta pessoa na lista, de forma que a
mesma seja a segunda da lista.
PROCEDURE Segunda_Posição_da_Lista (Var Raiz : Ap_Nodo; Reg:
Nodo);
VAR
Novo_Nodo : Ap_Nodo;
BEGIN
NEW ( Novo_Nodo);
Novo_Nodo^:= Reg;
Novo_Nodo^.Prox := Raiz^.Prox;
Raiz^.Prox := Novo_Nodo;
END.
13
Exemplo 4: Faça uma sub-Rotina genérica que recebendo como parâmetro as informações de uma
pessoa, acrescente a mesma no final da lista.
PROCEDURE Inclui_Final_da_Lista (Var Raiz : Ap_Nodo; Reg: Nodo);
VAR
Novo_Nodo, Atual : Ap_Nodo;
BEGIN
NEW ( Novo_Nodo);
Novo_Nodo^:= Reg;
Novo_Nodo^.Prox := NIL;
Atual := Raiz;
WHILE Atual^.Prox <> NIL DO
Atual := Atual^.Prox;
Atual^.Prox := Novo_Nodo;
END.
Exemplo 5 : Faça uma sub-Rotina genérica que recebendo como parâmetro as informações de uma
pessoa, acrescente a mesma em uma lista. No Inicio, considere a lista com o valor NIL. As pessoas
serão incluídas sempre no final da lista.
PROCEDURE Inclui_Final_da_Lista (Var Raiz : Ap_Nodo; Reg: Nodo);
VAR
Novo_Nodo, Atual : Ap_Nodo;
BEGIN
NEW ( Novo_Nodo);
Novo_Nodo^:= Reg
Novo_Nodo^.Prox := NIL;
IF RAIZ = NIL THEN
Raiz := Novo_Nodo
ELSE
BEGIN
Atual := Raiz;
WHILE Atual^.Prox <> NIL DO
Atual := Atual^.Prox;
Atual^.Prox := Novo_Nodo;
END;
END.
5.2.5 Exercícios:
1. Faça uma sub-Rotina que conte quantos elementos existem em uma lista simplesmente
encadeada.
2. Faça uma sub-Rotina que verifique se uma determina pessoa existe na lista. A consulta pode ser
feita pelo Nome da pessoa. Use a lista definida nos exemplos anteriores.
3. Faça uma sub-Rotina que elimine o primeiro elemento da lista se o mesmo existir.
4. Faça uma sub-Rotina que elimine o segundo elemento da lista se o mesmo existir.
5. Faça uma sub-Rotina que elimine o ultimo elemento da lista se o mesmo existir.
14
6. Faça uma sub-Rotina genérica que elimine um determinado elemento de uma lista. Deverá ser
fornecido o número do elemento a ser eliminado. Pode ser que a lista não contenha este elemento.
Por Exemplo, a lista tem 10 nodos e deseja-se eliminar o nodo de número 11.
7. Faça uma sub-Rotina que permita a inclusão de um elemento na lista em uma determinada
posição. A sub-Rotina deverá receber a lista, a informação e a posição em que a nova informação
será incluída. Caso a posição seja maior que o número de elementos existentes na lista, a mesma
deverá ser incluída no final. Considere a possibilidade da lista, no início estar vazia.
8. Faça uma sub-Rotina para ordenar uma lista de números inteiros em ordem crescente. Antes de
construir a Rotina, faça a definição do tipo da lista: RECORD e tipo apontador.
9. Faça a definição de um ou mais tipos que possam no futuro criar uma lista como a que é
mostrada abaixo:
Fornecedor
Nome
Prod
Prox
Nome
Prod
Prox
Nome
Prod
Prox
Nome
Quant
Seg
Nome Quant
Seg
Nome
Quant
Seg
Nome
Quant
Seg
Nome
Quant
Seg
Nome
Quant
Seg
10. Faça uma sub-Rotina genérica para incluir um novo produto na lista de produtos de um
fornecedor qualquer. Os parâmetros de entrada serão as informações do produto e a lista dos
produtos de cada fornecedor (Fornecedor^.Prod). A inclusão de novo produto se dará sempre no
final da lista de produtos.
11. Faça uma sub-Rotina genérica para incluir um novo fornecedor na lista de fornecedores. A
inclusão se dará sempre no final da lista.
Faça uma sub-Rotina genérica que inclua um produto para um determinado fornecedor. Os
parâmetros de entrada serão: A lista de fornecedores, as informações do produto e as informações
do fornecedor, que terá incluído no seu campo “Prod” este novo produto. A Rotina deverá antes de
mais nada percorrer a lista de fornecedores até achar o fornecedor cujo Nome combine com o Nome
passado como parâmetro. Só após é que será feito o processo de inclusão do novo produto. Caso o
fornecedor não exista na lista, o mesmo deverá antes de tudo ser incluído na lista de fornecedores,
para só então ter o produto incluído no seu corpo “Prod”. Use também as Rotinas criadas nos itens
10 e 11.
12. Faça uma agenda eletrônica que utilize os seguintes campos : código, nome, endereço, telefone e
uma observaçäo, que permita todas as operaçöes de cadastro (inclusäo, consulta, alteraçäo e
exclusäo). Esta agenda deverá utilizar listas simplesmente encadeadas, onde, as informaçöes,
deveräo ser carregadas e salvas em arquivos, da seguinte maneira, quando o programa agenda for
carregado, este deverá carregar o arquivo em disco para uma lista em memória, e quando o
programa for encerrado, a lista deverá ser descarregada no arquivo em disco.
15
5.3 Listas Duplamente Encadeadas
Continuado o estudo de listas encadeadas, apresentamos agora uma nova estrutura conhecida
como lista duplamente encadeada. Este termo é dado pelo fato de existir dois endereços (pointers)
que apontam para nodos da mesma lista, isto é, um endereço aponta para o nodo imediatamente
posterior e outro endereço aponta para o nodo imediatamente anterior, isto com exceção do primeiro
e do último nodo, cujos endereços posterior e antecessor são respectivamente NIL.
Abaixo está uma figura representando este tipo de lista encadeada na memória
5.3.1 Aplicaçäo
Aplicaçäo das listas duplamente encadeadas é semelhante as listas simplesmente encadeadas,
mas aquela é mais apropriada, quando há a necessidade de caminhamento em ambos os sentidos,
isso faz com que, novas sub-rotinas sejam utilizadas nas listas duplamente encadeadas, tais como :
Anterior, Posterior.
5.3.2 Rotinas
Abaixo colocaremos exemplos de Rotinas para criação de listas duplamente encadeada na memória.
Exemplo1: Faça um algoritmo que armazene o Nome, idade e sexo de uma pessoa em uma
estrutura duplamente encadeada na memória.
Lista
PROGRAM LISTA_ENCADEADA;
USES CRT;
TYPE
Ap_Nodo = ^Nodo
Nodo = RECORD
Nome : STRING;
Idade : BYTE;
Sexo : CHAR;
Ant, Prox : Ap_Nodo;
END;
VAR
Raiz : Ap_Nodo;
BEGIN
NEW(RAIZ)
WRITE (‘Digite o Nome : ‘);
READLN (RAIZ^.Nome);
WRITE (‘Digite o Idade : ‘);
READLN (RAIZ^.Idade);
WRITE (‘Digite o Sexo : ‘);
READLN (RAIZ^.Sexo);
RAIZ^.Ant := NIL;
16
RAIZ^.Prox := NIL;
END.
Exemplo 2: Aproveitando a lista criada no Exemplo anterior, crie uma sub-Rotina que recebendo
como parâmetro as informações de uma pessoa, acrescente esta pessoa no início da lista.
PROCEDURE Inclui_Inicio_da_Lista (Var Raiz : Ap_Nodo; Reg: Nodo);
VAR
Novo_Nodo : Ap_Nodo;
BEGIN
NEW ( Novo_Nodo);
Novo_Nodo^:= Reg;
Novo_Nodo^.Ant := NIL;
Novo_Nodo^.Prox := Raiz;
Raiz^.Ant:= Novo_Nodo;
Raiz := Novo_Nodo;
END.
Exemplo 3: Aproveitando a lista criada no Exemplo anterior, crie uma sub-Rotina que recebendo
como parâmetro as informações de uma pessoa, acrescente esta pessoa na lista, de forma que a
mesma seja a segunda da lista.
PROCEDURE Segunda_Posição_da_Lista (Var Raiz : Ap_Nodo; Reg:
Nodo);
VAR
Novo_Nodo, Aux : Ap_Nodo;
BEGIN
NEW ( Novo_Nodo);
Novo_Nodo^:= Reg;
Aux := Raiz^.Prox;
Novo_Nodo^.Prox := Aux;
Novo_Nodo^.Ant := Raiz;
Raiz^.Prox := Novo_Nodo;
IF Aux <> NIL THEN
Aux^.Ant := Novo_Nodo;
END.
Exemplo 4: Faça uma sub-Rotina genérica que recebendo como parâmetro as informações de uma
pessoa, acrescente a mesma no final da lista.
PROCEDURE Inclui_Final_da_Lista (Var Raiz : Ap_Nodo; Reg: Nodo);
VAR
Novo_Nodo, Atual : Ap_Nodo;
BEGIN
NEW ( Novo_Nodo);
Novo_Nodo^:= Reg;
Novo_Nodo^.Prox := NIL;
Atual := Raiz;
WHILE Atual^.Prox <> NIL DO
17
Atual := Atual^.Prox;
Atual^.Prox := Novo_Nodo;
Novo_Nodo^.Ant := Atual;
END.
Exemplo 5 : Faça uma sub-Rotina genérica que recebendo como parâmetro as informações de uma
pessoa, acrescente a mesma em uma lista. No Inicio, considere a lista com o valor NIL. As pessoas
serão incluídas sempre no final da lista.
PROCEDURE Inclui_Final_da_Lista (Var Raiz : Ap_Nodo; Reg: Nodo);
VAR
Novo_Nodo, Atual : Ap_Nodo;
BEGIN
NEW ( Novo_Nodo);
Novo_Nodo^:= Reg
Novo_Nodo^.Ant := NIL;
Novo_Nodo^.Prox := NIL;
IF RAIZ = NIL THEN
Raiz := Novo_Nodo
ELSE
BEGIN
Atual := Raiz;
WHILE Atual^.Prox <> NIL DO
Atual := Atual^.Prox;
Atual^.Prox := Novo_Nodo;
Novo_Nodo^.Ant := Atual;
END;
END.
5.3.3 Exercícios:
1. Faça uma sub-Rotinas que elimine o primeiro elemento da lista, se o mesmo existir.
2. Faça uma sub-Rotinas que elimine o segundo elemento da lista, se o mesmo existir.
3. Faça uma sub-Rotina que elimine o último elemento da lista, se o mesmo existir.
4. Faça uma sub-Rotina genérica que elimine um determinado elemento de uma lista. Deverá ser
fornecido o número do elemento a ser eliminado. Pode ser que a lista não contenha este
elemento. Por Exemplo, a lista tem 10 nodos e deseja-se eliminar o nodo de número 11.
5. Faça uma sub-Rotina que permita a inclusão de um elemento na lista em uma determinada
posição. A sub-Rotina deverá receber a lista, a informação e a posição em que a nova informação
será incluída. Caso a posição seja maior que o número de elementos atualmente existentes na lista, a
mesma deverá ser incluída no final. Considere a possibilidade da lista no início estar vazia.
6. Faça uma sub-Rotina para ordenar uma lista de números inteiros em ordem crescente. Antes de
construir a Rotina, faça a definição do tipo da lista: RECORD e o tipo apontador.
7. Aproveitando a lista ordenada no exercício anterior, faça uma sub-Rotina genérica para listar o
conteúdo da lista em ordem crescente.
8. Aproveitando a lista ordenada no exercício anterior, faça uma sub-Rotina genérica para listar o
conteúdo da lista em ordem crescente.
18
9. Faça as definições de tipo necessárias para criar, no futuro, uma estrutura na memória como a que
é representada na figura abaixo:
A
B
NIL
C
D
NIL
...
Z
Obs.: a) Dicionário é um vetor ( de “A” até “Z”) de pointers para uma estrutura duplamente
encadeada onde além dos campos “Prox” e “Ant” , existem mais dois campos STRING os quais
representam a palavra e o seu significado.
b) A lista de palavras que estão ligadas ao índice “A” do vetor, correspondem aquelas
palavras que iniciam com a letra “A”, e assim por diante.
10. Usando a definição feita no exercício anterior, faça uma sub-Rotina para inclusão de uma
palavra e o seu significado no dicionário de palavras. Lembre-se que a palavra e o seu significado
não devem ser incluídas em qualquer lista de forma aleatória, a inclusão dever ser feita somente na
lista cujo índice do vetor corresponde à primeira letra da palavra. Desta forma, caso a palavra, fosse
“Cavalo”, esta palavra, junto com o seu significado, deveriam ser incluídos na lista existente no
índice “C” do vetor.
11. Utilizando a agenda criada anteriormente, acrescente a possibilidade de navegaçäo (para frente e
para traz) na rotina de pesquisa.
5.4 Filas
5.4.1 Definiçäo
Uma fila é uma lista linear de informaçäo que é acessada na seguinte ordem, o “primeiro que
entra, primeiro que sai” (FIFO). Uma fila näo permite acesso a um elemento que náo seja o
primeiro.
5.4.2 Aplicaçäo
Normalmente as filas säo utilizadas na administraçäo de recursos compartilhados, impondo
uma prioridade por ordem de chegada. Um bom exemplo säo as filas de impressäo, onde, cada
documento espera sua vez para ser impresso.
19
5.4.3 Operaçöes Básicas (Inclusäo e Exclusäo)
Existem, basicamente, duas operaçöes básicas a serem implementadas na filas : adicionar e
remover. É comum a utilizaçäo de um ponteiro para o início e outro para o fim da fim, facilitando
assim as operaçöes.
Adicionar - procedure adiciona (var inicio : ponteiro ; info : InfoType);
Remover - function remove (var inicio : ponteiro) : InfoType;
5.5 Pilhas
5.5.1 Definiçäo
Análogo à estrutura fila, a estrutura pilha também pré-define a posiçäo de inserçäo e remoçäo
dos elementos, sendo que, a estratágia é “último que entra, primeiro que sai” (LIFO)
5.5.2 Aplicaçäo
Um bom exemplo da apliçäo das pilhas é a gerencia das chamadas as sub-rotinas utilizadas
pela maioria dos compiladores das linguagens de programaçäo.
5.5.3 Operaçöes Básicas (Inclusäo e Exclusäo)
Por razöes históricas, as duas operaçöes primárias de pilha - inserçäo e retirada - säo
normalmente chamadas de push e pop, respectivamente. Assim para implementar uma pilha säo
necessärias duas funçöes :
PUSH - coloca um elemento no topo da pilha
procedure push (var inicio : ponteiro; info : InfoType);
POP - retira um elemento do topo da pila
function pop (var inicio : ponteiro) : InfoType;
6. Deck
6.1 Definiçäo
Esta estrutura de dados é uma uniäo das pilhas e filas, ou seja, só é permitido, manipular os
elementos das extremidades.
6.2 Aplicaçäo
6.3 Operaçöes Básicas (Inclusäo e Exclusäo)
Pode-se inserir e retirar no início e no fim.
7. Hash
7.1 Definiçäo
A estrutura de dados HASH é largamente utilizada para organizaçäo dos arquivos em discos
nos banco de dados, veremos aqui, uma particularidade do HASH utilizada em memória para
melhorar o tempo de busca de elementos armazenados em listas encadeadas.
A idéia básica é criar uma série de sub-listas no lugar de uma única lista maior. A partir da
aplicaçäo de uma determinada funçäo (chamada funçäo de hashing) sobre aa chave de busca do
elemento, decide-se em qual das sub-listas o elemento deve ser ou estar armazenado. Procede-se,
20
entäo, uma busca na sub-lista determinada. Portanto, ao invés de realizar a busca em toda a lista,
faz-se uma busca num subconjunto da lista.
Assim, consegue-se uma busca eficiente, embora os elementos näo fiquem dispostos
ordenadamente, o hash pemite uma melhora na eficiência da localizaçäo idividual dos elemento em
relaçäo as listas.
A questäo principal é escolher uma funçäo de hashing adequada para garantir uma distribuiçäo
uniforme dos elementos nas sub-listas, pois existe uma variedade enorme nas funçöes de hashing.
Os ponteiros iniciais de cada sub-lista säo dispostos num vetor. O número de sub-listas, isto é,
a dimensäo deste vetor, define o tamanho da chamada tabela de hash.
A forma mais comum da funçäo hashing é a aplicaçäo, no campo chave de ordenaçäo, da
funçäo módulo pelo tamanho da hash table e o resultado desta operaçäo indica qual a sub-lista do
elemento. Caso o campo chave de ordenaçäo näo seja numerico, pode-se utilizar artifícios para
transformá-lo em um campo numeriro e, entäo, aplicar a funçäo hashing.
7.2 Aplicaçäo
Como vimos, o hash é utilizado para buscar uma melhor eficiência na busca de elementos.
Este tipo de hash em memória é muito utilizado nas implementaçöes das tabelas de símbolos dos
compiladores das linguagens de programaçäo.
7.3 Operaçöes Básicas (Criaçäo, Inclusäo, Pesquisa, Alteraçäo e Exclusäo)
8. Ávores
8.1 Definiçäo
Ávores säo estruturas de dados essencialmente dinâmicas, permitindo a inserçäo, pesquisa e
destruiçäo de elementos.
Árvores trazem, implicitamente, a idéia de hierarquia, por isso säo estruturas de dados muito
utilizadas em gerenciamento de arquivos e validaçäo de expressöes.
Uma árvore pode ser definida de várias formas. Talvez, a maneira mais natural é definí-las
recursivamente. Assim, uma árvore é composta por um conjunto de nós. Existe um nó denominado
raiz, que contém zero ou mais sub-árvores e cada sub-árvore pode ser considerada uma árvore.
DESENHO ÁRVORE GENÉRICA (liastas de filhos):
Estrutura do nó (com grau pré-definido e com grau inderterminado)
Nomenclatura :
Raiz - é o nó de mais alto nível da árvore (primeiro nó da árvore).
Nível - o número de nós que vai da raiz até um determinado nó.
Grau - o número de sub-árvores de um nó
Folha - nó com grau igual a zero
Altura - nível mais alto da árvore
Pai - a raiz de uma sub-árvore é pai das raizes de suas sub-árvores
Filho - os nós raizes de uma sub-arvores é filho da raiz da árvore
Irmäo - nós raízes das sub-árvores säo irmäos
21
8.2 Árvores Binárias
Säo árvores onde cada nó tem no máximo dois filhos (grau máximo 2). Com isto, obtém-se
uma estrutura apropriada para busca binária. Outra área onde estas estruturas säo muito utilizdas é
na validaçäo de expressöes. Isto porque um operador relaciona apenas um ou dois operandos.
Uma propriedade importante de árvores binárias é que possuem profundidade (altura) bastante
inferior ao núnero de nós. ( comentar inserçäo em ordem)
8.3 Aplicaçäo
A aplicaçäo mais importante das árvores binárias é seu uso em busca binária. A cada nó da
árvore associa-se uma chave que permite a realizaçäo de uma ordenaçäo. A Construçäo da árvore
deve ser de tal forma que na sub-árvore à esquerda de uma dada daiz só existam nós com chaves
menores que a chave da raiz. E a sub-árvore à direita só pode conter nós com chaves maiores que a
da raiz.
Com esta estruturaçäo, a busca de um determinado nó na árvore torna-se trivial, através do
uso da recursidade.
22
8.4 Operaçöes Básicas (Inclusäo, Pesquisa, Alteraçäo, Exclusäo, transformaçäo e
Caminhamentos)
Definiçäo do nó
type
ponteiro = ^no;
no = record
dado : byte;
dir,
esq : ponteiro;
end;
Inclusäo
function Pesquise( var raiz : ponteiro; dadoaux : byte) : ponteiro;
begin
if raiz = nil
then Pesquise := nil
else
begin
if raiz^.dado = dadoaux
then Pesquise := raiz
else
begin
if raiz^.dado < dadoaux
then pesquise := pesquise(raiz^.dir,dadoaux)
else pesquise:= pesquise(raiz^.esq,dadoaux)
end;
end;
end;
procedure InsereArvore( var raiz : ponteiro; dadoaux : byte);
begin
if raiz = nil
then
begin
new(raiz);
raiz^.dado:= dadoaux;
raiz^.esq := nil;
raiz^.dir := nil;
end
else
begin
if dadoaux < raiz^.dado then InsereArvore(raiz^.esq,dadoaux);
if dadoaux > raiz^.dado then InsereArvore(raiz^.dir,dadoaux)
end;
end;
23
Alteraçäo - efetua-se uma pesquisa e em seguida faz-se a alteraçäo
Exclusäo - Para a remoçäo de um nó de uma árvore deve-se levar em consideraçäo que seus filhos
devem continuar na árvore e esta deverá continuar ordenada (menor a esquerda maior a direita). E
entäo caímos em três possibilidades que devem ser tratadas separadamentes, afim de manter o
estrutura da árvore binária. Sendo elas :
1. Quando o nó a ser excluído näo contenha filhos
2. Quando o nó a ser excluído contenha somente um dos filhos
3. Quando o nó a ser excluído contenha os dois filhos
procedure Substitui( raiz : ponteiro; var sucessor : ponteiro);
var ptr : ponteiro;
begin
if sucessor^.esq = nil
then
begin
raiz^.dado := sucessor^.dado;
ptr := sucessor;
sucessor := sucessor^.dir;
dispose(ptr);
end
else
Substitui(raiz,sucessor^.esq);
end;
24
procedure RemoveRaiz(var raiz : ponteiro; dadoaux : byte);
var ptr : ponteiro;
begin
if raiz <> nil then
begin
if raiz^.dado = dadoaux
then
begin
if raiz^.esq = nil
then
begin
ptr := raiz;
raiz := raiz^.dir;
dispose(ptr);
end
else
begin
if raiz^.dir = nil
then
begin
ptr := raiz;
raiz := raiz^.esq;
dispose(ptr);
end
else
Substitui(raiz,raiz^.dir);
end;
end
else if raiz^.dado < dadoaux
then RemoveRaiz(raiz^.dir,dado)
else RemoveRaiz(raiz^.esq,dado);
end;
end;
25
Download