Você está na página 1de 131

Ponteiros em Pascal

Variáveis ponteiros são aquelas que guardam o endereço de outra, possibi- litando o acesso a seu conteúdo.

Declaração em Pascal:

var ptInt: ^integer; {ponteiro para uma variável inteira }

{ponteiro para uma variável real}

ptReal: ^real;

Operador @ Operador unário que retorna o endereço de uma variável

program soma; var

S,A,B:integer; PtS,PtA,PtB : ^integer; begin readln(A,B); PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; writeln('Resultado: ',PtS^);

end.

Alocação de memória

program soma; var

S,A,B: integer; PtS,PtA,PtB: ^integer; begin

A := 2;

B := 3;

PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end.

PtA PtB PtS A B S
PtA
PtB
PtS
A
B S

Alocação de memória

program soma; var

S,A,B: integer; PtS,PtA,PtB: ^integer; begin

A := 2;

B := 3;

PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end.

PtA PtB PtS A 2 B S
PtA
PtB
PtS
A 2
B S

Alocação de memória

program soma; var

S,A,B: integer; PtS,PtA,PtB: ^integer; begin

A := 2;

B := 3;

PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end.

PtA PtB PtS A 2 B 3 S
PtA
PtB
PtS
A 2
B 3
S

Alocação de memória

program soma; var

S,A,B: integer; PtS,PtA,PtB: ^integer; begin

A := 2;

B := 3;

PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end.

PtA PtB PtS A 2 B 3 S
PtA
PtB
PtS
A 2
B 3
S

Alocação de memória

program soma; var

S,A,B: integer; PtS,PtA,PtB: ^integer; begin

A := 2;

B := 3;

PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end.

PtA PtB PtS A 2 B 3 S
PtA
PtB
PtS
A 2
B 3
S

Alocação de memória

program soma; var

S,A,B: integer; PtS,PtA,PtB: ^integer; begin

A := 2;

B := 3;

PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end.

PtA PtB PtS A 2 B 3 S
PtA
PtB
PtS
A 2
B 3
S

Alocação de memória

program soma; var

S,A,B: integer; PtS,PtA,PtB: ^integer; begin

A := 2;

B := 3;

PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end.

PtA PtB PtS A 2 B 3 S 5
PtA
PtB
PtS
A 2
B 3
S
5

Alocação de memória

5

PtA PtB PtS A 2 B 3 S 5
PtA
PtB
PtS
A 2
B
3 S
5
program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA
program soma;
var
S,A,B: integer;
PtS,PtA,PtB: ^integer;
begin
A := 2;
B := 3;
PtA := @A;
PtB := @B;
PtS := @S;
PtS^ := PtA^ + PtB^;
Writeln('Resultado: ',PtS^);
end.

procedure New( )

Cria dinamicamente (em tempo de execução) uma nova variável e faz uma variável ponteiro apontar para ela.

type Str18 = string[18];

var

P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.

Alocação de memória

type Str18 = string[18];

var

P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.

P
P

Alocação de memória

type Str18 = string[18];

var

P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.

P
P

Alocação de memória

type Str18 = string[18];

var

P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.

P Bom Dia!
P
Bom Dia!

Alocação de memória

Bom Dia

!

P Bom Dia!
P
Bom Dia!
type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^)
type
Str18 = string[18];
var
P: ^Str18;
begin
New(P);
P^ := 'Bom dia!';
Writeln (P^)
Dispose(P);
end.

Alocação de memória

P
P

type Str18 = string[18];

var

P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.

OBS: a procedure Dispose libera uma variável criada

dinamicamente, para que o SO possa reutilizar o espaço de memória correspondente.

16

Um ponteiro recebendo o valor de um outro

U m ponteiro recebe o valor de um outro através do comando de atribuição Ex: q:= p;

Quando isso acontece, ele passa a apontar para o mesmo objeto que o outro aponta

Alocação de memória

var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r }

:

p q r
p
q
r

Alocação de memória

var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r }

:

p q r
p
q
r

Alocação de memória

var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r }

:

p q r 5
p
q
r
5

Alocação de memória

var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r }

:

p q r 5
p
q
r
5

Alocação de memória

var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r }

:

p q r 5
p
q
r
5

Alocação de memória

var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r }

:

p q r 5
p
q
r
5

Alocação de memória

5

p q r 5
p
q
r
5
var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou
var
p,q,r: ^integer;
begin
new(p);
p^ := 5;
new(q);
q:= p;
r := p; {ou q}
writeln(p^);{ou q^ ou r^ }
dispose(q);{ou p ou r }
:

Alocação de memória

var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r }

:

p q r
p
q
r

Alocação de memória ATENÇÃO: observe que a partir de q:=p;,

var perdeu-se o acesso à variável criada com new(q) Portanto, o manuseio de ponteiros begin
var
perdeu-se o acesso à variável criada com
new(q)
Portanto, o manuseio
de ponteiros
begin
exige cuidado!
p^ := 5;
new(q);
q:= p;
r := p; {ou q}
writeln(p^);{ou q^ ou r^ }
dispose(q);{ou p ou r }
p
q
r
:

Listas lineares

Em várias situações em programação temos que lidar com listas de elementos cujo tamanho exato é desconhecido. Estratégias:

• Empregar um agregado homogêneo (array) superdimensionado.

1 2 3 N-1 N
1
2
3
N-1 N

• Empregar seqüências de células (nós) que contêm dois elementos: um valor e um

ponteiro para

o próximo nó.

p

Empregar seqüências de células (nós) que contêm dois elementos: um valor e um ponteiro para o
Empregar seqüências de células (nós) que contêm dois elementos: um valor e um ponteiro para o
Empregar seqüências de células (nós) que contêm dois elementos: um valor e um ponteiro para o
Empregar seqüências de células (nós) que contêm dois elementos: um valor e um ponteiro para o
/
/

27

Quando adotar uma ou outra solução?

Agregado homogêneo: quando pudermos determinar com segurança o tamanho máximo.

Listas encadeada:

- quando for difícil estimar o tamanho

máximo com segurança;

- quando se desejar maior agilidade nas inclusões ou exclusões de novos elementos.

e/ou

Lista: uma estrutura recursiva:

Ex: definição de uma lista de inteiros:

• Lista vazia;

• Um inteiro seguido de uma lista de inteiros.

Lista vazia

/
/

p

Um inteiro seguido de uma lista de inteiros

p 4 7 1 9 /
p
4
7
1
9
/

Lista: uma estrutura recursiva:

O ponteiro contido no

primeiro nó aponta para a lista formada

pelos demais nós

Ex: definição de uma lista de inteiros:

Lista vazia

/
/

p

Um inteiro seguido de uma lista de inteiros

p 4 7 1 9 /
p
4
7
1
9
/

30

Lista: uma estrutura recursiva:

OBS: para se ter acesso aos elementos da

lista é necessário que haja sempre uma

variável apontando para a “cabeça” da

lista

Ex: definição de uma lista de inteiros:

Lista vazia

/
/

p

Um inteiro seguido de uma lista de inteiros

p 4 7 1 9 /
p
4
7
1
9
/

Lista: uma estrutura recursiva:

a partir de cada nó, pode-se ter

acesso ao seguinte.

Assim, pode-se percorrer a lista toda.

Ex: definição de uma lista de inteiros:

Lista vazia

/
/

p

Um inteiro seguido de uma lista de inteiros

p 4 7 1 9 /
p
4
7
1
9
/

Lista: uma estrutura recursiva:

Quando a lista estiver vazia o ponteiro que

deveria apontar o primeiro elemento,

guarda o valor nil ( / ).

Ex: definição de uma lista de inteiros:

Lista vazia

/
/

p

Um inteiro seguido de uma lista de inteiros

p 4 7 1 9 /
p
4
7
1
9
/

Definição (recursiva) de um nó:

type tDado = integer; { ou real, char, etc.} tPtNo = ^tNo; tNo = record Dado:tDado; Prox :tPtNo; end;

var

p,q: tPtNo;

Definição (recursiva) de um nó:

type tDado = integer; { ou real, char, etc.} tPtNo = ^tNo; tNo = record Dado:tDado; Prox :tPtNo; end;

var

p,q: tPtNo;

Semanticamente, uma definição semelhante seria

type tDado = integer; { ou real, char, etc.} tNo = record Dado:tDado; Prox :^tNo; end;

var

p,q: tPtNo;

Contudo, as regras de Pascal exigem a definição na forma anteriormente exposta.

OBS: no início da execução do programa só

há ponteiros (p,q) para nós. Estes poderão,

dinamicamente, ser empregados

para se construir uma lista.

type

tPtNo = ^tNo; tNo = record Dado:tDado; Prox :tPtNo; end;

var

p,q: tPtNo;
p,q: tPtNo;

Exemplo de uso: criação de uma lista com dois elementos:

var

p,q: tPtNo; begin new(p); p^.Dado := 7;

new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil;

:

p^.Dado

q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p^.Dado acesso ao acesso ao campo
q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p^.Dado acesso ao acesso ao campo

acesso ao

acesso ao campo específico

objeto apontado

por p

Exemplo de uso: criação de uma lista com dois elementos:

var

p,q: tPtNo; begin new(p); p^.Dado := 7;

new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil;

:

p^.Prox

q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p^.Prox acesso ao acesso ao campo
q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p^.Prox acesso ao acesso ao campo

acesso ao

acesso ao campo específico

objeto apontado

por p

Alocação de memória

var

p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q;

q^.Prox := nil;

:

p q
p
q

Alocação de memória

var

p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q;

q^.Prox := nil;

:

p q
p
q

Alocação de memória

var

p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q;

q^.Prox := nil;

:

p q 7
p
q
7

Alocação de memória

var

p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q;

q^.Prox := nil;

:

p q 7
p
q
7

Alocação de memória

var

p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q;

q^.Prox := nil;

:

p q 7 3
p
q
7
3

Alocação de memória

var

p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q;

q^.Prox := nil;

:

p q 7 3
p
q
7
3

Alocação de memória

var

p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q;

q^.Prox := nil;

:

p q 7 3 /
p
q
7
3
/

Exemplo 2: dada a lista abaixo, inserir um novo nó entre os dois existentes e armazenar nele o valor 2.

:

new(q);

p q

q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; : 7 3
q^.Dado := 2;
q^.Prox := p^.Prox;
p^.Prox := q;
q := nil;
:
7
3
/

Alocação de memória

:

new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q;

q := nil;

:

p q 7 3 /
p
q
7
3
/

Alocação de memória

:

new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q;

q := nil;

:

p q 7 3 /
p
q
7
3
/

Alocação de memória

:

new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q;

q := nil;

:

p q 2 7 3 /
p
q
2
7
3
/

Alocação de memória

:

new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q;

q := nil;

:

p q 2 7 3 /
p
q
2
7
3
/

Alocação de memória

:

new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q;

q := nil;

:

p q 2 7 3 /
p
q
2
7
3
/

Alocação de memória

:

new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q;

q := nil;

:

p q / 2 7 3 /
p
q
/
2
7
3
/

Alocação de memória

OBS: por conveniência, representamos esquematicamente os nós lado a lado. Entretanto, as suas localização no
OBS: por conveniência, representamos
esquematicamente os nós
lado a lado.
Entretanto, as suas localização no h eap
podem ser bastante dispersas
q^.Prox := p^.Prox;
p^.Prox := q;
p
q
/
q := nil;
:
7
2
3
/
p q 3 / 7 2
p
q
3
/
7
2

Representação esquemática “ideal”

p q

7 2 3 /
7
2
3
/
p q 3 / 7 2 Representação esquemática “ideal” p q 7 2 3 / Uma

Uma possível disposição física

h

e

a

p

55

Dúvidas freqüentes:

1) sempre que precisar de um ponteiro, preciso criá-lo, com “new”?

Dúvidas freqüentes:

1) sempre que precisar de um ponteiro, preciso criá-lo, com “new”?

Não.

>> o simples fato de se declarar o ponteiro (variável global, local ou parâmetro) faz com que o sistema aloque memória para ele.

Dúvidas freqüentes:

1) sempre que precisar de um ponteiro, preciso criá-lo, com “new”?

Não.

>> o simples fato de se declarar o ponteiro (variável global, local ou parâmetro) faz com que o sistema aloque memória para ele.

>> new() deve ser usado para criar um objeto (sem identificação) para o qual o ponteiro usado como argumento apontará.

Dúvidas freqüentes:

1) sempre que precisar de um ponteiro, preciso criá-lo, com “new”?

Não.

>> o simples fato de se declarar o ponteiro (variável global, local ou parâmetro) faz com que o sistema aloque memória para ele.

>> new() deve ser usado para criar um objeto (sem identificação) para o qual o ponteiro usado como argumento apontará. >> o tipo do objeto criado dependerá do tipo de ponteiro.

Dúvidas freqüentes:

Caso seja executado o código abaixo, p. ex

freqüentes: Caso seja executado o código abaixo, p. ex new(q); q := p; {apontar para o

new(q); q := p; {apontar para o primeiro elemento da lista}

p q

7 3 /
7
3
/

60

Dúvidas freqüentes:

Caso seja executado o código abaixo, p. ex

freqüentes: Caso seja executado o código abaixo, p. ex new(q); q := p; {apontar para o

new(q); q := p; {apontar para o primeiro elemento da lista}

a) criou-se um elemento, fazendo-se q apontar

para ele.

p q

7 3 /
7
3
/

61

Dúvidas freqüentes:

Caso seja executado o código abaixo, p. ex

freqüentes: Caso seja executado o código abaixo, p. ex new(q); q := p; {apontar para o

new(q); q := p; {apontar para o primeiro elemento da lista}

a) criou-se um elemento, fazendo-se q apontar

para ele.

b) perdeu-se esse elemento

p q

7 3 /
7
3
/

62

Dúvidas freqüentes:

2) ao encerrar um módulo, devo desalocar os ponteiros, empregando ”dispose”?

Dúvidas freqüentes:

2) ao encerrar um módulo, devo desalocar os ponteiros, empregando ”dispose”?

Não.

>> no encerramento do módulo, todas as variáveis locais e parâmetros (inclusive ponteiros) são desalocados automatica- mente.

Dúvidas freqüentes:

2) ao encerrar um módulo, devo desalocar os ponteiros, empregando ”dispose”?

Não.

>> no encerramento do módulo, todas as variáveis locais e parâmetros (inclusive ponteiros) são desalocados automatica- mente.

>> ao se utilizar dispose(r), é o objeto referenciado por r que será excluído. Não o ponteiro em si.

Dúvidas freqüentes:

3) quando se cria um objeto (comando new) empregando-se um ponteiro, só se pode empregar aquele ponteiro para desalocar aquele objeto?

Dúvidas freqüentes:

3) quando se cria um objeto (comando new) empregando-se um ponteiro, só se pode empregar aquele ponteiro para desalocar aquele objeto?

Não.

>> o nó não “pertence” ao ponteiro que foi empregado na sua criação.

Dúvidas freqüentes:

3) quando se cria um objeto (comando new) empregando-se um ponteiro, só se pode empregar aquele ponteiro para desalocar aquele objeto?

Não.

>> o nó não “pertence” ao ponteiro que foi empregado na sua criação.

>> qualquer ponteiro que esteja apontando para certo objeto pode ser usado para a sua desalocação.

Dúvidas freqüentes:

4) ao empregar-se uma variável local (ponteiro) para alocar um objeto, esse objeto será também local, desaparecendo portanto após a execução daquele módulo?

Dúvidas freqüentes:

4) ao empregar-se uma variável local (ponteiro) para alocar um objeto, esse objeto será também local, desaparecendo portanto após a execução daquele módulo?

Não.

>> o objeto criado é alocado na área de memória denominada heap (área própria para alocação dinâmica).

Dúvidas freqüentes:

4) ao empregar-se uma variável local (ponteiro) para alocar um objeto, esse objeto será também local, desaparecendo portanto após a execução daquele módulo?

Não.

>> o objeto criado é alocado na área de memória denominada heap (área própria para alocação dinâmica).

>> variáveis de heap não são nem globais nem locais.

Dúvidas freqüentes:

Atente bem:

Variáveis globais: seu tempo de vida é o intervalo de tempo de execução do programa.

Dúvidas freqüentes:

Atente bem:

Variáveis globais: seu tempo de vida é o intervalo de tempo de execução do programa.

Variáveis locais: seu tempo de vida é o intervalo de execução do módulo onde foram declaradas.

Dúvidas freqüentes:

Atente bem:

Variáveis globais: seu tempo de vida é o intervalo de tempo de execução do programa.

Variáveis locais: seu tempo de vida é o intervalo de execução do módulo onde foram declaradas.

Variáveis de heap: seu tempo de vida é arbitrário, dependendo de uma criação (new) e da posterior desalocação.

Manuseio de listas encadeadas

Para tratar de forma genérica todas as possí- veis manipulações de uma lista encadeada, é definido um conjunto de rotinas. Exemplos:

• inserir/excluir um elemento no início

• inserir /excluir um elemento no final

• inserir /excluir um elemento na enésima posição

• calcular a soma dos elementos

Exemplo: inserir elemento V no final

Duas situações a se considerar:

Lista vazia

Lista não vazia

/
/

p

Exemplo: inserir elemento V no final Duas situações a se considerar: Lista vazia Lista não vazia

p

Exemplo: inserir elemento V no final Duas situações a se considerar: Lista vazia Lista não vazia
Exemplo: inserir elemento V no final Duas situações a se considerar: Lista vazia Lista não vazia
/
/

Para lista vazia:

:

Alocação de memória V 5 p
Alocação de memória
V
5
p
Para lista vazia: : ? criar novo nó
Para lista vazia:
:
?
criar novo nó
Alocação de memória V 5 p
Alocação de memória
V
5
p

Para lista vazia:

:

new(p);

Alocação de memória V 5 p
Alocação de memória
V
5
p

Para lista vazia:

:

new(p);

Alocação de memória V 5 p
Alocação de memória
V
5
p
Para lista vazia: : new(p); ? guardar o valor de V
Para lista vazia:
:
new(p);
?
guardar o
valor de V
Alocação de memória V 5 p
Alocação de memória
V
5
p

Para lista vazia:

:

new(p);

p^.Dado:=V;

Alocação de memória V 5 p
Alocação de memória
V
5
p

Para lista vazia:

:

new(p);

p^.Dado:=V;

Alocação de memória V 5 p 5
Alocação de memória
V
5
p
5
Para lista vazia: : new(p); p^.Dado:=V; ? caracterizar último nó
Para lista vazia:
:
new(p);
p^.Dado:=V;
?
caracterizar
último nó
Alocação de memória V 5 p 5
Alocação de memória
V
5
p
5

Para lista vazia:

:

new(p);

p^.Dado:=V;

p^.Prox:=nil;

Alocação de memória V 5 p 5
Alocação de memória
V
5
p
5

Para lista vazia:

:

new(p);

p^.Dado:=V;

p^.Prox:=nil;

Alocação de memória

V 5 p 5 /
V
5
p
5
/

Para lista não vazia:

Para lista não vazia: p 4 7 1 / 87

p

4

Para lista não vazia: p 4 7 1 / 87

7

1 /
1 /
Para lista não vazia: p 4 7 1 / 87

Para lista não vazia:

p q 4 7 1 /
p
q
4
7
1
/

Condição facilitadora:

fazer com que um ponteiro auxiliar aponte para o último nó

:

q:= p; while q^.Prox <> nil do q:=q^.Prox;

Alocação de memória

V 5 p q r 7 2 3 /
V
5
p
q
r
7
2
3
/

:

q:= p; while q^.Prox <> nil do q:=q^.Prox;

Alocação de memória

V 5 p q r 7 2 3 /
V
5
p
q
r
7
2
3
/

:

q:= p; while q^.Prox <> nil do q:=q^.Prox;

Alocação de memória

V 5 p q r 7 2 3 /
V
5
p
q
r
7
2
3
/

:

q:= p; while q^.Prox <> nil do q:=q^.Prox;

Alocação de memória

V 5 p q r 7 2 3 /
V
5
p
q
r
7
2
3
/

:

q:= p; while q^.Prox <> nil do q:=q^.Prox;

Alocação de memória

V 5 p q r 7 2 3 /
V
5
p
q
r
7
2
3
/

:

q:= p; while q^.Prox <> nil do q:=q^.Prox;

Alocação de memória

V 5 p q r 7 2 3 /
V
5
p
q
r
7
2
3
/
: q:= p; while q^.Prox <> nil do q:=q^.Prox; ? criar novo nó
:
q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
?
criar novo nó

Alocação de memória

V 5 p q r 7 2 3 /
V
5
p
q
r
7
2
3
/

:

q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r);

Alocação de memória

V 5 p q r 7 2 3 /
V
5
p
q
r
7
2
3
/

:

q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r);

Alocação de memória

V 5 p q r 7 2 3 /
V
5
p
q
r
7
2
3
/
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); ? guardar o valor de
:
q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
?
guardar o
valor de V

Alocação de memória

V 5 p q r 7 2 3 /
V
5
p
q
r
7
2
3
/

:

q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V;

Alocação de memória

V 5 p q r 7 2 3 /
V
5
p
q
r
7
2
3
/

:

q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V;

Alocação de memória

V 5 p q r 7 2 3 / 5
V
5
p
q
r
7
2
3
/
5
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; ? caracterizar último nó
:
q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
?
caracterizar
último nó

Alocação de memória

V 5 p q r 7 2 3 / 5
V
5
p
q
r
7
2
3
/
5

:

q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^Prox:=nil;

Alocação de memória

V 5 p q r 7 2 3 / 5
V
5
p
q
r
7
2
3
/
5

:

q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil;

Alocação de memória

V 5 p q r 7 2 3 / 5 /
V
5
p
q
r
7
2
3
/
5
/
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; ? ligar nós
:
q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
?
ligar nós

Alocação de memória

V 5 p q r 7 2 3 / 5 /
V
5
p
q
r
7
2
3
/
5
/

:

q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r;

Alocação de memória

V 5 p q r 7 2 3 / 5 /
V
5
p
q
r
7
2
3
/
5
/

:

q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r;

Alocação de memória

V 5 p q r 7 2 3 5 /
V
5
p
q
r
7
2
3
5
/

Juntando as duas situações

{lista vazia} new(p); p^.Dado:=V; p^.Prox:=nil;

{lista não vazia} while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r;

Juntando as duas situações

{lista vazia} new(p); p^.Dado:=V; p^.Prox:=nil;

situações {lista vazia} new(p); p^.Dado:=V; p^.Prox:=nil; {lista não vazia} while q^.Prox <> nil do

{lista não vazia} while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r;

while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; observe as semelhanças 108
observe as semelhanças
observe as
semelhanças

Juntando as duas situações

{lista vazia} new(p); p^.Dado:=V; p^.Prox:=nil;

situações {lista vazia} new(p); p^.Dado:=V; p^.Prox:=nil; {lista não vazia} while q^.Prox <> nil do

{lista não vazia} while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r;

while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; observe as semelhanças 109
observe as semelhanças
observe as
semelhanças

Juntando as duas situações

{lista vazia} new(p); p^.Dado:=V; p^.Prox:=nil;

situações {lista vazia} new(p); p^.Dado:=V; p^.Prox:=nil; {lista não vazia} while q^.Prox <> nil do

{lista não vazia} while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r;

while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; observe as semelhanças 110
observe as semelhanças
observe as
semelhanças

Juntando as duas situações

Juntando as duas situações procedure InsereNo(var p: tPtNo; V : tDado); var q,r: tPtNo; begin end;

procedure InsereNo(var p: tPtNo; V : tDado); var q,r: tPtNo; begin

end;

Como existe a possibilidade de p mudar seu conteúdo, ele é passado por referência.
Como existe a possibilidade de p mudar seu
conteúdo, ele é passado por referência.

111

Juntando as duas situações

procedure InsereNo(var p: tPtNo; V : tDado); var q,r: tPtNo; begin new(r); r^.Dado:=V; r^.Prox:=nil; if p = nil then p:= r else begin q:= p; while q^.Prox <> nil do q:=q^.Prox; q^.Prox:=r; end;

end;

112

Listas duplamente encadeadas

Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores

Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores

p

/

/
/
/
/
/
/
/
/
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores

/

Listas duplamente encadeadas

Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores

Portanto, a estrutura do nó deve possuir 2 ponteiros

não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2

p

/

/
/
/
/
/
/
/
/
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2
não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2

/

Listas duplamente encadeadas

Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores

Portanto, a estrutura do nó deve possuir 2 ponteiros

não há nó anterior

p /
p
/

/

Listas duplamente encadeadas

Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores

Portanto, a estrutura do nó deve possuir 2 ponteiros

não há nó anterior

não há nó posterior p . /
não há nó
posterior
p
.
/
/
/

Listas duplamente encadeadas

Estrutura:

tDado = integer; { ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir: tPtNo; end;

var

p,q: tPtNo;

{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:

p

/

/
/
/
/
/
/
/
/
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:
{ ou real, char, etc.} tPtNo = ^tNo; tNo = record Esq: tPtNo Dado: tDado; Dir:

/

Listas duplamente encadeadas

Operações:

Partindo-se das operações com listas de encadeamento simples, basta fazer alguns ajustes.

é necessário considerar que há dois ponteiros

com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros

p

/

/
/
/
/
/
/
/
/
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros
com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros

/

com listas de encadeamento simples, basta fazer alguns ajustes. é necessário considerar que há dois ponteiros

Considere a rotina de inserção no final para encadeamento simples:

procedure InsereNoFinal(var p:tPtNo; V: tDado); var q,r: tPtNo; begin new(r); r^.Dado:=V; r^.Prox:=nil; if p = nil then p:= r else begin q:= p; while q^.Prox <> nil do q:=q^.Prox; q^.Prox:=r; end;

end;

119

ajustes

necessários:

procedure InsereNoFinal(var p:tPtNo; V: tDado); var q,r: tPtNo; begin new(r); r^.Dado:=V; r^.Dir:=nil; if p = nil then begin p:= r; r^.Esq:= nil; end; else begin q:= p; while q^.Dir <> nil do q:=q^.Dir; q^.Dir:=r; r^.Esq := q; end;

Exercícios (encadeamento simples e

duplo):

Construir módulos que façam as seguintes operações:

1- Inserir no início da lista; 2- Excluir o primeiro elemento; 3- Excluir o último elemento; 4- Inserir na enésima posição; 5- Excluir o enésimo nó; 6- Fornecer o tamanho da lista 7- Fornecer a soma dos elementos da lista.

Orientações

1- Sempre pla neje antes de codi fi car . a) faça um esquema visual do problema! -> use lápis e borracha, pois os ponteiros são dinâmicos

Orientações

1- Sempre pla neje antes de codi fi car . a) faça um esquema visual do problema! -> use lápis e borracha, pois os ponteiros são dinâmicos

b) atenção especial à list a de parâme tros :

quais são os parâmetros necessários, seus tipos, mecanismo de passagem (valor ou referência);

Orientações

c) procure identificar co ndiçõe s

fa ci li tadoras

problema. Por exemplo, para excluir o enésimo nó, será necessário um ponteiro auxiliar apontando para ele.

para a solução de um

o enésimo nó, será necessário um ponteiro auxiliar apontando para ele. para a solução de um

p

4

7

7
7
7
7
7
7
7
o enésimo nó, será necessário um ponteiro auxiliar apontando para ele. para a solução de um
o enésimo nó, será necessário um ponteiro auxiliar apontando para ele. para a solução de um
o enésimo nó, será necessário um ponteiro auxiliar apontando para ele. para a solução de um

q

3 8 1 /
3
8
1
/

124

Orientações

c) procure identificar co ndiçõe s

fa ci li tadoras

problema. Por exemplo, para excluir o enésimo nó,

para a solução de um

mas

isso

será

suficiente??

para a solução de um mas isso será suficiente ?? será necessário um ponteiro auxiliar apontando

será necessário um ponteiro auxiliar

apontando para ele.

de um mas isso será suficiente ?? será necessário um ponteiro auxiliar apontando para ele. p
de um mas isso será suficiente ?? será necessário um ponteiro auxiliar apontando para ele. p

p

q

4

7

7
7
7
7
7
7
7
de um mas isso será suficiente ?? será necessário um ponteiro auxiliar apontando para ele. p
de um mas isso será suficiente ?? será necessário um ponteiro auxiliar apontando para ele. p
3 8 1 /
3
8
1
/

125

Orientações

Não. No processo de exclusão, p. ex., do nó que guarda o valor 8, será necessário encadear o anterior com o sucessor

p. ex., do nó que guarda o valor 8, será necessário encadear o anterior com o

p

4

7

7
7
7
7
7
7
7
p. ex., do nó que guarda o valor 8, será necessário encadear o anterior com o
p. ex., do nó que guarda o valor 8, será necessário encadear o anterior com o
p. ex., do nó que guarda o valor 8, será necessário encadear o anterior com o

q

3 8 1 /
3
8
1
/

126

Orientações

Portanto a condição facilitadora pede também

um ponteiro para o nó anterior

Orientações Portanto a condição facilitadora pede também um ponteiro para o nó anterior p 4 7

p

4

7

7
7
7
7
7
7
7
Orientações Portanto a condição facilitadora pede também um ponteiro para o nó anterior p 4 7
Orientações Portanto a condição facilitadora pede também um ponteiro para o nó anterior p 4 7
r
r

q

3 8 1 /
3
8
1
/

127

Orientações

Portanto a condição facilitadora pede também

um ponteiro para o nó anterior

a condição facilitadora pede também um ponteiro para o nó anterior p 4 7 Agora ficou

p

4

7

7
7
7
7
7
7
7
a condição facilitadora pede também um ponteiro para o nó anterior p 4 7 Agora ficou
a condição facilitadora pede também um ponteiro para o nó anterior p 4 7 Agora ficou
Agora ficou simples r q
Agora ficou
simples
r
q
3 8 1 /
3
8
1
/

128

Orientações

a identificação da condição facilitadora

permite a divisão do problema em duas etapas, reduzindo-se a complexidade

Orientações

2 - Primeiramente, procure a solução para o caso mais geral. Depois considere as situações especiais

Orientações

2 - Primeiramente, procure a solução para o caso mais geral. Depois considere as situações especiais

Ex: Inserir na enésima posição: raciocinar para lista não vazia e inserção no meio da lista.

Depois considerar

- e se a lista estiver vazia?

- e se a posição for a primeira (ou a última)?

Quando a solução geral não funcionar para esses

casos, inserir o tratamento especial.