Вы находитесь на странице: 1из 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 }
ptReal: ^real; {ponteiro para uma variável
real}
1
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.
2
Alocação de memória

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

3
Alocação de memória

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

4
Alocação de memória

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

5
Alocação de memória

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

6
Alocação de memória

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

7
Alocação de memória

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

8
Alocação de memória

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

9
Alocação de memória
5
program soma;
var
S,A,B: integer;
PtS,PtA,PtB: ^integer;
begin
A := 2;
B := 3;
PtA := @A; PtA PtB PtS
PtB := @B;
PtS := @S;
PtS^ := PtA^ + PtB^;
Writeln('Resultado: ',PtS^);
end.
A 2 B 3 S 5

10
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.
11
Alocação de memória

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

12
Alocação de memória

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

13
Alocação de memória

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

14
Alocação de memória
Bom Dia!
type
Str18 = string[18];
var
P: ^Str18;
begin
New(P); P
P^ := 'Bom dia!';
Writeln (P^)
→ Dispose(P);
end.
Bom Dia!

15
Alocação de memória

type
Str18 = string[18];
var
P: ^Str18;
begin
New(P); 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...

Um 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

17
Alocação de memória

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

18
Alocação de memória

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

19
Alocação de memória

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

20
Alocação de memória

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

21
Alocação de memória

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

22
Alocação de memória

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

23
Alocação de memória
5
var
p,q,r: ^integer;
begin
new(p);
p^ := 5;
new(q);
q:= p; p q r
r := p; {ou q}
writeln(p^);{ou q^ ou r^ }
→ dispose(q);{ou p ou r }
: 5

24
Alocação de memória

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

25
Alocação de memória
ATENÇÃO: observe que a partir de q:=p;,
perdeu-se o acesso à variável criada com
var new(q)...
p,q,r:Portanto,
^integer;o manuseio de ponteiros
begin exige cuidado!
new(p);
p^ := 5;
new(q);
q:= p; p q r
r := p; {ou q}
writeln(p^);{ou q^ ou r^ }
dispose(q);{ou p ou r }
→ :

26
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
...
• Empregar seqüências de células (nós) que
contêm dois elementos: um valor e um
ponteiro para o próximo nó.
p

... /
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; e/ou...
- quando se desejar maior agilidade nas
inclusões ou exclusões de novos
elementos.

28
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
• Lista vazia;
• Um inteiro seguido de uma lista de
inteiros.

Lista vazia Um inteiro seguido de uma


lista de inteiros...
/ p p

4 7 1 9 /
29
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
O ponteiro contido no
• Lista vazia;
primeiro nó aponta para a lista formada
pelos demais
• Um inteiro seguido nós lista de
de uma
inteiros.

Lista vazia Um inteiro seguido de uma


lista de inteiros...
/ p p

4 7 1 9 /
30
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
OBS: para se ter acesso aos elementos da
lista vazia;
• Lista é necessário que haja sempre uma
variável apontando para a “cabeça” da
• Um inteiro seguido de uma lista de
lista...
inteiros.

Lista vazia Um inteiro seguido de uma


lista de inteiros...
/ p p

4 7 1 9 /
31
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
...a partir de cada nó, pode-se ter
• Lista vazia;acesso ao seguinte.
• UmAssim, pode-se
inteiro seguidopercorrer
de umaa lista
lista toda.
de
inteiros.

Lista vazia Um inteiro seguido de uma


lista de inteiros...
/ p p

4 7 1 9 /
32
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
Quando a lista estiver vazia o ponteiro que
• Lista vazia;
deveria apontar o primeiro elemento,
guarda
• Um inteiro o valor
seguido / ). de
nil ( lista
de uma
inteiros.

Lista vazia Um inteiro seguido de uma


lista de inteiros...
/ p p

4 7 1 9 /
33
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;

34
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;

35
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.
36
Definição (recursiva)
OBS: no início de umdo
da execução nó:
programa só
há ponteiros (p,q) para nós. Estes poderão,
type dinamicamente, ser empregados
tDado = integer; { ou real, char, etc.}
para se construir uma lista.
tPtNo = ^tNo;
tNo = record
Dado:tDado;
Prox :tPtNo;
end;
var
p,q: tPtNo;

37
Exemplo de uso: criação de uma lista com dois
elementos:
var
p,q: tPtNo;
begin
new(p);
p^.Dado
p^.Dado := 7;
acesso ao acesso ao
new(q);
objeto apontado campo
q^.Dado := 3;
por p específico
p^.Prox := q;
q^.Prox := nil;
:

38
Exemplo de uso: criação de uma lista com dois
elementos:
var
p,q: tPtNo;
begin
new(p);
p^.Prox
p^.Dado := 7;
acesso ao acesso ao
new(q);
objeto apontado campo
q^.Dado := 3;
por p específico
p^.Prox := q;
q^.Prox := nil;
:

39
Alocação de memória

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

40
Alocação de memória

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

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

41
Alocação de memória

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

42
Alocação de memória

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

43
Alocação de memória

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

44
Alocação de memória

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

45
Alocação de memória

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

46
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 /

47
Alocação de memória

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

7 3 /

48
Alocação de memória

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

7 3 /

49
Alocação de memória

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

7 3 /

50
Alocação de memória

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

7 3 /

51
Alocação de memória

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

7 3 /

52
Alocação de memória

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

7 3 /

53
Alocação de memória

OBS: por conveniência, representamos


:esquematicamente os nós lado a lado.
Entretanto, as suas localização no heap
new(q);
podem
q^.Dado := 2;ser bastante dispersas...
q^.Prox := p^.Prox; p q
p^.Prox := q; /
q := nil;
→ :

7 2 3 /

54
Representação
p
esquemática “ideal”
q
p q

...
3
/
7 2 3 /
h
e
7 a
p
2

Uma possível
.
disposição física
.
...
55
Dúvidas freqüentes:
1) sempre que precisar de um ponteiro, preciso
criá-lo, com “new”?

56
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.

57
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á.

58
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.

59
Dúvidas freqüentes:
Caso seja executado o código abaixo, p. ex...

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

p q

7 3 / 60
Dúvidas freqüentes:
Caso seja executado o código abaixo, p. ex...

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 / 61
Dúvidas freqüentes:
Caso seja executado o código abaixo, p. ex...

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

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


para ele. p q
b) perdeu-se esse elemento...

7 3 / 62
Dúvidas freqüentes:
2) ao encerrar um módulo, devo desalocar os
ponteiros, empregando ”dispose”?

63
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.

64
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.

65
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?

66
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.

67
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.

68
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?

69
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).

70
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.
71
Dúvidas freqüentes:
Atente bem:
Variáveis globais: seu tempo de vida é o
intervalo de tempo de execução do
programa.

72
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.

73
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.

74
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

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

p
/ p
... /

76
Para lista vazia: Alocação de memória

V
: 5
→ ...
...
... p

77
Para lista vazia: Alocação de memória

V
: 5
→ ...?
...
... criar novo nó p

78
Para lista vazia: Alocação de memória

V
: 5
→ new(p);
...
... p

79
Para lista vazia: Alocação de memória

V
: 5
new(p);
→ ...
... p

80
Para lista vazia: Alocação de memória

V
: 5
new(p);
→ ...?
... p
guardar o
valor de V

81
Para lista vazia: Alocação de memória

V
: 5
new(p);
→ p^.Dado:=V;
... p

82
Para lista vazia: Alocação de memória

V
: 5
new(p);
p^.Dado:=V;
→ ... p

83
Para lista vazia: Alocação de memória

V
: 5
new(p);
p^.Dado:=V;
→ ...? p
caracterizar
último nó

84
Para lista vazia: Alocação de memória

V
: 5
new(p);
p^.Dado:=V;
→ p^.Prox:=nil; p

85
Para lista vazia: Alocação de memória

V
: 5
new(p);
p^.Dado:=V;
p^.Prox:=nil; p

5 /

86
Para lista não vazia:

4 7 1 /

87
Para lista não vazia:

p q

4 7 1 /

Condição facilitadora:
fazer com que um ponteiro auxiliar
aponte para o último nó...
88
Alocação de memória

V
: 5
→ q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
p q r
...
...
...
...

7 2 3 /

89
Alocação de memória

V
: 5
q:= p;
→ while q^.Prox <> nil do
q:=q^.Prox;
p q r
...
...
...
...

7 2 3 /

90
Alocação de memória

V
: 5
q:= p;
while q^.Prox <> nil do
→ q:=q^.Prox;
p q r
...
...
...
...

7 2 3 /

91
Alocação de memória

V
: 5
q:= p;
→ while q^.Prox <> nil do
q:=q^.Prox;
p q r
...
...
...
...

7 2 3 /

92
Alocação de memória

V
: 5
q:= p;
while q^.Prox <> nil do
→ q:=q^.Prox;
p q r
...
...
...
...

7 2 3 /

93
Alocação de memória

V
: 5
q:= p;
→ while q^.Prox <> nil do
q:=q^.Prox;
p q r
...
...
...
...

7 2 3 /

94
Alocação de memória

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

7 2 3 /

95
Alocação de memória

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

7 2 3 /

96
Alocação de memória

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

7 2 3 /

97
Alocação de memória

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

7 2 3 /

98
Alocação de memória

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

7 2 3 /

99
Alocação de memória

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

7 2 3 / 5

100
Alocação de memória

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

101
Alocação de memória

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

7 2 3 / 5

102
Alocação de memória

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

7 2 3 / 5 /

103
Alocação de memória

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

ligar nós 7 2 3 / 5 /

104
Alocação de memória

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

7 2 3 / 5 /

105
Alocação de memória

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

7 2 3 5 /

106
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;
107
Juntando as duas situações...
{lista vazia}
new(p);
p^.Dado:=V;
p^.Prox:=nil;
observe as
semelhanças...

{lista não vazia}


while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
108
Juntando as duas situações...
{lista vazia}
new(p);
p^.Dado:=V;
p^.Prox:=nil;
observe as
semelhanças...

{lista não vazia}


while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
109
Juntando as duas situações...
{lista vazia}
new(p);
p^.Dado:=V;
p^.Prox:=nil;
observe as
semelhanças...

{lista não vazia}


while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
110
Juntando as duas situações...
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.

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...

/ ... /

113
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...

/ ... /

114
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...

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

115
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ó
posterior..
p .
não há nó
anterior...
/ ... /

116
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;
p

/ ... /

117
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...
p

/ ... /

118
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;
end; 120
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.
121
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...

122
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);
123
Orientações...

c) procure identificar co ndiçõe s


fa ci li tadoras para a solução de um
problema.
Por exemplo, para excluir o enésimo nó,
será necessário um ponteiro auxiliar
apontando para ele.
p q

4 7 ... 3 8 1 /
124
Orientações...

c) procure identificar co ndiçõe s


fa ci li tadoras para a solução de um
problema.
Por exemplo, para excluir o enésimo nó,
...mas isso
será necessário um ponteiro auxiliar será
apontando para ele. suficiente??

p q

4 7 ... 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 q

4 7 ... 3 8 1 /
126
Orientações...

Portanto a condição facilitadora pede também


um ponteiro para o nó anterior...

p r q

4 7 ... 3 8 1 /
127
Orientações...

Portanto a condição facilitadora pede também


um ponteiro para o nó anterior...

Agora ficou
simples...

p r q

4 7 ... 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...

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

130
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.
131

Вам также может понравиться